All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] Enhance twl4030_charger functionality. - V2
@ 2015-03-22 23:20 NeilBrown
  2015-03-22 23:20 ` [PATCH 05/14] twl4030_charger: split uA calculation into a function NeilBrown
                   ` (14 more replies)
  0 siblings, 15 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: linux-api, linux-kernel, GTA04 owners, inux-pm, Pavel Machek,
	linux-omap, Lee Jones

Hi Sebastian,
 here is V2 of my patches to improve the twl4030 charger.
 They include improved documentation and removal of changes
 to the CVENAC bit which I didn't properly understand.

 One patch needs to make a change in drivers/mfd, and that has
 been acked by Lee Jones.

Summary from before:
These patches make a number of improvements to twl4030_charger.

Some are just internal cleanups (e.g. use of devres).  Others allow
better control of charging through both manual and automatic means.

- the maximum current can be configured via sysfs.
- the charger will only draw that current if it can do so without
  the voltage dropping too much
- a 'continuous' mode is available which ignores voltage and just
  takes what it can (to be used with caution, but very useful in
  some circumstances).
- 'ac' and 'usb' power sources can be configured separately.


Thanks,
NeilBrown

---

NeilBrown (14):
      twl4030_charger: use devm_request_threaded_irq
      twl4030_charger: use devres for power_supply_register and kzalloc.
      twl4030_charger: use runtime_pm to keep usb phy active while charging.
      twl4030_charger: trust phy to determine when USB power is available.
      twl4030_charger: split uA calculation into a function.
      twl4030_charger: allow fine control of charger current.
      twl4030_charger: distinguish between USB current and 'AC' current
      twl4030_charger: allow max_current to be managed via sysfs.
      twl4030_charger: only draw USB current as negotiated with host.
      twl4030_charger: enable manual enable/disable of usb charging.
      twl4030_charger: add software controlled linear charging mode.
      twl4030_charger: add ac/mode to match usb/mode
      twl4030_charger: Increase current carefully while watching voltage.
      twl4030_charger: assume a 'charger' can supply maximum current.


 .../ABI/testing/sysfs-class-power-twl4030          |   45 ++
 drivers/mfd/twl-core.c                             |    9 
 drivers/power/twl4030_charger.c                    |  573 +++++++++++++++++---
 3 files changed, 536 insertions(+), 91 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-power-twl4030

--
Signature


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/14] twl4030_charger: use devm_request_threaded_irq
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (2 preceding siblings ...)
  2015-03-22 23:20 ` [PATCH 02/14] twl4030_charger: use devres for power_supply_register and kzalloc NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-07-24 14:34   ` Sebastian Reichel
  2015-03-22 23:20 ` [PATCH 04/14] twl4030_charger: trust phy to determine when USB power is available NeilBrown
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

This simplifies the error paths.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/power/twl4030_charger.c |   18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index b07f4e2f2dde..58996d252ecf 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -610,21 +610,21 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 		goto fail_register_usb;
 	}
 
-	ret = request_threaded_irq(bci->irq_chg, NULL,
+	ret = devm_request_threaded_irq(&pdev->dev, bci->irq_chg, NULL,
 			twl4030_charger_interrupt, IRQF_ONESHOT, pdev->name,
 			bci);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
 			bci->irq_chg, ret);
-		goto fail_chg_irq;
+		goto fail;
 	}
 
-	ret = request_threaded_irq(bci->irq_bci, NULL,
+	ret = devm_request_threaded_irq(&pdev->dev, bci->irq_bci, NULL,
 			twl4030_bci_interrupt, IRQF_ONESHOT, pdev->name, bci);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
 			bci->irq_bci, ret);
-		goto fail_bci_irq;
+		goto fail;
 	}
 
 	INIT_WORK(&bci->work, twl4030_bci_usb_work);
@@ -647,7 +647,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 			       TWL4030_INTERRUPTS_BCIIMR1A);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
-		goto fail_unmask_interrupts;
+		goto fail;
 	}
 
 	reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
@@ -666,11 +666,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 
 	return 0;
 
-fail_unmask_interrupts:
-	free_irq(bci->irq_bci, bci);
-fail_bci_irq:
-	free_irq(bci->irq_chg, bci);
-fail_chg_irq:
+fail:
 	power_supply_unregister(&bci->usb);
 fail_register_usb:
 	power_supply_unregister(&bci->ac);
@@ -695,8 +691,6 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
 	twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
 			 TWL4030_INTERRUPTS_BCIIMR2A);
 
-	free_irq(bci->irq_bci, bci);
-	free_irq(bci->irq_chg, bci);
 	power_supply_unregister(&bci->usb);
 	power_supply_unregister(&bci->ac);
 	kfree(bci);



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/14] twl4030_charger: use devres for power_supply_register and kzalloc.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
  2015-03-22 23:20 ` [PATCH 05/14] twl4030_charger: split uA calculation into a function NeilBrown
  2015-03-22 23:20 ` [PATCH 03/14] twl4030_charger: use runtime_pm to keep usb phy active while charging NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-23 21:25   ` Pavel Machek
  2015-07-24 14:35     ` Sebastian Reichel
  2015-03-22 23:20 ` [PATCH 01/14] twl4030_charger: use devm_request_threaded_irq NeilBrown
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

Final allocations/registrations are now managed by devres.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/power/twl4030_charger.c |   32 +++++++++-----------------------
 1 file changed, 9 insertions(+), 23 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 58996d252ecf..7b6c4000cd30 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -565,7 +565,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	int ret;
 	u32 reg;
 
-	bci = kzalloc(sizeof(*bci), GFP_KERNEL);
+	bci = devm_kzalloc(&pdev->dev, sizeof(*bci), GFP_KERNEL);
 	if (bci == NULL)
 		return -ENOMEM;
 
@@ -580,7 +580,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	ret = twl4030_is_battery_present(bci);
 	if  (ret) {
 		dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret);
-		goto fail_no_battery;
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, bci);
@@ -590,10 +590,10 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	bci->ac.num_properties = ARRAY_SIZE(twl4030_charger_props);
 	bci->ac.get_property = twl4030_bci_get_property;
 
-	ret = power_supply_register(&pdev->dev, &bci->ac);
+	ret = devm_power_supply_register(&pdev->dev, &bci->ac);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
-		goto fail_register_ac;
+		return ret;
 	}
 
 	bci->usb.name = "twl4030_usb";
@@ -604,10 +604,10 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 
 	bci->usb_reg = regulator_get(bci->dev, "bci3v1");
 
-	ret = power_supply_register(&pdev->dev, &bci->usb);
+	ret = devm_power_supply_register(&pdev->dev, &bci->usb);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
-		goto fail_register_usb;
+		return ret;
 	}
 
 	ret = devm_request_threaded_irq(&pdev->dev, bci->irq_chg, NULL,
@@ -616,7 +616,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	if (ret < 0) {
 		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
 			bci->irq_chg, ret);
-		goto fail;
+		return ret;
 	}
 
 	ret = devm_request_threaded_irq(&pdev->dev, bci->irq_bci, NULL,
@@ -624,7 +624,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	if (ret < 0) {
 		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
 			bci->irq_bci, ret);
-		goto fail;
+		return ret;
 	}
 
 	INIT_WORK(&bci->work, twl4030_bci_usb_work);
@@ -647,7 +647,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 			       TWL4030_INTERRUPTS_BCIIMR1A);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
-		goto fail;
+		return ret;
 	}
 
 	reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
@@ -665,16 +665,6 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 		twl4030_charger_enable_backup(0, 0);
 
 	return 0;
-
-fail:
-	power_supply_unregister(&bci->usb);
-fail_register_usb:
-	power_supply_unregister(&bci->ac);
-fail_register_ac:
-fail_no_battery:
-	kfree(bci);
-
-	return ret;
 }
 
 static int __exit twl4030_bci_remove(struct platform_device *pdev)
@@ -691,10 +681,6 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
 	twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
 			 TWL4030_INTERRUPTS_BCIIMR2A);
 
-	power_supply_unregister(&bci->usb);
-	power_supply_unregister(&bci->ac);
-	kfree(bci);
-
 	return 0;
 }
 



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/14] twl4030_charger: use runtime_pm to keep usb phy active while charging.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
  2015-03-22 23:20 ` [PATCH 05/14] twl4030_charger: split uA calculation into a function NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-22 23:20 ` [PATCH 02/14] twl4030_charger: use devres for power_supply_register and kzalloc NeilBrown
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

The twl4030 usb phy needs to be active while we are using
the USB VBUS as a current source for charging.
In particular, the usb3v1 regulator must be enabled and the
PHY_PWR_PHYPWD bit must be set to keep the phy powered.

commit ab37813f4093a5f59cb8e083cde277289dc72ed3
    twl4030_charger: Allow charger to control the regulator that feeds it

Gave the charger control over the regulator, but didn't resolve
the PHY_PWR_PHYPWD issue.

Now that both of these are controlled by runtime_pm in
phy-twl4030-usb, we can simply take a runtime_pm reference to the USB
phy whenever the charger wants to use it as a current source.

So this patch reverts the above commit, and adds the necessary
runtime_pm calls.

Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/mfd/twl-core.c          |    9 ++++-----
 drivers/power/twl4030_charger.c |   18 +++++-------------
 2 files changed, 9 insertions(+), 18 deletions(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 489674a2497e..831696ee2472 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -788,9 +788,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 		static struct regulator_consumer_supply usb1v8 = {
 			.supply =	"usb1v8",
 		};
-		static struct regulator_consumer_supply usb3v1[] = {
-			{ .supply =	"usb3v1" },
-			{ .supply =	"bci3v1" },
+		static struct regulator_consumer_supply usb3v1 = {
+			.supply =	"usb3v1",
 		};
 
 	/* First add the regulators so that they can be used by transceiver */
@@ -818,7 +817,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 				return PTR_ERR(child);
 
 			child = add_regulator_linked(TWL4030_REG_VUSB3V1,
-						      &usb_fixed, usb3v1, 2,
+						      &usb_fixed, &usb3v1, 1,
 						      features);
 			if (IS_ERR(child))
 				return PTR_ERR(child);
@@ -838,7 +837,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
 			usb1v5.dev_name = dev_name(child);
 			usb1v8.dev_name = dev_name(child);
-			usb3v1[0].dev_name = dev_name(child);
+			usb3v1.dev_name = dev_name(child);
 		}
 	}
 
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 7b6c4000cd30..94c7a4d9400a 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -22,7 +22,6 @@
 #include <linux/power_supply.h>
 #include <linux/notifier.h>
 #include <linux/usb/otg.h>
-#include <linux/regulator/machine.h>
 
 #define TWL4030_BCIMSTATEC	0x02
 #define TWL4030_BCIICHG		0x08
@@ -94,7 +93,6 @@ struct twl4030_bci {
 	struct work_struct	work;
 	int			irq_chg;
 	int			irq_bci;
-	struct regulator	*usb_reg;
 	int			usb_enabled;
 
 	unsigned long		event;
@@ -208,7 +206,7 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 {
 	int ret;
 
-	if (enable) {
+	if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
 		/* Check for USB charger connected */
 		if (!twl4030_bci_have_vbus(bci))
 			return -ENODEV;
@@ -222,14 +220,9 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 			return -EACCES;
 		}
 
-		/* Need to keep regulator on */
+		/* Need to keep phy powered */
 		if (!bci->usb_enabled) {
-			ret = regulator_enable(bci->usb_reg);
-			if (ret) {
-				dev_err(bci->dev,
-					"Failed to enable regulator\n");
-				return ret;
-			}
+			pm_runtime_get_sync(bci->transceiver->dev);
 			bci->usb_enabled = 1;
 		}
 
@@ -244,7 +237,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 	} else {
 		ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
 		if (bci->usb_enabled) {
-			regulator_disable(bci->usb_reg);
+			pm_runtime_mark_last_busy(bci->transceiver->dev);
+			pm_runtime_put_autosuspend(bci->transceiver->dev);
 			bci->usb_enabled = 0;
 		}
 	}
@@ -602,8 +596,6 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props);
 	bci->usb.get_property = twl4030_bci_get_property;
 
