aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neil@brown.name>2015-07-29 20:11:24 -0400
committerSebastian Reichel <sre@kernel.org>2015-08-04 23:20:36 -0400
commit22d4c33f7335ddf6deda26630c78650e133bfe72 (patch)
tree1206e8ba5bc4e273c1125e039035cd7c4a23705f
parentaca3c3546396b305fff79f09883cff48a908aac0 (diff)
twl4030_charger: enable manual enable/disable of usb charging.
'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 <neil@brown.name> Signed-off-by: Sebastian Reichel <sre@kernel.org>
-rw-r--r--Documentation/ABI/testing/sysfs-class-power-twl403011
-rw-r--r--drivers/power/twl4030_charger.c59
2 files changed, 70 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 b/Documentation/ABI/testing/sysfs-class-power-twl4030
index 0331bba4605d..40e0f919cbde 100644
--- a/Documentation/ABI/testing/sysfs-class-power-twl4030
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -13,3 +13,14 @@ Description:
13 Value can the set by writing to the attribute. 13 Value can the set by writing to the attribute.
14 The change will only persist until the next 14 The change will only persist until the next
15 plug event. These event are reported via udev. 15 plug event. These event are reported via udev.
16
17
18What: /sys/class/power_supply/twl4030_usb/mode
19Description:
20 Changing mode for USB port.
21 Writing to this can disable charging.
22
23 Possible values are:
24 "auto" - draw power as appropriate for detected
25 power source and battery status.
26 "off" - do not draw any power.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index b0a50adebfda..6fa928ed3128 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -109,10 +109,16 @@ struct twl4030_bci {
109 unsigned int ichg_eoc, ichg_lo, ichg_hi; 109 unsigned int ichg_eoc, ichg_lo, ichg_hi;
110 unsigned int usb_cur, ac_cur; 110 unsigned int usb_cur, ac_cur;
111 bool ac_is_active; 111 bool ac_is_active;
112 int usb_mode; /* charging mode requested */
113#define CHARGE_OFF 0
114#define CHARGE_AUTO 1
112 115
113 unsigned long event; 116 unsigned long event;
114}; 117};
115 118
119/* strings for 'usb_mode' values */
120static char *modes[] = { "off", "auto" };
121
116/* 122/*
117 * clear and set bits on an given register on a given module 123 * clear and set bits on an given register on a given module
118 */ 124 */
@@ -386,6 +392,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
386{ 392{
387 int ret; 393 int ret;
388 394
395 if (bci->usb_mode == CHARGE_OFF)
396 enable = false;
389 if (enable && !IS_ERR_OR_NULL(bci->transceiver)) { 397 if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
390 398
391 twl4030_charger_update_current(bci); 399 twl4030_charger_update_current(bci);
@@ -629,6 +637,53 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
629 return NOTIFY_OK; 637 return NOTIFY_OK;
630} 638}
631 639
640/*
641 * sysfs charger enabled store
642 */
643static ssize_t
644twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr,
645 const char *buf, size_t n)
646{
647 struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
648 int mode;
649 int status;
650
651 if (sysfs_streq(buf, modes[0]))
652 mode = 0;
653 else if (sysfs_streq(buf, modes[1]))
654 mode = 1;
655 else
656 return -EINVAL;
657 twl4030_charger_enable_usb(bci, false);
658 bci->usb_mode = mode;
659 status = twl4030_charger_enable_usb(bci, true);
660 return (status == 0) ? n : status;
661}
662
663/*
664 * sysfs charger enabled show
665 */
666static ssize_t
667twl4030_bci_mode_show(struct device *dev,
668 struct device_attribute *attr, char *buf)
669{
670 struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
671 int len = 0;
672 int i;
673
674 for (i = 0; i < ARRAY_SIZE(modes); i++)
675 if (bci->usb_mode == i)
676 len += snprintf(buf+len, PAGE_SIZE-len,
677 "[%s] ", modes[i]);
678 else
679 len += snprintf(buf+len, PAGE_SIZE-len,
680 "%s ", modes[i]);
681 buf[len-1] = '\n';
682 return len;
683}
684static DEVICE_ATTR(mode, 0644, twl4030_bci_mode_show,
685 twl4030_bci_mode_store);
686
632static int twl4030_charger_get_current(void) 687static int twl4030_charger_get_current(void)
633{ 688{
634 int curr; 689 int curr;
@@ -815,6 +870,7 @@ static int twl4030_bci_probe(struct platform_device *pdev)
815 bci->usb_cur = 500000; /* 500mA */ 870 bci->usb_cur = 500000; /* 500mA */
816 else 871 else
817 bci->usb_cur = 100000; /* 100mA */ 872 bci->usb_cur = 100000; /* 100mA */
873 bci->usb_mode = CHARGE_AUTO;
818 874
819 bci->dev = &pdev->dev; 875 bci->dev = &pdev->dev;
820 bci->irq_chg = platform_get_irq(pdev, 0); 876 bci->irq_chg = platform_get_irq(pdev, 0);
@@ -898,6 +954,8 @@ static int twl4030_bci_probe(struct platform_device *pdev)
898 twl4030_charger_update_current(bci); 954 twl4030_charger_update_current(bci);
899 if (device_create_file(&bci->usb->dev, &dev_attr_max_current)) 955 if (device_create_file(&bci->usb->dev, &dev_attr_max_current))
900 dev_warn(&pdev->dev, "could not create sysfs file\n"); 956 dev_warn(&pdev->dev, "could not create sysfs file\n");
957 if (device_create_file(&bci->usb->dev, &dev_attr_mode))
958 dev_warn(&pdev->dev, "could not create sysfs file\n");
901 if (device_create_file(&bci->ac->dev, &dev_attr_max_current)) 959 if (device_create_file(&bci->ac->dev, &dev_attr_max_current))
902 dev_warn(&pdev->dev, "could not create sysfs file\n"); 960 dev_warn(&pdev->dev, "could not create sysfs file\n");
903 961
@@ -926,6 +984,7 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
926 twl4030_charger_enable_backup(0, 0); 984 twl4030_charger_enable_backup(0, 0);
927 985
928 device_remove_file(&bci->usb->dev, &dev_attr_max_current); 986 device_remove_file(&bci->usb->dev, &dev_attr_max_current);
987 device_remove_file(&bci->usb->dev, &dev_attr_mode);
929 device_remove_file(&bci->ac->dev, &dev_attr_max_current); 988 device_remove_file(&bci->ac->dev, &dev_attr_max_current);
930 /* mask interrupts */ 989 /* mask interrupts */
931 twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, 990 twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,