[Gta04-owner] [PATCH 3.2] twl4030_charger: set usb max current through sysfs

Andreas Kemnade andreas at kemnade.info
Mon Mar 26 23:00:15 CEST 2012


It provides a sysfs file here:
/sys/bus/platform/devices/twl4030_bci/max_current
/sys/class/power_supply/twl4030_usb/device/max_current
(symlinked stuff)

Into this sysfs file the maximum usb current in uA can be written or read.
The setting stays the same when the usb plug is disconnected and
reconnected.

Signed-off-by: Andreas Kemnade <andreas at kemnade.info>
---
 drivers/power/twl4030_charger.c |   95 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 95 insertions(+), 0 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index c6dee6d..1c26387 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -30,6 +30,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_BCIAUTOWEN	BIT(5)
 #define TWL4030_CONFIG_DONE	BIT(4)
@@ -353,6 +358,91 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 	return NOTIFY_OK;
 }
 
+
+#ifdef CONFIG_SYSFS
+/*
+ * sysfs max_current show
+ */
+static ssize_t twl4030_bci_max_current_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	int status = 0;
+	unsigned int cur;
+	u8 c1, c2;
+	u8 bcictl1;
+
+	status = twl4030_bci_read(TWL4030_BCIIREF1, &c1);
+	if (status < 0)
+		return status;
+	status = twl4030_bci_read(TWL4030_BCIIREF2, &c2);
+	if (status < 0)
+		return status;
+	cur = (c2 & 1) ? 256 : 0;
+	cur += c1;
+	cur *= 1665;
+	status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
+	if (status < 0)
+		return status;
+	if (bcictl1 & TWL4030_CGAIN)
+		cur *= 2;
+	if (status == 0)
+		return scnprintf(buf, PAGE_SIZE, "%u\n", cur);
+	return status;
+}
+
+static int twl4030_charger_set_max_current(int cur)
+{
+	u8 bcictl1;
+	int status;
+	/* get setting of CGAIN bit */
+	status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
+	if (status < 0)
+		return status;
+	if (bcictl1 & TWL4030_CGAIN)
+		cur /= 2;
+	cur = cur / 1665;
+	if (cur > 511)
+		return -EINVAL;
+	if (cur < 0)
+		return -EINVAL;
+	/* disable write protection for one write access for BCIIREF */
+	status = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, 0xE7,
+			TWL4030_BCIMFKEY);
+	if (status < 0)
+		return status;
+	status = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
+			(cur & 0x100) ? 3 : 2, TWL4030_BCIIREF2);
+	if (status < 0)
+		return status;
+	/* disable write protection for one write access for BCIIREF */
+	status = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, 0xE7,
+			TWL4030_BCIMFKEY);
+	if (status < 0)
+		return status;
+	status = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, cur & 0xff,
+			TWL4030_BCIIREF1);
+	return status;
+}
+
+/*
+ * sysfs max_current store
+ */
+static ssize_t
+twl4030_bci_max_current_store(struct device *dev, struct device_attribute *attr,
+	const char *buf, size_t n)
+{
+	unsigned int cur = 0;
+	int status = 0;
+	if (1 != sscanf(buf, "%u", &cur))
+		return -EINVAL;
+	status = twl4030_charger_set_max_current(cur);
+	return (status == 0) ? n : status;
+}
+
+static DEVICE_ATTR(max_current, 0644, twl4030_bci_max_current_show,
+			twl4030_bci_max_current_store);
+#endif /* CONFIG_SYSFS */
+
 /*
  * TI provided formulas:
  * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
@@ -567,6 +657,11 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 			       TWL4030_INTERRUPTS_BCIIMR2A);
 	if (ret < 0)
 		dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
+#ifdef CONFIG_SYSFS
+	if (device_create_file(&pdev->dev, &dev_attr_max_current))
+		dev_warn(&pdev->dev, "could not create sysfs file\n");
+#endif
+
 
 	twl4030_charger_enable_ac(true);
 	twl4030_charger_enable_usb(bci, true);
-- 
1.7.2.5



More information about the Gta04-owner mailing list