-	bci->usb_reg = regulator_get(bci->dev, "bci3v1");
-
 	ret = devm_power_supply_register(&pdev->dev, &bci->usb);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register usb: %d\n", ret);



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/14] twl4030_charger: trust phy to determine when USB power is available.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (3 preceding siblings ...)
  2015-03-22 23:20 ` [PATCH 01/14] twl4030_charger: use devm_request_threaded_irq NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-22 23:20 ` [PATCH 14/14] twl4030_charger: assume a 'charger' can supply maximum current NeilBrown
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

The usb phy driver already determines when VBUS is available,
so repeating the test in the charger driver is pointless duplication.

On probe, process the last event from the phy, and from then on,
do whatever the phy tells us without double-checking.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/power/twl4030_charger.c |   33 ++++++---------------------------
 1 file changed, 6 insertions(+), 27 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 94c7a4d9400a..0e62a5ae56a3 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -178,28 +178,6 @@ static int twl4030_is_battery_present(struct twl4030_bci *bci)
 }
 
 /*
- * Check if VBUS power is present
- */
-static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
-{
-	int ret;
-	u8 hwsts;
-
-	ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &hwsts,
-			      TWL4030_PM_MASTER_STS_HW_CONDITIONS);
-	if (ret < 0)
-		return 0;
-
-	dev_dbg(bci->dev, "check_vbus: HW_CONDITIONS %02x\n", hwsts);
-
-	/* in case we also have STS_USB_ID, VBUS is driven by TWL itself */
-	if ((hwsts & TWL4030_STS_VBUS) && !(hwsts & TWL4030_STS_USB_ID))
-		return 1;
-
-	return 0;
-}
-
-/*
  * Enable/Disable USB Charge functionality.
  */
 static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
@@ -207,10 +185,6 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 	int ret;
 
 	if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
-		/* Check for USB charger connected */
-		if (!twl4030_bci_have_vbus(bci))
-			return -ENODEV;
-
 		/*
 		 * Until we can find out what current the device can provide,
 		 * require a module param to enable USB charging.
@@ -649,7 +623,12 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 		dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
 
 	twl4030_charger_enable_ac(true);
-	twl4030_charger_enable_usb(bci, true);
+	if (!IS_ERR_OR_NULL(bci->transceiver))
+		twl4030_bci_usb_ncb(&bci->usb_nb,
+				    bci->transceiver->last_event,
+				    NULL);
+	else
+		twl4030_charger_enable_usb(bci, false);
 	if (pdata)
 		twl4030_charger_enable_backup(pdata->bb_uvolt,
 					      pdata->bb_uamp);



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/14] twl4030_charger: split uA calculation into a function.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-22 23:20 ` [PATCH 03/14] twl4030_charger: use runtime_pm to keep usb phy active while charging NeilBrown
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

We will need this calculation in other places, so
create functions to map between register value and uA value.

Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/power/twl4030_charger.c |   48 ++++++++++++++++++++++++++++-----------
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 0e62a5ae56a3..c9a7efbb9141 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -178,6 +178,40 @@ static int twl4030_is_battery_present(struct twl4030_bci *bci)
 }
 
 /*
+ * TI provided formulas:
+ * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
+ * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7
+ * Here we use integer approximation of:
+ * CGAIN == 0: val * 1.6618 - 0.85 * 1000
+ * CGAIN == 1: (val * 1.6618 - 0.85 * 1000) * 2
+ */
+/*
+ * convert twl register value for currents into uA
+ */
+static int regval2ua(int regval, bool cgain)
+{
+	if (cgain)
+		return (regval * 16618 - 8500 * 1000) / 5;
+	else
+		return (regval * 16618 - 8500 * 1000) / 10;
+}
+
+/*
+ * convert uA currents into twl register value
+ */
+static int ua2regval(int ua, bool cgain)
+{
+	int ret;
+	if (cgain)
+		ua /= 2;
+	ret = (ua * 10 + 8500 * 1000) / 16618;
+	/* rounding problems */
+	if (ret < 512)
+		ret = 512;
+	return ret;
+}
+
+/*
  * Enable/Disable USB Charge functionality.
  */
 static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
@@ -366,14 +400,6 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 	return NOTIFY_OK;
 }
 
-/*
- * TI provided formulas:
- * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
- * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7
- * Here we use integer approximation of:
- * CGAIN == 0: val * 1.6618 - 0.85
- * CGAIN == 1: (val * 1.6618 - 0.85) * 2
- */
 static int twl4030_charger_get_current(void)
 {
 	int curr;
@@ -388,11 +414,7 @@ static int twl4030_charger_get_current(void)
 	if (ret)
 		return ret;
 
-	ret = (curr * 16618 - 850 * 10000) / 10;
-	if (bcictl1 & TWL4030_CGAIN)
-		ret *= 2;
-
-	return ret;
+	return regval2ua(curr, bcictl1 & TWL4030_CGAIN);
 }
 
 /*



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/14] twl4030_charger: allow fine control of charger current.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (5 preceding siblings ...)
  2015-03-22 23:20 ` [PATCH 14/14] twl4030_charger: assume a 'charger' can supply maximum current NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-22 23:20 ` [PATCH 10/14] twl4030_charger: enable manual enable/disable of usb charging NeilBrown
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

The twl4030 allows control of the incoming current.
Part of this control is a 'CGAIN' setting which doubles
the range for half the precision.  This control affects
several different current setting, so all need to be updated
at once when CGAIN is changed.

With this patch, all of these current setting are managed
by the driver, but most are left at their default settings.

The current drawn is set to 500mA if the allow_usb module parameter is
set, and to 100mA otherwise.
More fine control will appear in later patches.

Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/power/twl4030_charger.c |  168 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 160 insertions(+), 8 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index c9a7efbb9141..02d677ef63e2 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -31,6 +31,11 @@
 #define TWL4030_BCIMFSTS4	0x10
 #define TWL4030_BCICTL1		0x23
 #define TWL4030_BB_CFG		0x12
+#define TWL4030_BCIIREF1	0x27
+#define TWL4030_BCIIREF2	0x28
+#define TWL4030_BCIMFKEY	0x11
+#define TWL4030_BCIMFTH8	0x1d
+#define TWL4030_BCIMFTH9	0x1e
 
 #define TWL4030_BCIMFSTS1	0x01
 
@@ -95,6 +100,12 @@ struct twl4030_bci {
 	int			irq_bci;
 	int			usb_enabled;
 
+	/*
+	 * ichg values in uA. If any are 'large', we set CGAIN to
+	 * '1' which doubles the range for half the precision.
+	 */
+	unsigned int		ichg_eoc, ichg_lo, ichg_hi, cur;
+
 	unsigned long		event;
 };
 
@@ -211,6 +222,146 @@ static int ua2regval(int ua, bool cgain)
 	return ret;
 }
 
+static int twl4030_charger_update_current(struct twl4030_bci *bci)
+{
+	int status;
+	unsigned reg, cur_reg;
+	u8 bcictl1, oldreg, fullreg;
+	bool cgain = false;
+	u8 boot_bci;
+
+	/* First, check thresholds and see if cgain is needed */
+	if (bci->ichg_eoc >= 200000)
+		cgain = true;
+	if (bci->ichg_lo >= 400000)
+		cgain = true;
+	if (bci->ichg_hi >= 820000)
+		cgain = true;
+	if (bci->cur > 852000)
+		cgain = true;
+
+	status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
+	if (status < 0)
+		return status;
+	if (twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &boot_bci,
+			    TWL4030_PM_MASTER_BOOT_BCI) < 0)
+		boot_bci = 0;
+	boot_bci &= 7;
+
+	if ((!!cgain) != !!(bcictl1 & TWL4030_CGAIN))
+		/* Need to turn for charging while we change the
+		 * CGAIN bit.  Leave it off while everything is
+		 * updated.
+		 */
+		twl4030_clear_set_boot_bci(boot_bci, 0);
+
+	/*
+	 * For ichg_eoc, the hardware only supports reg values matching
+	 * 100XXXX000, and requires the XXXX be stored in the high nibble
+	 * of TWL4030_BCIMFTH8
+	 */
+	reg = ua2regval(bci->ichg_eoc, cgain);
+	if (reg > 0x278)
+		reg = 0x278;
+	if (reg < 0x200)
+		reg = 0x200;
+	reg = (reg >> 3) & 0xf;
+	fullreg = reg << 4;
+
+	/*
+	 * For ichg_lo, reg value must match 10XXXX0000.
+	 * XXXX is stored in low nibble of TWL4030_BCIMFTH8
+	 */
+	reg = ua2regval(bci->ichg_lo, cgain);
+	if (reg > 0x2F0)
+		reg = 0x2F0;
+	if (reg < 0x200)
+		reg = 0x200;
+	reg = (reg >> 4) & 0xf;
+	fullreg |= reg;
+
+	/* ichg_eoc and ichg_lo live in same register */
+	status = twl4030_bci_read(TWL4030_BCIMFTH8, &oldreg);
+	if (status < 0)
+		return status;
+	if (oldreg != fullreg) {
+		status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xF4,
+					  TWL4030_BCIMFKEY);
+		if (status < 0)
+			return status;
+		twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+				 fullreg, TWL4030_BCIMFTH8);
+	}
+
+	/* ichg_hi threshold must be 1XXXX01100 (I think) */
+	reg = ua2regval(bci->ichg_hi, cgain);
+	if (reg > 0x3E0)
+		reg = 0x3E0;
+	if (reg < 0x200)
+		reg = 0x200;
+	fullreg = (reg >> 5) & 0xF;
+	fullreg <<= 4;
+	status = twl4030_bci_read(TWL4030_BCIMFTH9, &oldreg);
+	if (status < 0)
+		return status;
+	if ((oldreg & 0xF0) != fullreg) {
+		fullreg |= (oldreg & 0x0F);
+		status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
+					  TWL4030_BCIMFKEY);
+		if (status < 0)
+			return status;
+		twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+				 fullreg, TWL4030_BCIMFTH9);
+	}
+
+	/*
+	 * And finally, set the current.  This is stored in
+	 * two registers.
+	 */
+	reg = ua2regval(bci->cur, cgain);
+	/* we have only 10 bits */
+	if (reg > 0x3ff)
+		reg = 0x3ff;
+	status = twl4030_bci_read(TWL4030_BCIIREF1, &oldreg);
+	if (status < 0)
+		return status;
+	cur_reg = oldreg;
+	status = twl4030_bci_read(TWL4030_BCIIREF2, &oldreg);
+	if (status < 0)
+		return status;
+	cur_reg |= oldreg << 8;
+	if (reg != oldreg) {
+		/* disable write protection for one write access for
+		 * BCIIREF */
+		status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
+					  TWL4030_BCIMFKEY);
+		if (status < 0)
+			return status;
+		status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+					  (reg & 0x100) ? 3 : 2,
+					  TWL4030_BCIIREF2);
+		if (status < 0)
+			return status;
+		/* disable write protection for one write access for
+		 * BCIIREF */
+		status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
+					  TWL4030_BCIMFKEY);
+		if (status < 0)
+			return status;
+		status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+					  reg & 0xff,
+					  TWL4030_BCIIREF1);
+	}
+	if ((!!cgain) != !!(bcictl1 & TWL4030_CGAIN)) {
+		/* Flip CGAIN and re-enable charging */
+		bcictl1 ^= TWL4030_CGAIN;
+		twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+				 bcictl1, TWL4030_BCICTL1);
+		twl4030_clear_set_boot_bci(0, boot_bci);
+	}
+	return 0;
+}
+
 /*
  * Enable/Disable USB Charge functionality.
  */
