aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorNeilBrown <neil@brown.name>2015-07-29 20:11:24 -0400
committerSebastian Reichel <sre@kernel.org>2015-08-04 23:18:06 -0400
commite4ae537e0482e99eeaa5373d39932fe65a477c21 (patch)
treec2614aea68397f9181e596916aa2f7d4b82e0f97 /drivers/power
parent1098cb58aed8eb4e06302d947a38bbfb69c8b4ba (diff)
twl4030_charger: distinguish between USB current and 'AC' current
The twl4030 charger has two current sources, 'USB' and 'AC' (presumably "Accessory Charger" because it isn't Alternating Current). If 'AC' is providing current, we should set the current limit differently to when it isn't (and so USB is used). So split 'cur' into 'usb_cur' and 'ac_cur' and use accordingly. Now we must review the current setting on any interrupt or USB event which might indicate that the charger-source has changed. Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: NeilBrown <neil@brown.name> Signed-off-by: Sebastian Reichel <sre@kernel.org>
Diffstat (limited to 'drivers/power')
-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);