aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/power/twl4030_charger.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 3b7cc631bb8a..982675df21b7 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -22,6 +22,7 @@
22#include <linux/power_supply.h> 22#include <linux/power_supply.h>
23#include <linux/notifier.h> 23#include <linux/notifier.h>
24#include <linux/usb/otg.h> 24#include <linux/usb/otg.h>
25#include <linux/i2c/twl4030-madc.h>
25 26
26#define TWL4030_BCIMSTATEC 0x02 27#define TWL4030_BCIMSTATEC 0x02
27#define TWL4030_BCIICHG 0x08 28#define TWL4030_BCIICHG 0x08
@@ -101,10 +102,13 @@ struct twl4030_bci {
101 int usb_enabled; 102 int usb_enabled;
102 103
103 /* 104 /*
104 * ichg values in uA. If any are 'large', we set CGAIN to 105 * ichg_* and *_cur values in uA. If any are 'large', we set
105 * '1' which doubles the range for half the precision. 106 * CGAIN to '1' which doubles the range for half the
107 * precision.
106 */ 108 */
107 unsigned int ichg_eoc, ichg_lo, ichg_hi, cur; 109 unsigned int ichg_eoc, ichg_lo, ichg_hi;
110 unsigned int usb_cur, ac_cur;
111 bool ac_is_active;
108 112
109 unsigned long event; 113 unsigned long event;
110}; 114};
@@ -225,11 +229,24 @@ static int ua2regval(int ua, bool cgain)
225static int twl4030_charger_update_current(struct twl4030_bci *bci) 229static int twl4030_charger_update_current(struct twl4030_bci *bci)
226{ 230{
227 int status; 231 int status;
232 int cur;
228 unsigned reg, cur_reg; 233 unsigned reg, cur_reg;
229 u8 bcictl1, oldreg, fullreg; 234 u8 bcictl1, oldreg, fullreg;
230 bool cgain = false; 235 bool cgain = false;
231 u8 boot_bci; 236 u8 boot_bci;
232 237
238 /*
239 * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
240 * and AC is enabled, set current for 'ac'
241 */
242 if (twl4030_get_madc_conversion(11) > 4500) {
243 cur = bci->ac_cur;
244 bci->ac_is_active = true;
245 } else {
246 cur = bci->usb_cur;
247 bci->ac_is_active = false;
248 }
249
233 /* First, check thresholds and see if cgain is needed */ 250 /* First, check thresholds and see if cgain is needed */
234 if (bci->ichg_eoc >= 200000) 251 if (bci->ichg_eoc >= 200000)
235 cgain = true; 252 cgain = true;
@@ -237,7 +254,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
237 cgain = true; 254 cgain = true;
238 if (bci->ichg_hi >= 820000) 255 if (bci->ichg_hi >= 820000)
239 cgain = true; 256 cgain = true;
240 if (bci->cur > 852000) 257 if (cur > 852000)
241 cgain = true; 258 cgain = true;
242 259
243 status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1); 260 status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
@@ -318,7 +335,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
318 * And finally, set the current. This is stored in 335 * And finally, set the current. This is stored in
319 * two registers. 336 * two registers.
320 */ 337 */
321 reg = ua2regval(bci->cur, cgain); 338 reg = ua2regval(cur, cgain);
322 /* we have only 10 bits */ 339 /* we have only 10 bits */
323 if (reg > 0x3ff) 340 if (reg > 0x3ff)
324 reg = 0x3ff; 341 reg = 0x3ff;
@@ -371,6 +388,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
371 388
372 if (enable && !IS_ERR_OR_NULL(bci->transceiver)) { 389 if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
373 390
391 twl4030_charger_update_current(bci);
392
374 /* Need to keep phy powered */ 393 /* Need to keep phy powered */
375 if (!bci->usb_enabled) { 394 if (!bci->usb_enabled) {
376 pm_runtime_get_sync(bci->transceiver->dev); 395 pm_runtime_get_sync(bci->transceiver->dev);
@@ -463,6 +482,7 @@ static irqreturn_t twl4030_charger_interrupt(int irq, void *arg)
463 struct twl4030_bci *bci = arg; 482 struct twl4030_bci *bci = arg;
464 483
465 dev_dbg(bci->dev, "CHG_PRES irq\n"); 484 dev_dbg(bci->dev, "CHG_PRES irq\n");
485 twl4030_charger_update_current(bci);
466 power_supply_changed(bci->ac); 486 power_supply_changed(bci->ac);
467 power_supply_changed(bci->usb); 487 power_supply_changed(bci->usb);
468 488
@@ -495,6 +515,7 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
495 power_supply_changed(bci->ac); 515 power_supply_changed(bci->ac);
496 power_supply_changed(bci->usb); 516 power_supply_changed(bci->usb);
497 } 517 }
518 twl4030_charger_update_current(bci);
498 519
499 /* various monitoring events, for now we just log them here */ 520 /* various monitoring events, for now we just log them here */
500 if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1)) 521 if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1))
@@ -724,10 +745,11 @@ static int twl4030_bci_probe(struct platform_device *pdev)
724 bci->ichg_eoc = 80100; /* Stop charging when current drops to here */ 745 bci->ichg_eoc = 80100; /* Stop charging when current drops to here */
725 bci->ichg_lo = 241000; /* Low threshold */ 746 bci->ichg_lo = 241000; /* Low threshold */
726 bci->ichg_hi = 500000; /* High threshold */ 747 bci->ichg_hi = 500000; /* High threshold */
748 bci->ac_cur = 500000; /* 500mA */
727 if (allow_usb) 749 if (allow_usb)
728 bci->cur = 500000; /* 500mA */ 750 bci->usb_cur = 500000; /* 500mA */
729 else 751 else
730 bci->cur = 100000; /* 100mA */ 752 bci->usb_cur = 100000; /* 100mA */
731 753
732 bci->dev = &pdev->dev; 754 bci->dev = &pdev->dev;
733 bci->irq_chg = platform_get_irq(pdev, 0); 755 bci->irq_chg = platform_get_irq(pdev, 0);