@@ -219,14 +370,6 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 	int ret;
 
 	if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
-		/*
-		 * Until we can find out what current the device can provide,
-		 * require a module param to enable USB charging.
-		 */
-		if (!allow_usb) {
-			dev_warn(bci->dev, "USB charging is disabled.\n");
-			return -EACCES;
-		}
 
 		/* Need to keep phy powered */
 		if (!bci->usb_enabled) {
@@ -562,6 +705,14 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	if (!pdata)
 		pdata = twl4030_bci_parse_dt(&pdev->dev);
 
+	bci->ichg_eoc = 80100; /* Stop charging when current drops to here */
+	bci->ichg_lo = 241000; /* Low threshold */
+	bci->ichg_hi = 500000; /* High threshold */
+	if (allow_usb)
+		bci->cur = 500000;  /* 500mA */
+	else
+		bci->cur = 100000;  /* 100mA */
+
 	bci->dev = &pdev->dev;
 	bci->irq_chg = platform_get_irq(pdev, 0);
 	bci->irq_bci = platform_get_irq(pdev, 1);
@@ -644,6 +795,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	if (ret < 0)
 		dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
 
+	twl4030_charger_update_current(bci);
 	twl4030_charger_enable_ac(true);
 	if (!IS_ERR_OR_NULL(bci->transceiver))
 		twl4030_bci_usb_ncb(&bci->usb_nb,



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/14] twl4030_charger: distinguish between USB current and 'AC' current
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (11 preceding siblings ...)
  2015-03-22 23:20 ` [PATCH 09/14] twl4030_charger: only draw USB current as negotiated with host NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-22 23:20 ` [PATCH 12/14] twl4030_charger: add ac/mode to match usb/mode NeilBrown
  2015-07-24 14:44   ` Sebastian Reichel
  14 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

The twl4030 charger has two current sources, 'USB' and 'AC'
(presumably "Accessory Charger").

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 <neilb@suse.de>
---
 drivers/power/twl4030_charger.c |   36 +++++++++++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 02d677ef63e2..37f2f40991ee 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -22,6 +22,7 @@
 #include <linux/power_supply.h>
 #include <linux/notifier.h>
 #include <linux/usb/otg.h>
+#include <linux/i2c/twl4030-madc.h>
 
 #define TWL4030_BCIMSTATEC	0x02
 #define TWL4030_BCIICHG		0x08
@@ -101,10 +102,13 @@ struct twl4030_bci {
 	int			usb_enabled;
 
 	/*
-	 * ichg values in uA. If any are 'large', we set CGAIN to
-	 * '1' which doubles the range for half the precision.
+	 * ichg_* and *_cur values in uA. If any are 'large', we set
+	 * CGAIN to '1' which doubles the range for half the
+	 * precision.
 	 */
-	unsigned int		ichg_eoc, ichg_lo, ichg_hi, cur;
+	unsigned int		ichg_eoc, ichg_lo, ichg_hi;
+	unsigned int		usb_cur, ac_cur;
+	bool			ac_is_active;
 
 	unsigned long		event;
 };
@@ -225,11 +229,24 @@ static int ua2regval(int ua, bool cgain)
 static int twl4030_charger_update_current(struct twl4030_bci *bci)
 {
 	int status;
+	int cur;
 	unsigned reg, cur_reg;
 	u8 bcictl1, oldreg, fullreg;
 	bool cgain = false;
 	u8 boot_bci;
 
+	/*
+	 * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
+	 * and AC is enabled, set current for 'ac'
+	 */
+	if (twl4030_get_madc_conversion(11) > 4500) {
+		cur = bci->ac_cur;
+		bci->ac_is_active = true;
+	} else {
+		cur = bci->usb_cur;
+		bci->ac_is_active = false;
+	}
+
 	/* First, check thresholds and see if cgain is needed */
 	if (bci->ichg_eoc >= 200000)
 		cgain = true;
@@ -237,7 +254,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
 		cgain = true;
 	if (bci->ichg_hi >= 820000)
 		cgain = true;
-	if (bci->cur > 852000)
+	if (cur > 852000)
 		cgain = true;
 
 	status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
@@ -318,7 +335,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
 	 * And finally, set the current.  This is stored in
 	 * two registers.
 	 */
-	reg = ua2regval(bci->cur, cgain);
+	reg = ua2regval(cur, cgain);
 	/* we have only 10 bits */
 	if (reg > 0x3ff)
 		reg = 0x3ff;
@@ -371,6 +388,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 
 	if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
 
+		twl4030_charger_update_current(bci);
+
 		/* Need to keep phy powered */
 		if (!bci->usb_enabled) {
 			pm_runtime_get_sync(bci->transceiver->dev);
@@ -463,6 +482,7 @@ static irqreturn_t twl4030_charger_interrupt(int irq, void *arg)
 	struct twl4030_bci *bci = arg;
 
 	dev_dbg(bci->dev, "CHG_PRES irq\n");
+	twl4030_charger_update_current(bci);
 	power_supply_changed(&bci->ac);
 	power_supply_changed(&bci->usb);
 
@@ -495,6 +515,7 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
 		power_supply_changed(&bci->ac);
 		power_supply_changed(&bci->usb);
 	}
+	twl4030_charger_update_current(bci);
 
 	/* various monitoring events, for now we just log them here */
 	if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1))
@@ -708,10 +729,11 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	bci->ichg_eoc = 80100; /* Stop charging when current drops to here */
 	bci->ichg_lo = 241000; /* Low threshold */
 	bci->ichg_hi = 500000; /* High threshold */
+	bci->ac_cur = 500000; /* 500mA */
 	if (allow_usb)
-		bci->cur = 500000;  /* 500mA */
+		bci->usb_cur = 500000;  /* 500mA */
 	else
-		bci->cur = 100000;  /* 100mA */
+		bci->usb_cur = 100000;  /* 100mA */
 
 	bci->dev = &pdev->dev;
 	bci->irq_chg = platform_get_irq(pdev, 0);



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/14] twl4030_charger: allow max_current to be managed via sysfs.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (8 preceding siblings ...)
  2015-03-22 23:20 ` [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-23 12:14     ` jake42
  2015-03-22 23:20   ` NeilBrown
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

'max_current' sysfs attributes are created which allow the
max to be set.
Whenever a current source changes, the default is restored.
This will be followed by a uevent, so user-space can decide to
update again.

Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 .../ABI/testing/sysfs-class-power-twl4030          |   15 ++++
 drivers/power/twl4030_charger.c                    |   72 ++++++++++++++++++++
 2 files changed, 87 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-power-twl4030

diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 b/Documentation/ABI/testing/sysfs-class-power-twl4030
new file mode 100644
index 000000000000..06092209d851
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -0,0 +1,15 @@
+What: /sys/class/power_supply/twl4030_ac/max_current
+      /sys/class/power_supply/twl4030_usb/max_current
+Description:
+	Read/Write limit on current which which may
+	be drawn from the ac (Accessory Charger) or
+	USB port.
+
+	Value is in micro-Amps.
+
+	Value is set automatically to an appropriate
+	value when a cable is plugged on unplugged.
+
+	Value can the set by writing to the attribute.
+	The change will only persist until the next
+	plug event.  These event are reported via udev.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 37f2f40991ee..df031b0123d0 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -482,6 +482,8 @@ static irqreturn_t twl4030_charger_interrupt(int irq, void *arg)
 	struct twl4030_bci *bci = arg;
 
 	dev_dbg(bci->dev, "CHG_PRES irq\n");
+	/* reset current on each 'plug' event */
+	bci->ac_cur = 500000;
 	twl4030_charger_update_current(bci);
 	power_supply_changed(&bci->ac);
 	power_supply_changed(&bci->usb);
@@ -536,6 +538,63 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
+/*
+ * Provide "max_current" attribute in sysfs.
+ */
+static ssize_t
+twl4030_bci_max_current_store(struct device *dev, struct device_attribute *attr,
+	const char *buf, size_t n)
+{
+	struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
+	int cur = 0;
+	int status = 0;
+	status = kstrtoint(buf, 10, &cur);
+	if (status)
+		return status;
+	if (cur < 0)
+		return -EINVAL;
+	if (dev == bci->ac.dev)
+		bci->ac_cur = cur;
+	else
+		bci->usb_cur = cur;
+
+	twl4030_charger_update_current(bci);
+	return n;
+}
+
+/*
+ * sysfs max_current show
+ */
+static ssize_t twl4030_bci_max_current_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	int status = 0;
+	int cur = -1;
+	u8 bcictl1;
+	struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
+
+	if (dev == bci->ac.dev) {
+		if (!bci->ac_is_active)
+			cur = bci->ac_cur;
+	} else {
+		if (bci->ac_is_active)
+			cur = bci->usb_cur;
+	}
+	if (cur < 0) {
+		cur = twl4030bci_read_adc_val(TWL4030_BCIIREF1);
+		if (cur < 0)
+			return cur;
+		status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
+		if (status < 0)
+			return status;
+		cur = regval2ua(cur, bcictl1 & TWL4030_CGAIN);
+	}
+	return scnprintf(buf, PAGE_SIZE, "%u\n", cur);
+}
+
+static DEVICE_ATTR(max_current, 0644, twl4030_bci_max_current_show,
+			twl4030_bci_max_current_store);
+
 static void twl4030_bci_usb_work(struct work_struct *data)
 {
 	struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work);
@@ -558,6 +617,12 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 
 	dev_dbg(bci->dev, "OTG notify %lu\n", val);
 
+	/* reset current on each 'plug' event */
+	if (allow_usb)
+		bci->usb_cur = 500000;
+	else
+		bci->usb_cur = 100000;
+
 	bci->event = val;
 	schedule_work(&bci->work);
 
@@ -818,6 +883,11 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 		dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
 
 	twl4030_charger_update_current(bci);
+	if (device_create_file(bci->usb.dev, &dev_attr_max_current))
+		dev_warn(&pdev->dev, "could not create sysfs file\n");
+	if (device_create_file(bci->ac.dev, &dev_attr_max_current))
+		dev_warn(&pdev->dev, "could not create sysfs file\n");
+
 	twl4030_charger_enable_ac(true);
 	if (!IS_ERR_OR_NULL(bci->transceiver))
 		twl4030_bci_usb_ncb(&bci->usb_nb,
@@ -842,6 +912,8 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
 	twl4030_charger_enable_usb(bci, false);
 	twl4030_charger_enable_backup(0, 0);
 
+	device_remove_file(bci->usb.dev, &dev_attr_max_current);
+	device_remove_file(bci->ac.dev, &dev_attr_max_current);
 	/* mask interrupts */
 	twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
 			 TWL4030_INTERRUPTS_BCIIMR1A);



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/14] twl4030_charger: only draw USB current as negotiated with host.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (10 preceding siblings ...)
  2015-03-22 23:20   ` NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-22 23:20 ` [PATCH 07/14] twl4030_charger: distinguish between USB current and 'AC' current NeilBrown
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

If the phy has been told what current it can draw, it tells us
and now we use that number.

Note that 'vbus_draw' is in mA, while usb_cur is in uA.

Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/power/twl4030_charger.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index df031b0123d0..2042e7619954 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -602,6 +602,7 @@ static void twl4030_bci_usb_work(struct work_struct *data)
 	switch (bci->event) {
 	case USB_EVENT_VBUS:
 	case USB_EVENT_CHARGER:
+	case USB_EVENT_ENUMERATED:
 		twl4030_charger_enable_usb(bci, true);
 		break;
 	case USB_EVENT_NONE:
@@ -614,6 +615,7 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 			       void *priv)
 {
 	struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, usb_nb);
