diff options
author | Johan Palsson <johan.palsson@stericsson.com> | 2011-03-16 13:25:10 +0100 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@stericsson.com> | 2011-09-19 15:14:59 +0200 |
commit | 616a7c9fe03dc24ba62830c0b4d1c9e28771174a (patch) | |
tree | 868ddfea1aeb31a751da3109aa39775ebaf0f43d /drivers/power | |
parent | f9afcae44e931ca9ed2a270666e9dfe1d38ea78e (diff) |
power: ab8500_bm: Lower current when charger voltage drops
The charger current optimization loop has been corrected for
when the VBUS voltage collapses
ST-Ericsson Linux next: -
ST-Ericsson ID: ER328139
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: Ie997402e3c0b868212ad59fe242f393ba0721007
Signed-off-by: Johan Palsson <johan.palsson@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/18415
Reviewed-by: Karl KOMIEROWSKI <karl.komierowski@stericsson.com>
Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/ab8500_chargalg.c | 8 | ||||
-rw-r--r-- | drivers/power/ab8500_charger.c | 48 |
2 files changed, 24 insertions, 32 deletions
diff --git a/drivers/power/ab8500_chargalg.c b/drivers/power/ab8500_chargalg.c index f4e4528b15c..788d81aa7cd 100644 --- a/drivers/power/ab8500_chargalg.c +++ b/drivers/power/ab8500_chargalg.c @@ -733,9 +733,11 @@ static enum maxim_ret ab8500_chargalg_chg_curr_maxim(struct ab8500_chargalg *di) delta_i = di->ccm.original_iset - di->batt_data.inst_curr; if (di->events.vbus_collapsed) { - dev_dbg(di->dev, "Charger voltage has collapsed\n"); - if (di->ccm.wait_cnt++ == 0) { + dev_dbg(di->dev, "Charger voltage has collapsed %d\n", + di->ccm.wait_cnt); + if (di->ccm.wait_cnt == 0) { dev_dbg(di->dev, "lowering current\n"); + di->ccm.wait_cnt++; di->ccm.condition_cnt = di->bat->maxi->wait_cycles; di->ccm.max_current = di->ccm.current_iset - di->ccm.test_delta_i; @@ -745,7 +747,7 @@ static enum maxim_ret ab8500_chargalg_chg_curr_maxim(struct ab8500_chargalg *di) } else { dev_dbg(di->dev, "waiting\n"); /* Let's go in here twice before lowering curr again */ - di->ccm.wait_cnt = (di->ccm.wait_cnt + 1) % 4; + di->ccm.wait_cnt = (di->ccm.wait_cnt + 1) % 3; return MAXIM_RET_NOACTION; } } diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 6c0b8af2f7f..47be3e089ff 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -181,13 +181,13 @@ struct ab8500_charger_usb_state { * @usb: Structure that holds the USB charger properties * @charger_wq: Work queue for the IRQs and checking HW state * @check_hw_failure_work: Work for checking HW state + * @check_usbchgnotok_work: Work for checking USB charger not ok status * @kick_wd_work: Work for kicking the charger watchdog in case * of ABB rev 1.* due to the watchog logic bug * @ac_work: Work for checking AC charger connection * @detect_usb_type_work: Work for detecting the USB type connected * @usb_link_status_work: Work for checking the new USB link status * @usb_state_changed_work: Work for checking USB state - * @check_usbchgnotok_work: Work for checking USB charger not ok status * @check_main_thermal_prot_work: * Work for checking Main thermal status * @check_usb_thermal_prot_work: @@ -212,12 +212,12 @@ struct ab8500_charger { struct ab8500_charger_info usb; struct workqueue_struct *charger_wq; struct delayed_work check_hw_failure_work; + struct delayed_work check_usbchgnotok_work; struct delayed_work kick_wd_work; struct work_struct ac_work; struct work_struct detect_usb_type_work; struct work_struct usb_link_status_work; struct work_struct usb_state_changed_work; - struct work_struct check_usbchgnotok_work; struct work_struct check_main_thermal_prot_work; struct work_struct check_usb_thermal_prot_work; struct otg_transceiver *otg; @@ -1528,9 +1528,10 @@ static void ab8500_charger_check_usbchargernotok_work(struct work_struct *work) { int ret; u8 reg_value; + bool prev_status; struct ab8500_charger *di = container_of(work, - struct ab8500_charger, check_usbchgnotok_work); + struct ab8500_charger, check_usbchgnotok_work.work); /* Check if the status bit for usbchargernotok is still active */ ret = abx500_get_register_interruptible(di->dev, @@ -1539,14 +1540,20 @@ static void ab8500_charger_check_usbchargernotok_work(struct work_struct *work) dev_err(di->dev, "%s ab8500 read failed\n", __func__); return; } + prev_status = di->flags.usbchargernotok; + if (reg_value & VBUS_CH_NOK) { di->flags.usbchargernotok = true; + /* Check again in 1sec */ + queue_delayed_work(di->charger_wq, + &di->check_usbchgnotok_work, HZ); } else { di->flags.usbchargernotok = false; di->flags.vbus_collapse = false; } - power_supply_changed(&di->usb_chg.psy); + if (prev_status != di->flags.usbchargernotok) + power_supply_changed(&di->usb_chg.psy); } /** @@ -1794,23 +1801,6 @@ static irqreturn_t ab8500_charger_usbchthprotf_handler(int irq, void *_di) } /** - * ab8500_charger_usbchargernotokf_handler() - USB charger ok detected - * @irq: interrupt number - * @_di: pointer to the ab8500_charger structure - * - * Returns IRQ status(IRQ_HANDLED) - */ -static irqreturn_t ab8500_charger_usbchargernotokf_handler(int irq, void *_di) -{ - struct ab8500_charger *di = _di; - - dev_dbg(di->dev, "Allowed USB charger detected\n"); - queue_work(di->charger_wq, &di->check_usbchgnotok_work); - - return IRQ_HANDLED; -} - -/** * ab8500_charger_usbchargernotokr_handler() - USB charger not ok detected * @irq: interrupt number * @_di: pointer to the ab8500_charger structure @@ -1822,7 +1812,7 @@ static irqreturn_t ab8500_charger_usbchargernotokr_handler(int irq, void *_di) struct ab8500_charger *di = _di; dev_dbg(di->dev, "Not allowed USB charger detected\n"); - queue_work(di->charger_wq, &di->check_usbchgnotok_work); + queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0); return IRQ_HANDLED; } @@ -2026,6 +2016,7 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) case AB8500_CUT1P1: break; case AB8500_CUT2P0: + default: ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6); @@ -2045,14 +2036,13 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) } break; - default: - goto out; } - /* VBUS OVV set to 6.3V */ + /* VBUS OVV set to 6.3V and enable automatic current limitiation */ ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, - AB8500_USBCH_CTRL2_REG, 0x78); + AB8500_USBCH_CTRL2_REG, + VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA); if (ret) { dev_err(di->dev, "failed to set VBUS OVV\n"); goto out; @@ -2146,7 +2136,6 @@ static struct ab8500_charger_interrupts ab8500_charger_irq[] = { {"USB_LINK_STATUS", ab8500_charger_usblinkstatus_handler}, {"USB_CH_TH_PROT_R", ab8500_charger_usbchthprotr_handler}, {"USB_CH_TH_PROT_F", ab8500_charger_usbchthprotf_handler}, - {"USB_CHARGER_NOT_OKF", ab8500_charger_usbchargernotokf_handler}, {"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler}, {"VBUS_OVV", ab8500_charger_vbusovv_handler}, {"CH_WD_EXP", ab8500_charger_chwdexp_handler}, @@ -2360,6 +2349,9 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) /* Init work for HW failure check */ INIT_DELAYED_WORK_DEFERRABLE(&di->check_hw_failure_work, ab8500_charger_check_hw_failure_work); + INIT_DELAYED_WORK_DEFERRABLE(&di->check_usbchgnotok_work, + ab8500_charger_check_usbchargernotok_work); + /* * For ABB revision 1.0 and 1.1 there is a bug in the watchdog @@ -2384,8 +2376,6 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) ab8500_charger_usb_state_changed_work); /* Init work for checking HW status */ - INIT_WORK(&di->check_usbchgnotok_work, - ab8500_charger_check_usbchargernotok_work); INIT_WORK(&di->check_main_thermal_prot_work, ab8500_charger_check_main_thermal_prot_work); INIT_WORK(&di->check_usb_thermal_prot_work, |