According to the adapter interrupt comes from PMIC GPIO 0, and SCU firmware will take care battery charge/discharge scenario. This patch add adapter interrupt handler, and remove charger relative function.
Signed-off-by: Major Lee <[email protected]> --- intel_mid_battery.c | 147 +++++++++++++++++++++++----------------------------- 1 file changed, 67 insertions(+), 80 deletions(-) --- linux-2.6.37.6.bak/drivers/power/intel_mid_battery.c 2011-04-12 10:00:03.120483277 +0800 +++ linux-2.6.37.6/drivers/power/intel_mid_battery.c 2011-04-18 17:00:09.756836000 +0800 @@ -33,6 +33,7 @@ #include <linux/spi/spi.h> #include <linux/platform_device.h> #include <linux/power_supply.h> +#include <linux/gpio.h> #include <asm/intel_scu_ipc.h> @@ -65,16 +66,6 @@ MODULE_PARM_DESC(debug, "Flag to enable #define PMIC_BATT_ADC_ACCCHRG_MASK (1 << 31) #define PMIC_BATT_ADC_ACCCHRGVAL_MASK 0x7FFFFFFF -/* pmic ipc related */ -#define PMIC_BATT_CHR_IPC_FCHRG_SUBID 0x4 -#define PMIC_BATT_CHR_IPC_TCHRG_SUBID 0x6 - -/* types of battery charging */ -enum batt_charge_type { - BATT_USBOTG_500MA_CHARGE, - BATT_USBOTG_TRICKLE_CHARGE, -}; - /* valid battery events */ enum batt_event { BATT_EVENT_BATOVP_EXCPT, @@ -109,9 +100,11 @@ struct pmic_power_module_info { struct power_supply usb; struct power_supply batt; int irq; /* GPE_ID or IRQ# */ + int adap_irq; struct workqueue_struct *monitor_wqueue; struct delayed_work monitor_battery; struct work_struct handler; + struct work_struct adap_handler; }; static unsigned int delay_time = 2000; /* in ms */ @@ -156,6 +149,9 @@ struct battery_property { #define IPC_CMD_CC_RD 1 /* Read coulomb counter value */ #define IPC_CMD_BATTERY_PROPERTY 2 /* Read Battery property */ +/* PMIC_GPIO_0 for adapter detection */ +#define PMIC_GPIO_0 64 + /** * pmic_scu_ipc_battery_cc_read - read battery cc * @value: battery coulomb counter read @@ -199,18 +195,6 @@ static int pmic_scu_ipc_battery_property } /** - * pmic_scu_ipc_set_charger - set charger - * @charger: charger to select - * - * Switch the charging mode for the SCU - */ - -static int pmic_scu_ipc_set_charger(int charger) -{ - return intel_scu_ipc_simple_command(IPCMSG_BATTERY, charger); -} - -/** * pmic_battery_log_event - log battery events * @event: battery event to be logged * Context: can sleep @@ -494,40 +478,41 @@ static void pmic_battery_monitor(struct } /** - * pmic_battery_set_charger - set battery charger - * @pbi: device info structure - * @chrg: charge mode to set battery charger in - * Context: can sleep + * pmic_adapter_interrupt_handler - pmic adapter interrupt handler + * Context: interrupt context * - * PMIC battery charger needs to be enabled based on the usb charge - * capabilities connected to the platform. + * PMIC adapter interrupt handler which will be called with apapter + * connected or removed condition occurs. */ -static int pmic_battery_set_charger(struct pmic_power_module_info *pbi, - enum batt_charge_type chrg) +static irqreturn_t pmic_adapter_interrupt_handler(int id, void *dev) { - int retval; + struct pmic_power_module_info *pbi = dev; - /* set usblmt bits and chrgcntl register bits appropriately */ - switch (chrg) { - case BATT_USBOTG_500MA_CHARGE: - retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_FCHRG_SUBID); - break; - case BATT_USBOTG_TRICKLE_CHARGE: - retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_TCHRG_SUBID); - break; - default: - dev_warn(pbi->dev, "%s(): out of range usb charger " - "charge detected\n", __func__); - return -EINVAL; - } + schedule_work(&pbi->adap_handler); - if (retval) { - dev_warn(pbi->dev, "%s(): ipc pmic read failed\n", - __func__); - return retval;; - } + return IRQ_HANDLED; +} - return 0; +/** + * pmic_adaptor_handle_intrpt - pmic adapter service interrupt + * @work: work structure + * Context: can sleep + * + * PMIC adapter needs to either update the adapter status as connected + * or removed. + */ +static void pmic_adaptor_handle_intrpt(struct work_struct *work) +{ + struct pmic_power_module_info *pbi = container_of(work, + struct pmic_power_module_info, handler); + int val = gpio_get_value(PMIC_GPIO_0); + + if (val) { + pbi->usb_is_present = PMIC_USB_PRESENT; + } else { + pbi->usb_is_present = PMIC_USB_NOT_PRESENT; + pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN; + } } /** @@ -561,7 +546,6 @@ static void pmic_battery_handle_intrpt(s { struct pmic_power_module_info *pbi = container_of(work, struct pmic_power_module_info, handler); - enum batt_charge_type chrg; u8 r8; if (intel_scu_ipc_ioread8(PMIC_BATT_CHR_SCHRGINT_ADDR, &r8)) { @@ -611,35 +595,6 @@ static void pmic_battery_handle_intrpt(s pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN; return; } - - /* setup battery charging */ - -#if 0 - /* check usb otg power capability and set charger accordingly */ - retval = langwell_udc_maxpower(&power); - if (retval) { - dev_warn(pbi->dev, - "%s(): usb otg power query failed with error code %d\n", - __func__, retval); - return; - } - - if (power >= 500) - chrg = BATT_USBOTG_500MA_CHARGE; - else -#endif - chrg = BATT_USBOTG_TRICKLE_CHARGE; - - /* enable battery charging */ - if (pmic_battery_set_charger(pbi, chrg)) { - dev_warn(pbi->dev, - "%s(): failed to set up battery charging\n", __func__); - return; - } - - dev_dbg(pbi->dev, - "pmic-battery: %s() - setting up battery charger successful\n", - __func__); } /** @@ -667,10 +622,29 @@ static __devinit int probe(int irq, stru pbi->dev = dev; pbi->irq = irq; + + /* It is better passed from platform data */ + retval = gpio_request(PMIC_GPIO_0, "pmic-adap"); + if (retval) { + dev_err(dev, "%s: request gpio fail\n", __func__); + goto gpio_failed; + } + retval = gpio_direction_input(PMIC_GPIO_0); + if (retval) { + dev_err(dev, "%s: set gpio direction fail\n", __func__); + goto gpio_failed; + } + pbi->adap_irq = gpio_to_irq(PMIC_GPIO_0); + if (pbi->adap_irq < 0) { + dev_err(dev, "%s: gpio to irq fail\n", __func__); + goto gpio_failed; + } + dev_set_drvdata(dev, pbi); /* initialize all required framework before enabling interrupts */ INIT_WORK(&pbi->handler, pmic_battery_handle_intrpt); + INIT_WORK(&pbi->adap_handler, pmic_adaptor_handle_intrpt); INIT_DELAYED_WORK(&pbi->monitor_battery, pmic_battery_monitor); pbi->monitor_wqueue = create_singlethread_workqueue(dev_name(dev)); @@ -688,6 +662,14 @@ static __devinit int probe(int irq, stru goto requestirq_failed; } + /* register adaptor interrupt */ + retval = request_irq(pbi->adap_irq, pmic_adapter_interrupt_handler, + IRQ_TYPE_EDGE_BOTH, "pmic-usb", pbi); + if (retval) { + dev_err(dev, "%s: cannot get adaptor irq\n", __func__); + goto requestirq_failed_adap; + } + /* register pmic-batt with power supply subsystem */ pbi->batt.name = "pmic-batt"; pbi->batt.type = POWER_SUPPLY_TYPE_BATTERY; @@ -734,9 +716,13 @@ power_reg_failed_1: power_reg_failed: cancel_rearming_delayed_workqueue(pbi->monitor_wqueue, &pbi->monitor_battery); + free_irq(pbi->adap_irq, pbi); +requestirq_failed_adap: + free_irq(pbi->irq, pbi); requestirq_failed: destroy_workqueue(pbi->monitor_wqueue); wqueue_failed: +gpio_failed: kfree(pbi); return retval; @@ -762,6 +748,7 @@ static int __devexit platform_pmic_batte struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev); free_irq(pbi->irq, pbi); + free_irq(pbi->adap_irq, pbi); cancel_rearming_delayed_workqueue(pbi->monitor_wqueue, &pbi->monitor_battery); destroy_workqueue(pbi->monitor_wqueue);
intel_mid_battery-add-adapter-interrupt-and-remove-charger-function.patch
Description: intel_mid_battery-add-adapter-interrupt-and-remove-charger-function.patch
_______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