+	unsigned int *vbus_draw = priv;
 
 	dev_dbg(bci->dev, "OTG notify %lu\n", val);
 
@@ -624,6 +626,9 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 		bci->usb_cur = 100000;
 
 	bci->event = val;
+	if (val == USB_EVENT_ENUMERATED && vbus_draw &&
+	    *vbus_draw * 1000 > bci->usb_cur)
+		bci->usb_cur = *vbus_draw * 1000;
 	schedule_work(&bci->work);
 
 	return NOTIFY_OK;



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/14] twl4030_charger: enable manual enable/disable of usb charging.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (6 preceding siblings ...)
  2015-03-22 23:20 ` [PATCH 06/14] twl4030_charger: allow fine control of charger current NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-22 23:20 ` [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage NeilBrown
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

'off' or 'auto' to

 /sys/class/power/twl4030_usb/mode

will now enable or disable charging from USB port.  Normally this is
enabled on 'plug' and disabled on 'unplug'.
Unplug will still disable charging.  'plug' will only enable it if
'auto' if selected.

Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 .../ABI/testing/sysfs-class-power-twl4030          |   11 ++++
 drivers/power/twl4030_charger.c                    |   59 ++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 b/Documentation/ABI/testing/sysfs-class-power-twl4030
index 06092209d851..390db7a55231 100644
--- a/Documentation/ABI/testing/sysfs-class-power-twl4030
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -13,3 +13,14 @@ Description:
 	Value can the set by writing to the attribute.
 	The change will only persist until the next
 	plug event.  These event are reported via udev.
+
+
+What: /sys/class/power_supply/twl4030_usb/mode
+Description:
+	Changing mode for USB port.
+	Writing to this can disable charging.
+
+	Possible values are:
+		"auto" - draw power as appropriate for detected
+			 power source and battery status.
+		"off"  - do not draw any power.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 2042e7619954..802cdd6d3e00 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -109,10 +109,16 @@ struct twl4030_bci {
 	unsigned int		ichg_eoc, ichg_lo, ichg_hi;
 	unsigned int		usb_cur, ac_cur;
 	bool			ac_is_active;
+	int			usb_mode; /* charging mode requested */
+#define	CHARGE_OFF	0
+#define	CHARGE_AUTO	1
 
 	unsigned long		event;
 };
 
+/* strings for 'usb_mode' values */
+static char *modes[] = { "off", "auto" };
+
 /*
  * clear and set bits on an given register on a given module
  */
@@ -386,6 +392,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 {
 	int ret;
 
+	if (bci->usb_mode == CHARGE_OFF)
+		enable = false;
 	if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
 
 		twl4030_charger_update_current(bci);
@@ -634,6 +642,53 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 	return NOTIFY_OK;
 }
 
+/*
+ * sysfs charger enabled store
+ */
+static ssize_t
+twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t n)
+{
+	struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
+	int mode;
+	int status;
+
+	if (sysfs_streq(buf, modes[0]))
+		mode = 0;
+	else if (sysfs_streq(buf, modes[1]))
+		mode = 1;
+	else
+		return -EINVAL;
+	twl4030_charger_enable_usb(bci, false);
+	bci->usb_mode = mode;
+	status = twl4030_charger_enable_usb(bci, true);
+	return (status == 0) ? n : status;
+}
+
+/*
+ * sysfs charger enabled show
+ */
+static ssize_t
+twl4030_bci_mode_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
+	int len = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(modes); i++)
+		if (bci->usb_mode == i)
+			len += snprintf(buf+len, PAGE_SIZE-len,
+					"[%s] ", modes[i]);
+		else
+			len += snprintf(buf+len, PAGE_SIZE-len,
+					"%s ", modes[i]);
+	buf[len-1] = '\n';
+	return len;
+}
+static DEVICE_ATTR(mode, 0644, twl4030_bci_mode_show,
+		   twl4030_bci_mode_store);
+
 static int twl4030_charger_get_current(void)
 {
 	int curr;
@@ -804,6 +859,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 		bci->usb_cur = 500000;  /* 500mA */
 	else
 		bci->usb_cur = 100000;  /* 100mA */
+	bci->usb_mode = CHARGE_AUTO;
 
 	bci->dev = &pdev->dev;
 	bci->irq_chg = platform_get_irq(pdev, 0);
@@ -890,6 +946,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	twl4030_charger_update_current(bci);
 	if (device_create_file(bci->usb.dev, &dev_attr_max_current))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
+	if (device_create_file(bci->usb.dev, &dev_attr_mode))
+		dev_warn(&pdev->dev, "could not create sysfs file\n");
 	if (device_create_file(bci->ac.dev, &dev_attr_max_current))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
@@ -918,6 +976,7 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
 	twl4030_charger_enable_backup(0, 0);
 
 	device_remove_file(bci->usb.dev, &dev_attr_max_current);
+	device_remove_file(bci->usb.dev, &dev_attr_mode);
 	device_remove_file(bci->ac.dev, &dev_attr_max_current);
 	/* mask interrupts */
 	twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/14] twl4030_charger: add software controlled linear charging mode.
@ 2015-03-22 23:20   ` NeilBrown
  0 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

Add a 'continuous' option for usb charging which enables
the "linear" charging mode of the twl4030.

Linear charging does a good job with not-so-reliable power sources.
Auto mode does not work well as it switches off when voltage drops
momentarily.  Care must be taken not to over-charge.

It was used with a bike hub dynamo since a year or so. In that case
there are automatically charging stops when the cyclist needs a break.

Orignal-by: Andreas Kemnade <andreas@kemnade.info>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 .../ABI/testing/sysfs-class-power-twl4030          |    9 +++
 drivers/power/twl4030_charger.c                    |   55 ++++++++++++++++++--
 2 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 b/Documentation/ABI/testing/sysfs-class-power-twl4030
index 390db7a55231..c27e8ca8c9db 100644
--- a/Documentation/ABI/testing/sysfs-class-power-twl4030
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -24,3 +24,12 @@ Description:
 		"auto" - draw power as appropriate for detected
 			 power source and battery status.
 		"off"  - do not draw any power.
+		"continuous"
+		       - activate mode described as "linear" in
+		         TWL data sheets.  This uses whatever
+			 current is available and doesn't switch off
+			 when voltage drops.
+
+			 This is useful for unstable power sources
+			 such as bicycle dynamo, but care should
+			 be taken that battery is not over-charged.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 802cdd6d3e00..2c8d85102def 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -24,6 +24,8 @@
 #include <linux/usb/otg.h>
 #include <linux/i2c/twl4030-madc.h>
 
+#define TWL4030_BCIMDEN		0x00
+#define TWL4030_BCIMDKEY	0x01
 #define TWL4030_BCIMSTATEC	0x02
 #define TWL4030_BCIICHG		0x08
 #define TWL4030_BCIVAC		0x0a
@@ -35,13 +37,16 @@
 #define TWL4030_BCIIREF1	0x27
 #define TWL4030_BCIIREF2	0x28
 #define TWL4030_BCIMFKEY	0x11
+#define TWL4030_BCIMFEN3	0x14
 #define TWL4030_BCIMFTH8	0x1d
 #define TWL4030_BCIMFTH9	0x1e
+#define TWL4030_BCIWDKEY	0x21
 
 #define TWL4030_BCIMFSTS1	0x01
 
 #define TWL4030_BCIAUTOWEN	BIT(5)
 #define TWL4030_CONFIG_DONE	BIT(4)
+#define TWL4030_CVENAC		BIT(2)
 #define TWL4030_BCIAUTOUSB	BIT(1)
 #define TWL4030_BCIAUTOAC	BIT(0)
 #define TWL4030_CGAIN		BIT(5)
@@ -112,12 +117,13 @@ struct twl4030_bci {
 	int			usb_mode; /* charging mode requested */
 #define	CHARGE_OFF	0
 #define	CHARGE_AUTO	1
+#define	CHARGE_LINEAR	2
 
 	unsigned long		event;
 };
 
 /* strings for 'usb_mode' values */
-static char *modes[] = { "off", "auto" };
+static char *modes[] = { "off", "auto", "continuous" };
 
 /*
  * clear and set bits on an given register on a given module
@@ -404,16 +410,42 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 			bci->usb_enabled = 1;
 		}
 
-		/* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
-		ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
-		if (ret < 0)
-			return ret;
+		if (bci->usb_mode == CHARGE_AUTO)
+			/* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
+			ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
 
 		/* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
 		ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0,
 			TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
+		if (bci->usb_mode == CHARGE_LINEAR) {
+			twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC|TWL4030_CVENAC, 0);
+			/* Watch dog key: WOVF acknowledge */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x33,
+					       TWL4030_BCIWDKEY);
+			/* 0x24 + EKEY6: off mode */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
+					       TWL4030_BCIMDKEY);
+			/* EKEY2: Linear charge: USB path */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x26,
+					       TWL4030_BCIMDKEY);
+			/* WDKEY5: stop watchdog count */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf3,
+					       TWL4030_BCIWDKEY);
+			/* enable MFEN3 access */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x9c,
+					       TWL4030_BCIMFKEY);
+			 /* ICHGEOCEN - end-of-charge monitor (current < 80mA)
+			  *                      (charging continues)
+			  * ICHGLOWEN - current level monitor (charge continues)
+			  * don't monitor over-current or heat save
+			  */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf0,
+					       TWL4030_BCIMFEN3);
+		}
 	} else {
 		ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
+		ret |= twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
+					TWL4030_BCIMDKEY);
 		if (bci->usb_enabled) {
 			pm_runtime_mark_last_busy(bci->transceiver->dev);
 			pm_runtime_put_autosuspend(bci->transceiver->dev);
@@ -657,6 +689,8 @@ twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr,
 		mode = 0;
 	else if (sysfs_streq(buf, modes[1]))
 		mode = 1;
+	else if (sysfs_streq(buf, modes[2]))
+		mode = 2;
 	else
 		return -EINVAL;
 	twl4030_charger_enable_usb(bci, false);
@@ -755,6 +789,17 @@ static int twl4030_bci_get_property(struct power_supply *psy,
 		is_charging = state & TWL4030_MSTATEC_USB;
 	else
 		is_charging = state & TWL4030_MSTATEC_AC;
+	if (!is_charging) {
+		u8 s;
+		twl4030_bci_read(TWL4030_BCIMDEN, &s);
+		if (psy->type == POWER_SUPPLY_TYPE_USB)
+			is_charging = s & 1;
+		else
+			is_charging = s & 2;
+		if (is_charging)
+			/* A little white lie */
+			state = TWL4030_MSTATEC_QUICK1;
+	}
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_STATUS:



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 12/14] twl4030_charger: add ac/mode to match usb/mode
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (12 preceding siblings ...)
  2015-03-22 23:20 ` [PATCH 07/14] twl4030_charger: distinguish between USB current and 'AC' current NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-07-24 14:44   ` Sebastian Reichel
  14 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

This allows AC charging to be turned off, much like usb charging.
"continuous" mode is not available though.

Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 .../ABI/testing/sysfs-class-power-twl4030          |   10 ++++++
 drivers/power/twl4030_charger.c                    |   35 +++++++++++++++-----
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 b/Documentation/ABI/testing/sysfs-class-power-twl4030
index c27e8ca8c9db..35a211b9a172 100644
--- a/Documentation/ABI/testing/sysfs-class-power-twl4030
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -33,3 +33,13 @@ Description:
 			 This is useful for unstable power sources
 			 such as bicycle dynamo, but care should
 			 be taken that battery is not over-charged.
+
+What: /sys/class/power_supply/twl4030_ac/mode
+Description:
+	Changing mode for 'ac' port.
+	Writing to this can disable charging.
+
+	Possible values are:
+		"auto" - draw power as appropriate for detected
+			 power source and battery status.
+		"off"  - do not draw any power.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 2c8d85102def..73c7cd96ebc1 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -114,7 +114,7 @@ struct twl4030_bci {
 	unsigned int		ichg_eoc, ichg_lo, ichg_hi;
 	unsigned int		usb_cur, ac_cur;
 	bool			ac_is_active;
-	int			usb_mode; /* charging mode requested */
+	int			usb_mode, ac_mode; /* charging mode requested */
 #define	CHARGE_OFF	0
 #define	CHARGE_AUTO	1
 #define	CHARGE_LINEAR	2
@@ -459,10 +459,13 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 /*
  * Enable/Disable AC Charge funtionality.
  */
-static int twl4030_charger_enable_ac(bool enable)
+static int twl4030_charger_enable_ac(struct twl4030_bci *bci, bool enable)
 {
 	int ret;
 
+	if (bci->ac_mode == CHARGE_OFF)
+		enable = false;
+
 	if (enable)
 		ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC);
 	else
@@ -693,9 +696,17 @@ twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr,
 		mode = 2;
 	else
 		return -EINVAL;
-	twl4030_charger_enable_usb(bci, false);
-	bci->usb_mode = mode;
-	status = twl4030_charger_enable_usb(bci, true);
+	if (dev == bci->ac.dev) {
+		if (mode == 2)
+			return -EINVAL;
+		twl4030_charger_enable_ac(bci, false);
+		bci->ac_mode = mode;
+		status = twl4030_charger_enable_ac(bci, true);
+	} else {
+		twl4030_charger_enable_usb(bci, false);
+		bci->usb_mode = mode;
+		status = twl4030_charger_enable_usb(bci, true);
+	}
 	return (status == 0) ? n : status;
 }
 
@@ -709,9 +720,13 @@ twl4030_bci_mode_show(struct device *dev,
 	struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
 	int len = 0;
 	int i;
+	int mode = bci->usb_mode;
+
+	if (dev == bci->ac.dev)
+		mode = bci->ac_mode;
 
 	for (i = 0; i < ARRAY_SIZE(modes); i++)
-		if (bci->usb_mode == i)
+		if (mode == i)
 			len += snprintf(buf+len, PAGE_SIZE-len,
 					"[%s] ", modes[i]);
 		else
@@ -905,6 +920,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	else
 		bci->usb_cur = 100000;  /* 100mA */
 	bci->usb_mode = CHARGE_AUTO;
+	bci->ac_mode = CHARGE_AUTO;
 
 	bci->dev = &pdev->dev;
 	bci->irq_chg = platform_get_irq(pdev, 0);
@@ -993,10 +1009,12 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 	if (device_create_file(bci->usb.dev, &dev_attr_mode))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
+	if (device_create_file(bci->ac.dev, &dev_attr_mode))
+		dev_warn(&pdev->dev, "could not create sysfs file\n");
 	if (device_create_file(bci->ac.dev, &dev_attr_max_current))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
-	twl4030_charger_enable_ac(true);
+	twl4030_charger_enable_ac(bci, true);
 	if (!IS_ERR_OR_NULL(bci->transceiver))
 		twl4030_bci_usb_ncb(&bci->usb_nb,
 				    bci->transceiver->last_event,
@@ -1016,13 +1034,14 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
 {
 	struct twl4030_bci *bci = platform_get_drvdata(pdev);
 
-	twl4030_charger_enable_ac(false);
+	twl4030_charger_enable_ac(bci, false);
 	twl4030_charger_enable_usb(bci, false);
 	twl4030_charger_enable_backup(0, 0);
 
 	device_remove_file(bci->usb.dev, &dev_attr_max_current);
 	device_remove_file(bci->usb.dev, &dev_attr_mode);
 	device_remove_file(bci->ac.dev, &dev_attr_max_current);
+	device_remove_file(bci->ac.dev, &dev_attr_mode);
 	/* mask interrupts */
 	twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
 			 TWL4030_INTERRUPTS_BCIIMR1A);



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (7 preceding siblings ...)
  2015-03-22 23:20 ` [PATCH 10/14] twl4030_charger: enable manual enable/disable of usb charging NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-23 21:25   ` Pavel Machek
  2015-03-22 23:20 ` [PATCH 08/14] twl4030_charger: allow max_current to be managed via sysfs NeilBrown
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

The USB Battery Charging spec (BC1.2) suggests a dedicated
charging port can deliver from 0.5 to 5.0A at between 4.75 and 5.25
volts.

To choose the "correct" current voltage setting requires a trial
and error approach: try to draw current and see if the voltage drops
too low.

Even with a configured Standard Downstream Port, it may not be possible
to reliably pull 500mA - depending on cable quality and source
quality I have reports of charging failure due to the voltage dropping
too low.

To address both these concerns, this patch introduce incremental
current setting.
The current pull from VBUS is increased in steps of 20mA every 100ms
until the target is reached or until the measure voltage drops below
4.75V.  If the voltage does go too low, the target current is reduced
by 20mA and kept there.

This applies to currents selected automatically, or to values
set via sysfs.  So setting a large value will cause the maximum
available to be used - up to the limit of 1.7A imposed by the
hardware.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/power/twl4030_charger.c |   68 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 60 insertions(+), 8 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 73c7cd96ebc1..d0199495dddc 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -119,6 +119,18 @@ struct twl4030_bci {
 #define	CHARGE_AUTO	1
 #define	CHARGE_LINEAR	2
 
+	/* When setting the USB current we slowly increase the
+	 * requested current until target is reached or the voltage
+	 * drops below 4.75V.  In the latter case we step back one
+	 * step.
+	 */
+	unsigned int		usb_cur_target;
+	struct delayed_work	current_worker;
+#define	USB_CUR_STEP	20000	/* 20mA at a time */
+#define	USB_MIN_VOLT	4750000	/* 4.75V */
+#define	USB_CUR_DELAY	msecs_to_jiffies(100)
+#define	USB_MAX_CURRENT	1700000 /* TWL4030 caps at 1.7A */
+
 	unsigned long		event;
 };
 
@@ -257,6 +269,12 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
 	} else {
 		cur = bci->usb_cur;
 		bci->ac_is_active = false;
+		if (cur > bci->usb_cur_target) {
+			cur = bci->usb_cur_target;
+			bci->usb_cur = cur;
+		}
+		if (cur < bci->usb_cur_target)
+			schedule_delayed_work(&bci->current_worker, USB_CUR_DELAY);
 	}
 
 	/* First, check thresholds and see if cgain is needed */
@@ -391,6 +409,38 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
 	return 0;
 }
 
+static void twl4030_current_worker(struct work_struct *data)
+{
+	int v;
+	int res;
+	struct twl4030_bci *bci = container_of(data, struct twl4030_bci,
+					       current_worker.work);
+
+	res = twl4030bci_read_adc_val(TWL4030_BCIVBUS);
+	if (res < 0)
+		v = 0;
+	else
+		/* BCIVBUS uses ADCIN8, 7/1023 V/step */
+		v = res * 6843;
+
+	printk("v=%d cur=%d target=%d\n", v, bci->usb_cur,
+	       bci->usb_cur_target);
+
+	if (v < USB_MIN_VOLT) {
+		/* Back up and stop adjusting. */
+		bci->usb_cur -= USB_CUR_STEP;
+		bci->usb_cur_target = bci->usb_cur;
+	} else if (bci->usb_cur >= bci->usb_cur_target ||
+		   bci->usb_cur + USB_CUR_STEP > USB_MAX_CURRENT) {
+		/* Reached target and voltage is OK - stop */
+		return;
+	} else {
+		bci->usb_cur += USB_CUR_STEP;
+		schedule_delayed_work(&bci->current_worker, USB_CUR_DELAY);
+	}
+	twl4030_charger_update_current(bci);
+}
+
 /*
  * Enable/Disable USB Charge functionality.
  */
@@ -451,6 +501,7 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 			pm_runtime_put_autosuspend(bci->transceiver->dev);
 			bci->usb_enabled = 0;
 		}
+		bci->usb_cur = 0;
 	}
 
 	return ret;
@@ -599,7 +650,7 @@ twl4030_bci_max_current_store(struct device *dev, struct device_attribute *attr,
 	if (dev == bci->ac.dev)
 		bci->ac_cur = cur;
 	else
-		bci->usb_cur = cur;
+		bci->usb_cur_target = cur;
 
 	twl4030_charger_update_current(bci);
 	return n;
@@ -621,7 +672,7 @@ static ssize_t twl4030_bci_max_current_show(struct device *dev,
 			cur = bci->ac_cur;
 	} else {
 		if (bci->ac_is_active)
-			cur = bci->usb_cur;
+			cur = bci->usb_cur_target;
 	}
 	if (cur < 0) {
 		cur = twl4030bci_read_adc_val(TWL4030_BCIIREF1);
@@ -664,14 +715,14 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 
 	/* reset current on each 'plug' event */
 	if (allow_usb)
-		bci->usb_cur = 500000;
+		bci->usb_cur_target = 500000;
 	else
-		bci->usb_cur = 100000;
+		bci->usb_cur_target = 100000;
 
 	bci->event = val;
 	if (val == USB_EVENT_ENUMERATED && vbus_draw &&
-	    *vbus_draw * 1000 > bci->usb_cur)
-		bci->usb_cur = *vbus_draw * 1000;
+	    *vbus_draw * 1000 > bci->usb_cur_target)
+		bci->usb_cur_target = *vbus_draw * 1000;
 	schedule_work(&bci->work);
 
 	return NOTIFY_OK;
@@ -916,9 +967,9 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	bci->ichg_hi = 500000; /* High threshold */
 	bci->ac_cur = 500000; /* 500mA */
 	if (allow_usb)
-		bci->usb_cur = 500000;  /* 500mA */
+		bci->usb_cur_target = 500000;  /* 500mA */
 	else
-		bci->usb_cur = 100000;  /* 100mA */
+		bci->usb_cur_target = 100000;  /* 100mA */
 	bci->usb_mode = CHARGE_AUTO;
 	bci->ac_mode = CHARGE_AUTO;
 
@@ -976,6 +1027,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 	}
 
 	INIT_WORK(&bci->work, twl4030_bci_usb_work);
+	INIT_DELAYED_WORK(&bci->current_worker, twl4030_current_worker);
 
 	bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
 	if (bci->dev->of_node) {



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 14/14] twl4030_charger: assume a 'charger' can supply maximum current.
  2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
                   ` (4 preceding siblings ...)
  2015-03-22 23:20 ` [PATCH 04/14] twl4030_charger: trust phy to determine when USB power is available NeilBrown
@ 2015-03-22 23:20 ` NeilBrown
  2015-03-22 23:20 ` [PATCH 06/14] twl4030_charger: allow fine control of charger current NeilBrown
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

From: NeilBrown <neilb@suse.de>

If it cannot, we will stop pulling more current when voltage drops.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/power/twl4030_charger.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index d0199495dddc..6f0dc971d84d 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -694,8 +694,10 @@ static void twl4030_bci_usb_work(struct work_struct *data)
 	struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work);
 
 	switch (bci->event) {
-	case USB_EVENT_VBUS:
 	case USB_EVENT_CHARGER:
+		bci->usb_cur = USB_MAX_CURRENT;
+		/* FALL THROUGH */
+	case USB_EVENT_VBUS:
 	case USB_EVENT_ENUMERATED:
 		twl4030_charger_enable_usb(bci, true);
 		break;



^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/14] twl4030_charger: add software controlled linear charging mode.
@ 2015-03-22 23:20   ` NeilBrown
  0 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-22 23:20 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: NeilBrown, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, GTA04 owners,
	inux-pm-u79uwXL29TY76Z2rM5mHXA, Pavel Machek,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, Lee Jones

From: NeilBrown <neilb-l3A5Bk7waGM@public.gmane.org>

Add a 'continuous' option for usb charging which enables
the "linear" charging mode of the twl4030.

Linear charging does a good job with not-so-reliable power sources.
Auto mode does not work well as it switches off when voltage drops
momentarily.  Care must be taken not to over-charge.

It was used with a bike hub dynamo since a year or so. In that case
there are automatically charging stops when the cyclist needs a break.

Orignal-by: Andreas Kemnade <andreas-cLv4Z9ELZ06ZuzBka8ofvg@public.gmane.org>
Signed-off-by: NeilBrown <neilb-l3A5Bk7waGM@public.gmane.org>
---
 .../ABI/testing/sysfs-class-power-twl4030          |    9 +++
 drivers/power/twl4030_charger.c                    |   55 ++++++++++++++++++--
 2 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 b/Documentation/ABI/testing/sysfs-class-power-twl4030
index 390db7a55231..c27e8ca8c9db 100644
--- a/Documentation/ABI/testing/sysfs-class-power-twl4030
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -24,3 +24,12 @@ Description:
 		"auto" - draw power as appropriate for detected
 			 power source and battery status.
 		"off"  - do not draw any power.
+		"continuous"
+		       - activate mode described as "linear" in
+		         TWL data sheets.  This uses whatever
+			 current is available and doesn't switch off
+			 when voltage drops.
+
+			 This is useful for unstable power sources
+			 such as bicycle dynamo, but care should
+			 be taken that battery is not over-charged.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 802cdd6d3e00..2c8d85102def 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -24,6 +24,8 @@
 #include <linux/usb/otg.h>
 #include <linux/i2c/twl4030-madc.h>
 
+#define TWL4030_BCIMDEN		0x00
+#define TWL4030_BCIMDKEY	0x01
 #define TWL4030_BCIMSTATEC	0x02
 #define TWL4030_BCIICHG		0x08
 #define TWL4030_BCIVAC		0x0a
@@ -35,13 +37,16 @@
 #define TWL4030_BCIIREF1	0x27
 #define TWL4030_BCIIREF2	0x28
 #define TWL4030_BCIMFKEY	0x11
+#define TWL4030_BCIMFEN3	0x14
 #define TWL4030_BCIMFTH8	0x1d
 #define TWL4030_BCIMFTH9	0x1e
+#define TWL4030_BCIWDKEY	0x21
 
 #define TWL4030_BCIMFSTS1	0x01
 
 #define TWL4030_BCIAUTOWEN	BIT(5)
 #define TWL4030_CONFIG_DONE	BIT(4)
+#define TWL4030_CVENAC		BIT(2)
 #define TWL4030_BCIAUTOUSB	BIT(1)
 #define TWL4030_BCIAUTOAC	BIT(0)
 #define TWL4030_CGAIN		BIT(5)
@@ -112,12 +117,13 @@ struct twl4030_bci {
 	int			usb_mode; /* charging mode requested */
 #define	CHARGE_OFF	0
 #define	CHARGE_AUTO	1
+#define	CHARGE_LINEAR	2
 
 	unsigned long		event;
 };
 
 /* strings for 'usb_mode' values */
-static char *modes[] = { "off", "auto" };
+static char *modes[] = { "off", "auto", "continuous" };
 
 /*
  * clear and set bits on an given register on a given module
@@ -404,16 +410,42 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 			bci->usb_enabled = 1;
 		}
 
-		/* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
-		ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
-		if (ret < 0)
-			return ret;
+		if (bci->usb_mode == CHARGE_AUTO)
+			/* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
+			ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
 
 		/* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
 		ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0,
 			TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
+		if (bci->usb_mode == CHARGE_LINEAR) {
+			twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC|TWL4030_CVENAC, 0);
+			/* Watch dog key: WOVF acknowledge */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x33,
+					       TWL4030_BCIWDKEY);
+			/* 0x24 + EKEY6: off mode */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
+					       TWL4030_BCIMDKEY);
+			/* EKEY2: Linear charge: USB path */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x26,
+					       TWL4030_BCIMDKEY);
+			/* WDKEY5: stop watchdog count */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf3,
+					       TWL4030_BCIWDKEY);
+			/* enable MFEN3 access */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x9c,
+					       TWL4030_BCIMFKEY);
+			 /* ICHGEOCEN - end-of-charge monitor (current < 80mA)
+			  *                      (charging continues)
+			  * ICHGLOWEN - current level monitor (charge continues)
+			  * don't monitor over-current or heat save
+			  */
+			ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf0,
+					       TWL4030_BCIMFEN3);
+		}
 	} else {
 		ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
+		ret |= twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
+					TWL4030_BCIMDKEY);
 		if (bci->usb_enabled) {
 			pm_runtime_mark_last_busy(bci->transceiver->dev);
 			pm_runtime_put_autosuspend(bci->transceiver->dev);
@@ -657,6 +689,8 @@ twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr,
 		mode = 0;
 	else if (sysfs_streq(buf, modes[1]))
 		mode = 1;
+	else if (sysfs_streq(buf, modes[2]))
+		mode = 2;
 	else
 		return -EINVAL;
 	twl4030_charger_enable_usb(bci, false);
@@ -755,6 +789,17 @@ static int twl4030_bci_get_property(struct power_supply *psy,
 		is_charging = state & TWL4030_MSTATEC_USB;
 	else
 		is_charging = state & TWL4030_MSTATEC_AC;
+	if (!is_charging) {
+		u8 s;
+		twl4030_bci_read(TWL4030_BCIMDEN, &s);
+		if (psy->type == POWER_SUPPLY_TYPE_USB)
+			is_charging = s & 1;
+		else
+			is_charging = s & 2;
+		if (is_charging)
+			/* A little white lie */
+			state = TWL4030_MSTATEC_QUICK1;
+	}
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_STATUS:

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [Gta04-owner] [PATCH 08/14] twl4030_charger: allow max_current to be managed via sysfs.
@ 2015-03-23 12:14     ` jake42
  0 siblings, 0 replies; 31+ messages in thread
From: jake42 @ 2015-03-23 12:14 UTC (permalink / raw)
  To: NeilBrown
  Cc: Sebastian Reichel, linux-api, linux-kernel, inux-pm,
	Pavel Machek, linux-omap, Lee Jones,
	List for communicating with real GTA04 owners

Hello Neil,

some suggestions:

On 23.03.2015 00:20, NeilBrown wrote:
> From: NeilBrown <neilb@suse.de>
> diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030
> b/Documentation/ABI/testing/sysfs-class-power-twl4030
> new file mode 100644
> index 000000000000..06092209d851
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
> @@ -0,0 +1,15 @@
> +What: /sys/class/power_supply/twl4030_ac/max_current
> +      /sys/class/power_supply/twl4030_usb/max_current
> +Description:
> +	Read/Write limit on current which which may
one less which                        ^^
> +	be drawn from the ac (Accessory Charger) or
> +	USB port.
> +
> +	Value is in micro-Amps.
> +
> +	Value is set automatically to an appropriate
> +	value when a cable is plugged on unplugged.
s/on/or                               ^^
> +
> +	Value can the set by writing to the attribute.
                   ^^ be set?
> +	The change will only persist until the next
> +	plug event.  These event are reported via udev.

Regards
Jake


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Gta04-owner] [PATCH 08/14] twl4030_charger: allow max_current to be managed via sysfs.
@ 2015-03-23 12:14     ` jake42
  0 siblings, 0 replies; 31+ messages in thread
From: jake42 @ 2015-03-23 12:14 UTC (permalink / raw)
  To: NeilBrown
  Cc: Sebastian Reichel, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	inux-pm-u79uwXL29TY76Z2rM5mHXA, Pavel Machek,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, Lee Jones,
	List for communicating with real GTA04 owners

Hello Neil,

some suggestions:

On 23.03.2015 00:20, NeilBrown wrote:
> From: NeilBrown <neilb-l3A5Bk7waGM@public.gmane.org>
> diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030
> b/Documentation/ABI/testing/sysfs-class-power-twl4030
> new file mode 100644
> index 000000000000..06092209d851
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
> @@ -0,0 +1,15 @@
> +What: /sys/class/power_supply/twl4030_ac/max_current
> +      /sys/class/power_supply/twl4030_usb/max_current
> +Description:
> +	Read/Write limit on current which which may
one less which                        ^^
> +	be drawn from the ac (Accessory Charger) or
> +	USB port.
> +
> +	Value is in micro-Amps.
> +
> +	Value is set automatically to an appropriate
> +	value when a cable is plugged on unplugged.
s/on/or                               ^^
> +
> +	Value can the set by writing to the attribute.
                   ^^ be set?
> +	The change will only persist until the next
> +	plug event.  These event are reported via udev.

Regards
Jake

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/14] twl4030_charger: use devres for power_supply_register and kzalloc.
  2015-03-22 23:20 ` [PATCH 02/14] twl4030_charger: use devres for power_supply_register and kzalloc NeilBrown
@ 2015-03-23 21:25   ` Pavel Machek
  2015-07-24 14:35     ` Sebastian Reichel
  1 sibling, 0 replies; 31+ messages in thread
From: Pavel Machek @ 2015-03-23 21:25 UTC (permalink / raw)
  To: NeilBrown
  Cc: Sebastian Reichel, NeilBrown, linux-api, linux-kernel,
	GTA04 owners, inux-pm, linux-omap, Lee Jones

On Mon 2015-03-23 10:20:28, NeilBrown wrote:
> From: NeilBrown <neilb@suse.de>
> 
> Final allocations/registrations are now managed by devres.
> 
> Signed-off-by: NeilBrown <neilb@suse.de>

Patches 1,2: Acked-by: Pavel Machek <pavel@ucw.cz>

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage.
  2015-03-22 23:20 ` [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage NeilBrown
@ 2015-03-23 21:25   ` Pavel Machek
  2015-03-29 21:26       ` NeilBrown
  0 siblings, 1 reply; 31+ messages in thread
From: Pavel Machek @ 2015-03-23 21:25 UTC (permalink / raw)
  To: NeilBrown
  Cc: Sebastian Reichel, NeilBrown, linux-api, linux-kernel,
	GTA04 owners, inux-pm, linux-omap, Lee Jones

Hi!

> The USB Battery Charging spec (BC1.2) suggests a dedicated
> charging port can deliver from 0.5 to 5.0A at between 4.75 and 5.25
> volts.
> 
> To choose the "correct" current voltage setting requires a trial
> and error approach: try to draw current and see if the voltage drops
> too low.
> 
> Even with a configured Standard Downstream Port, it may not be possible
> to reliably pull 500mA - depending on cable quality and source
> quality I have reports of charging failure due to the voltage dropping
> too low.
> 
> To address both these concerns, this patch introduce incremental
> current setting.
> The current pull from VBUS is increased in steps of 20mA every 100ms
> until the target is reached or until the measure voltage drops below
> 4.75V.  If the voltage does go too low, the target current is reduced
> by 20mA and kept there.

Still nervous. If it is possible to overheat the charger, without
tripping internal fuse, then you'll do it.

> This applies to currents selected automatically, or to values
> set via sysfs.  So setting a large value will cause the maximum
> available to be used - up to the limit of 1.7A imposed by the
> hardware.
>

> +	printk("v=%d cur=%d target=%d\n", v, bci->usb_cur,
> +	       bci->usb_cur_target);

dev_info() and a bit better message, or drop it for production?

> +	if (v < USB_MIN_VOLT) {
> +		/* Back up and stop adjusting. */
> +		bci->usb_cur -= USB_CUR_STEP;
> +		bci->usb_cur_target = bci->usb_cur;

More importantly.... how does it work with device drawing power for
operation, too?

Imagine device need 500mA with wifi hotspot, nearly nothing while idle.

Idle device. Code will find that it can charge using 1A, backs up to
0.9A. User starts hotspot. Now device will draw 1.4A, overloading the
charger and not charging at all...?

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage.
  2015-03-23 21:25   ` Pavel Machek
@ 2015-03-29 21:26       ` NeilBrown
  0 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-29 21:26 UTC (permalink / raw)
  To: Pavel Machek
  Cc: NeilBrown, Sebastian Reichel, linux-api, linux-kernel,
	GTA04 owners, inux-pm, linux-omap, Lee Jones

[-- Attachment #1: Type: text/plain, Size: 3179 bytes --]

On Mon, 23 Mar 2015 22:25:41 +0100 Pavel Machek <pavel@ucw.cz> wrote:

> Hi!
> 
> > The USB Battery Charging spec (BC1.2) suggests a dedicated
> > charging port can deliver from 0.5 to 5.0A at between 4.75 and 5.25
> > volts.
> > 
> > To choose the "correct" current voltage setting requires a trial
> > and error approach: try to draw current and see if the voltage drops
> > too low.
> > 
> > Even with a configured Standard Downstream Port, it may not be possible
> > to reliably pull 500mA - depending on cable quality and source
> > quality I have reports of charging failure due to the voltage dropping
> > too low.
> > 
> > To address both these concerns, this patch introduce incremental
> > current setting.
> > The current pull from VBUS is increased in steps of 20mA every 100ms
> > until the target is reached or until the measure voltage drops below
> > 4.75V.  If the voltage does go too low, the target current is reduced
> > by 20mA and kept there.
> 
> Still nervous. If it is possible to overheat the charger, without
> tripping internal fuse, then you'll do it.

If it is possible to overheat the charger without tripping an internal fuse,
then sure the charger is mis-designed - is it not?

Can you suggest an algorithm for determining how much current can safely be
pulled from a charger that would *not* make you nervous?



> 
> > This applies to currents selected automatically, or to values
> > set via sysfs.  So setting a large value will cause the maximum
> > available to be used - up to the limit of 1.7A imposed by the
> > hardware.
> >
> 
> > +	printk("v=%d cur=%d target=%d\n", v, bci->usb_cur,
> > +	       bci->usb_cur_target);
> 
> dev_info() and a bit better message, or drop it for production?

Changed to dev_dbg() - thanks.


> 
> > +	if (v < USB_MIN_VOLT) {
> > +		/* Back up and stop adjusting. */
> > +		bci->usb_cur -= USB_CUR_STEP;
> > +		bci->usb_cur_target = bci->usb_cur;
> 
> More importantly.... how does it work with device drawing power for
> operation, too?
> 
> Imagine device need 500mA with wifi hotspot, nearly nothing while idle.
> 
> Idle device. Code will find that it can charge using 1A, backs up to
> 0.9A. User starts hotspot. Now device will draw 1.4A, overloading the
> charger and not charging at all...?

The current being measured and controlled is the current flowing in from the
USB VBUS, not flowing out to the battery.
So I the code choose 0.9A, that is all that will be drawn.

This is a possible issue similar to this though.
If the device is idle and the battery is fully charged, then it won't draw
much current from USB even if we allow it too.
So the algorithm might decide it is OK to draw 1.7A because at that time the
device cannot use more than 200mA, and that doesn't cause the voltage to drop.

Then later when user enabled wifi-hotspot, the current needed might go up
above what the charger can provide.

Maybe I should only increase the limit while the actual current is also
increasing.  Maybe also revisit the setting when the battery starts charging.

NeilBrown


> 
> Best regards,
> 									Pavel


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage.
@ 2015-03-29 21:26       ` NeilBrown
  0 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-03-29 21:26 UTC (permalink / raw)
  To: Pavel Machek
  Cc: NeilBrown, Sebastian Reichel, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, GTA04 owners,
	inux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, Lee Jones

[-- Attachment #1: Type: text/plain, Size: 3201 bytes --]

On Mon, 23 Mar 2015 22:25:41 +0100 Pavel Machek <pavel-+ZI9xUNit7I@public.gmane.org> wrote:

> Hi!
> 
> > The USB Battery Charging spec (BC1.2) suggests a dedicated
> > charging port can deliver from 0.5 to 5.0A at between 4.75 and 5.25
> > volts.
> > 
> > To choose the "correct" current voltage setting requires a trial
> > and error approach: try to draw current and see if the voltage drops
> > too low.
> > 
> > Even with a configured Standard Downstream Port, it may not be possible
> > to reliably pull 500mA - depending on cable quality and source
> > quality I have reports of charging failure due to the voltage dropping
> > too low.
> > 
> > To address both these concerns, this patch introduce incremental
> > current setting.
> > The current pull from VBUS is increased in steps of 20mA every 100ms
> > until the target is reached or until the measure voltage drops below
> > 4.75V.  If the voltage does go too low, the target current is reduced
> > by 20mA and kept there.
> 
> Still nervous. If it is possible to overheat the charger, without
> tripping internal fuse, then you'll do it.

If it is possible to overheat the charger without tripping an internal fuse,
then sure the charger is mis-designed - is it not?

Can you suggest an algorithm for determining how much current can safely be
pulled from a charger that would *not* make you nervous?



> 
> > This applies to currents selected automatically, or to values
> > set via sysfs.  So setting a large value will cause the maximum
> > available to be used - up to the limit of 1.7A imposed by the
> > hardware.
> >
> 
> > +	printk("v=%d cur=%d target=%d\n", v, bci->usb_cur,
> > +	       bci->usb_cur_target);
> 
> dev_info() and a bit better message, or drop it for production?

Changed to dev_dbg() - thanks.


> 
> > +	if (v < USB_MIN_VOLT) {
> > +		/* Back up and stop adjusting. */
> > +		bci->usb_cur -= USB_CUR_STEP;
> > +		bci->usb_cur_target = bci->usb_cur;
> 
> More importantly.... how does it work with device drawing power for
> operation, too?
> 
> Imagine device need 500mA with wifi hotspot, nearly nothing while idle.
> 
> Idle device. Code will find that it can charge using 1A, backs up to
> 0.9A. User starts hotspot. Now device will draw 1.4A, overloading the
> charger and not charging at all...?

The current being measured and controlled is the current flowing in from the
USB VBUS, not flowing out to the battery.
So I the code choose 0.9A, that is all that will be drawn.

This is a possible issue similar to this though.
If the device is idle and the battery is fully charged, then it won't draw
much current from USB even if we allow it too.
So the algorithm might decide it is OK to draw 1.7A because at that time the
device cannot use more than 200mA, and that doesn't cause the voltage to drop.

Then later when user enabled wifi-hotspot, the current needed might go up
above what the charger can provide.

Maybe I should only increase the limit while the actual current is also
increasing.  Maybe also revisit the setting when the battery starts charging.

NeilBrown


> 
> Best regards,
> 									Pavel


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 811 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage.
@ 2015-04-04  7:48         ` Pavel Machek
  0 siblings, 0 replies; 31+ messages in thread
From: Pavel Machek @ 2015-04-04  7:48 UTC (permalink / raw)
  To: NeilBrown
  Cc: NeilBrown, Sebastian Reichel, linux-api, linux-kernel,
	GTA04 owners, inux-pm, linux-omap, Lee Jones

Hi!

> > > The USB Battery Charging spec (BC1.2) suggests a dedicated
> > > charging port can deliver from 0.5 to 5.0A at between 4.75 and 5.25
> > > volts.
> > > 
> > > To choose the "correct" current voltage setting requires a trial
> > > and error approach: try to draw current and see if the voltage drops
> > > too low.
> > > 
> > > Even with a configured Standard Downstream Port, it may not be possible
> > > to reliably pull 500mA - depending on cable quality and source
> > > quality I have reports of charging failure due to the voltage dropping
> > > too low.
> > > 
> > > To address both these concerns, this patch introduce incremental
> > > current setting.
> > > The current pull from VBUS is increased in steps of 20mA every 100ms
> > > until the target is reached or until the measure voltage drops below
> > > 4.75V.  If the voltage does go too low, the target current is reduced
> > > by 20mA and kept there.
> > 
> > Still nervous. If it is possible to overheat the charger, without
> > tripping internal fuse, then you'll do it.
> 
> If it is possible to overheat the charger without tripping an internal fuse,
> then sure the charger is mis-designed - is it not?
> 
> Can you suggest an algorithm for determining how much current can safely be
> pulled from a charger that would *not* make you nervous?

Not nervous? No.

Less nervous?

Run detection as you do, but then round down to "known reasonable"
max charging currents?

If you detected 1.1A charger, you are probably overloading 1A
charger. So idea would be to round down to 0.5A, 1A, 1.7A.


> > Idle device. Code will find that it can charge using 1A, backs up to
> > 0.9A. User starts hotspot. Now device will draw 1.4A, overloading the
> > charger and not charging at all...?
> 
> The current being measured and controlled is the current flowing in from the
> USB VBUS, not flowing out to the battery.
> So I the code choose 0.9A, that is all that will be drawn.
> 
> This is a possible issue similar to this though.
> If the device is idle and the battery is fully charged, then it won't draw
> much current from USB even if we allow it too.
> So the algorithm might decide it is OK to draw 1.7A because at that time the
> device cannot use more than 200mA, and that doesn't cause the voltage to drop.
> 
> Then later when user enabled wifi-hotspot, the current needed might go up
> above what the charger can provide.
> 
> Maybe I should only increase the limit while the actual current is also
> increasing.  Maybe also revisit the setting when the battery starts charging.

Yes, that sounds better.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage.
@ 2015-04-04  7:48         ` Pavel Machek
  0 siblings, 0 replies; 31+ messages in thread
From: Pavel Machek @ 2015-04-04  7:48 UTC (permalink / raw)
  To: NeilBrown
  Cc: NeilBrown, Sebastian Reichel, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, GTA04 owners,
	inux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, Lee Jones

Hi!

> > > The USB Battery Charging spec (BC1.2) suggests a dedicated
> > > charging port can deliver from 0.5 to 5.0A at between 4.75 and 5.25
> > > volts.
> > > 
> > > To choose the "correct" current voltage setting requires a trial
> > > and error approach: try to draw current and see if the voltage drops
> > > too low.
> > > 
> > > Even with a configured Standard Downstream Port, it may not be possible
> > > to reliably pull 500mA - depending on cable quality and source
> > > quality I have reports of charging failure due to the voltage dropping
> > > too low.
> > > 
> > > To address both these concerns, this patch introduce incremental
> > > current setting.
> > > The current pull from VBUS is increased in steps of 20mA every 100ms
> > > until the target is reached or until the measure voltage drops below
> > > 4.75V.  If the voltage does go too low, the target current is reduced
> > > by 20mA and kept there.
> > 
> > Still nervous. If it is possible to overheat the charger, without
> > tripping internal fuse, then you'll do it.
> 
> If it is possible to overheat the charger without tripping an internal fuse,
> then sure the charger is mis-designed - is it not?
> 
> Can you suggest an algorithm for determining how much current can safely be
> pulled from a charger that would *not* make you nervous?

Not nervous? No.

Less nervous?

Run detection as you do, but then round down to "known reasonable"
max charging currents?

If you detected 1.1A charger, you are probably overloading 1A
charger. So idea would be to round down to 0.5A, 1A, 1.7A.


> > Idle device. Code will find that it can charge using 1A, backs up to
> > 0.9A. User starts hotspot. Now device will draw 1.4A, overloading the
> > charger and not charging at all...?
> 
> The current being measured and controlled is the current flowing in from the
> USB VBUS, not flowing out to the battery.
> So I the code choose 0.9A, that is all that will be drawn.
> 
> This is a possible issue similar to this though.
> If the device is idle and the battery is fully charged, then it won't draw
> much current from USB even if we allow it too.
> So the algorithm might decide it is OK to draw 1.7A because at that time the
> device cannot use more than 200mA, and that doesn't cause the voltage to drop.
> 
> Then later when user enabled wifi-hotspot, the current needed might go up
> above what the charger can provide.
> 
> Maybe I should only increase the limit while the actual current is also
> increasing.  Maybe also revisit the setting when the battery starts charging.

Yes, that sounds better.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 01/14] twl4030_charger: use devm_request_threaded_irq
  2015-03-22 23:20 ` [PATCH 01/14] twl4030_charger: use devm_request_threaded_irq NeilBrown
@ 2015-07-24 14:34   ` Sebastian Reichel
  0 siblings, 0 replies; 31+ messages in thread
From: Sebastian Reichel @ 2015-07-24 14:34 UTC (permalink / raw)
  To: NeilBrown
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

[-- Attachment #1: Type: text/plain, Size: 366 bytes --]

Hi,

On Mon, Mar 23, 2015 at 10:20:28AM +1100, NeilBrown wrote:
> From: NeilBrown <neilb@suse.de>
> 
> This simplifies the error paths.
> 
> Signed-off-by: NeilBrown <neilb@suse.de>

I queued this with Pavel's ACK after a rebase to current master:

http://git.infradead.org/battery-2.6.git/commit/1b7cac23419e1398eac4c28368da6671c9c4ce9d

-- Sebastian

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/14] twl4030_charger: use devres for power_supply_register and kzalloc.
@ 2015-07-24 14:35     ` Sebastian Reichel
  0 siblings, 0 replies; 31+ messages in thread
From: Sebastian Reichel @ 2015-07-24 14:35 UTC (permalink / raw)
  To: NeilBrown
  Cc: NeilBrown, linux-api, linux-kernel, GTA04 owners, inux-pm,
	Pavel Machek, linux-omap, Lee Jones

[-- Attachment #1: Type: text/plain, Size: 405 bytes --]

Hi,

On Mon, Mar 23, 2015 at 10:20:28AM +1100, NeilBrown wrote:
> From: NeilBrown <neilb@suse.de>
> 
> Final allocations/registrations are now managed by devres.
> 
> Signed-off-by: NeilBrown <neilb@suse.de>

Thanks for the patch, rebased to current master and queued with
Pavel's ACK:

http://git.infradead.org/battery-2.6.git/commit/325b50aa5d1c7dae57d1e44defdbacd1e2bcabde

-- Sebastian

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/14] twl4030_charger: use devres for power_supply_register and kzalloc.
@ 2015-07-24 14:35     ` Sebastian Reichel
  0 siblings, 0 replies; 31+ messages in thread
From: Sebastian Reichel @ 2015-07-24 14:35 UTC (permalink / raw)
  To: NeilBrown
  Cc: NeilBrown, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, GTA04 owners,
	inux-pm-u79uwXL29TY76Z2rM5mHXA, Pavel Machek,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, Lee Jones

[-- Attachment #1: Type: text/plain, Size: 447 bytes --]

Hi,

On Mon, Mar 23, 2015 at 10:20:28AM +1100, NeilBrown wrote:
> From: NeilBrown <neilb-l3A5Bk7waGM@public.gmane.org>
> 
> Final allocations/registrations are now managed by devres.
> 
> Signed-off-by: NeilBrown <neilb-l3A5Bk7waGM@public.gmane.org>

Thanks for the patch, rebased to current master and queued with
Pavel's ACK:

http://git.infradead.org/battery-2.6.git/commit/325b50aa5d1c7dae57d1e44defdbacd1e2bcabde

-- Sebastian

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/14] Enhance twl4030_charger functionality. - V2
@ 2015-07-24 14:44   ` Sebastian Reichel
  0 siblings, 0 replies; 31+ messages in thread
From: Sebastian Reichel @ 2015-07-24 14:44 UTC (permalink / raw)
  To: NeilBrown
  Cc: linux-api, linux-kernel, GTA04 owners, inux-pm, Pavel Machek,
	linux-omap, Lee Jones

[-- Attachment #1: Type: text/plain, Size: 372 bytes --]

Hi Neil,

On Mon, Mar 23, 2015 at 10:20:28AM +1100, NeilBrown wrote:
> here is V2 of my patches to improve the twl4030 charger.
> They include improved documentation and removal of changes
> to the CVENAC bit which I didn't properly understand.

I rebased and queued patches 1 and 2. Can you rebase the
other patches and take care of the remaining comments?

-- Sebastian

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/14] Enhance twl4030_charger functionality. - V2
@ 2015-07-24 14:44   ` Sebastian Reichel
  0 siblings, 0 replies; 31+ messages in thread
From: Sebastian Reichel @ 2015-07-24 14:44 UTC (permalink / raw)
  To: NeilBrown
  Cc: linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, GTA04 owners,
	inux-pm-u79uwXL29TY76Z2rM5mHXA, Pavel Machek,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, Lee Jones

[-- Attachment #1: Type: text/plain, Size: 372 bytes --]

Hi Neil,

On Mon, Mar 23, 2015 at 10:20:28AM +1100, NeilBrown wrote:
> here is V2 of my patches to improve the twl4030 charger.
> They include improved documentation and removal of changes
> to the CVENAC bit which I didn't properly understand.

I rebased and queued patches 1 and 2. Can you rebase the
other patches and take care of the remaining comments?

-- Sebastian

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Gta04-owner] [PATCH 08/14] twl4030_charger: allow max_current to be managed via sysfs.
  2015-03-23 12:14     ` jake42
@ 2015-07-29 22:10       ` NeilBrown
  -1 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-07-29 22:10 UTC (permalink / raw)
  To: jake42
  Cc: Sebastian Reichel, linux-api, linux-kernel, inux-pm,
	Pavel Machek, linux-omap, Lee Jones,
	List for communicating with real GTA04 owners

On Mon, 23 Mar 2015 13:14:50 +0100 jake42
<jake42@rommel.stw.uni-erlangen.de> wrote:

> Hello Neil,
> 
> some suggestions:
> 
> On 23.03.2015 00:20, NeilBrown wrote:
> > From: NeilBrown <neilb@suse.de>
> > diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030
> > b/Documentation/ABI/testing/sysfs-class-power-twl4030
> > new file mode 100644
> > index 000000000000..06092209d851
> > --- /dev/null
> > +++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
> > @@ -0,0 +1,15 @@
> > +What: /sys/class/power_supply/twl4030_ac/max_current
> > +      /sys/class/power_supply/twl4030_usb/max_current
> > +Description:
> > +	Read/Write limit on current which which may
> one less which                        ^^
> > +	be drawn from the ac (Accessory Charger) or
> > +	USB port.
> > +
> > +	Value is in micro-Amps.
> > +
> > +	Value is set automatically to an appropriate
> > +	value when a cable is plugged on unplugged.
> s/on/or                               ^^
> > +
> > +	Value can the set by writing to the attribute.
>                    ^^ be set?
> > +	The change will only persist until the next
> > +	plug event.  These event are reported via udev.
> 
> Regards
> Jake
> 

Thanks.
I've made those two changes.

NeilBrown

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Gta04-owner] [PATCH 08/14] twl4030_charger: allow max_current to be managed via sysfs.
@ 2015-07-29 22:10       ` NeilBrown
  0 siblings, 0 replies; 31+ messages in thread
From: NeilBrown @ 2015-07-29 22:10 UTC (permalink / raw)
  To: jake42
  Cc: Sebastian Reichel, linux-api, linux-kernel, inux-pm,
	Pavel Machek, linux-omap, Lee Jones,
	List for communicating with real GTA04 owners

On Mon, 23 Mar 2015 13:14:50 +0100 jake42
<jake42@rommel.stw.uni-erlangen.de> wrote:

> Hello Neil,
> 
> some suggestions:
> 
> On 23.03.2015 00:20, NeilBrown wrote:
> > From: NeilBrown <neilb@suse.de>
> > diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030
> > b/Documentation/ABI/testing/sysfs-class-power-twl4030
> > new file mode 100644
> > index 000000000000..06092209d851
> > --- /dev/null
> > +++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
> > @@ -0,0 +1,15 @@
> > +What: /sys/class/power_supply/twl4030_ac/max_current
> > +      /sys/class/power_supply/twl4030_usb/max_current
> > +Description:
> > +	Read/Write limit on current which which may
> one less which                        ^^
> > +	be drawn from the ac (Accessory Charger) or
> > +	USB port.
> > +
> > +	Value is in micro-Amps.
> > +
> > +	Value is set automatically to an appropriate
> > +	value when a cable is plugged on unplugged.
> s/on/or                               ^^
> > +
> > +	Value can the set by writing to the attribute.
>                    ^^ be set?
> > +	The change will only persist until the next
> > +	plug event.  These event are reported via udev.
> 
> Regards
> Jake
> 

Thanks.
I've made those two changes.

NeilBrown

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2015-07-29 22:28 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-22 23:20 [PATCH 00/14] Enhance twl4030_charger functionality. - V2 NeilBrown
2015-03-22 23:20 ` [PATCH 05/14] twl4030_charger: split uA calculation into a function NeilBrown
2015-03-22 23:20 ` [PATCH 03/14] twl4030_charger: use runtime_pm to keep usb phy active while charging NeilBrown
2015-03-22 23:20 ` [PATCH 02/14] twl4030_charger: use devres for power_supply_register and kzalloc NeilBrown
2015-03-23 21:25   ` Pavel Machek
2015-07-24 14:35   ` Sebastian Reichel
2015-07-24 14:35     ` Sebastian Reichel
2015-03-22 23:20 ` [PATCH 01/14] twl4030_charger: use devm_request_threaded_irq NeilBrown
2015-07-24 14:34   ` Sebastian Reichel
2015-03-22 23:20 ` [PATCH 04/14] twl4030_charger: trust phy to determine when USB power is available NeilBrown
2015-03-22 23:20 ` [PATCH 14/14] twl4030_charger: assume a 'charger' can supply maximum current NeilBrown
2015-03-22 23:20 ` [PATCH 06/14] twl4030_charger: allow fine control of charger current NeilBrown
2015-03-22 23:20 ` [PATCH 10/14] twl4030_charger: enable manual enable/disable of usb charging NeilBrown
2015-03-22 23:20 ` [PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage NeilBrown
2015-03-23 21:25   ` Pavel Machek
2015-03-29 21:26     ` NeilBrown
2015-03-29 21:26       ` NeilBrown
2015-04-04  7:48       ` Pavel Machek
2015-04-04  7:48         ` Pavel Machek
2015-03-22 23:20 ` [PATCH 08/14] twl4030_charger: allow max_current to be managed via sysfs NeilBrown
2015-03-23 12:14   ` [Gta04-owner] " jake42
2015-03-23 12:14     ` jake42
2015-07-29 22:10     ` NeilBrown
2015-07-29 22:10       ` NeilBrown
2015-03-22 23:20 ` [PATCH 11/14] twl4030_charger: add software controlled linear charging mode NeilBrown
2015-03-22 23:20   ` NeilBrown
2015-03-22 23:20 ` [PATCH 09/14] twl4030_charger: only draw USB current as negotiated with host NeilBrown
2015-03-22 23:20 ` [PATCH 07/14] twl4030_charger: distinguish between USB current and 'AC' current NeilBrown
2015-03-22 23:20 ` [PATCH 12/14] twl4030_charger: add ac/mode to match usb/mode NeilBrown
2015-07-24 14:44 ` [PATCH 00/14] Enhance twl4030_charger functionality. - V2 Sebastian Reichel
2015-07-24 14:44   ` Sebastian Reichel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.