diff options
author | NeilBrown <neil@brown.name> | 2015-07-29 20:11:24 -0400 |
---|---|---|
committer | Sebastian Reichel <sre@kernel.org> | 2015-08-04 23:21:57 -0400 |
commit | b04b908d8a2901c2cc59db87defd9c08bd4293cc (patch) | |
tree | cc66542acca233a902d606d775b66c31a42193f9 /drivers/power | |
parent | 7f4a633d21331155ee06c5ee44749ed35a3a3cc5 (diff) |
twl4030_charger: add ac/mode to match usb/mode
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 <neil@brown.name>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/twl4030_charger.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index de5430deaf23..68117ad23564 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c | |||
@@ -114,7 +114,7 @@ struct twl4030_bci { | |||
114 | unsigned int ichg_eoc, ichg_lo, ichg_hi; | 114 | unsigned int ichg_eoc, ichg_lo, ichg_hi; |
115 | unsigned int usb_cur, ac_cur; | 115 | unsigned int usb_cur, ac_cur; |
116 | bool ac_is_active; | 116 | bool ac_is_active; |
117 | int usb_mode; /* charging mode requested */ | 117 | int usb_mode, ac_mode; /* charging mode requested */ |
118 | #define CHARGE_OFF 0 | 118 | #define CHARGE_OFF 0 |
119 | #define CHARGE_AUTO 1 | 119 | #define CHARGE_AUTO 1 |
120 | #define CHARGE_LINEAR 2 | 120 | #define CHARGE_LINEAR 2 |
@@ -459,10 +459,13 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) | |||
459 | /* | 459 | /* |
460 | * Enable/Disable AC Charge funtionality. | 460 | * Enable/Disable AC Charge funtionality. |
461 | */ | 461 | */ |
462 | static int twl4030_charger_enable_ac(bool enable) | 462 | static int twl4030_charger_enable_ac(struct twl4030_bci *bci, bool enable) |
463 | { | 463 | { |
464 | int ret; | 464 | int ret; |
465 | 465 | ||
466 | if (bci->ac_mode == CHARGE_OFF) | ||
467 | enable = false; | ||
468 | |||
466 | if (enable) | 469 | if (enable) |
467 | ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC); | 470 | ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC); |
468 | else | 471 | else |
@@ -688,9 +691,17 @@ twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr, | |||
688 | mode = 2; | 691 | mode = 2; |
689 | else | 692 | else |
690 | return -EINVAL; | 693 | return -EINVAL; |
691 | twl4030_charger_enable_usb(bci, false); | 694 | if (dev == &bci->ac->dev) { |
692 | bci->usb_mode = mode; | 695 | if (mode == 2) |
693 | status = twl4030_charger_enable_usb(bci, true); | 696 | return -EINVAL; |
697 | twl4030_charger_enable_ac(bci, false); | ||
698 | bci->ac_mode = mode; | ||
699 | status = twl4030_charger_enable_ac(bci, true); | ||
700 | } else { | ||
701 | twl4030_charger_enable_usb(bci, false); | ||
702 | bci->usb_mode = mode; | ||
703 | status = twl4030_charger_enable_usb(bci, true); | ||
704 | } | ||
694 | return (status == 0) ? n : status; | 705 | return (status == 0) ? n : status; |
695 | } | 706 | } |
696 | 707 | ||
@@ -704,9 +715,13 @@ twl4030_bci_mode_show(struct device *dev, | |||
704 | struct twl4030_bci *bci = dev_get_drvdata(dev->parent); | 715 | struct twl4030_bci *bci = dev_get_drvdata(dev->parent); |
705 | int len = 0; | 716 | int len = 0; |
706 | int i; | 717 | int i; |
718 | int mode = bci->usb_mode; | ||
719 | |||
720 | if (dev == &bci->ac->dev) | ||
721 | mode = bci->ac_mode; | ||
707 | 722 | ||
708 | for (i = 0; i < ARRAY_SIZE(modes); i++) | 723 | for (i = 0; i < ARRAY_SIZE(modes); i++) |
709 | if (bci->usb_mode == i) | 724 | if (mode == i) |
710 | len += snprintf(buf+len, PAGE_SIZE-len, | 725 | len += snprintf(buf+len, PAGE_SIZE-len, |
711 | "[%s] ", modes[i]); | 726 | "[%s] ", modes[i]); |
712 | else | 727 | else |
@@ -916,6 +931,7 @@ static int twl4030_bci_probe(struct platform_device *pdev) | |||
916 | else | 931 | else |
917 | bci->usb_cur = 100000; /* 100mA */ | 932 | bci->usb_cur = 100000; /* 100mA */ |
918 | bci->usb_mode = CHARGE_AUTO; | 933 | bci->usb_mode = CHARGE_AUTO; |
934 | bci->ac_mode = CHARGE_AUTO; | ||
919 | 935 | ||
920 | bci->dev = &pdev->dev; | 936 | bci->dev = &pdev->dev; |
921 | bci->irq_chg = platform_get_irq(pdev, 0); | 937 | bci->irq_chg = platform_get_irq(pdev, 0); |
@@ -1001,10 +1017,12 @@ static int twl4030_bci_probe(struct platform_device *pdev) | |||
1001 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 1017 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
1002 | if (device_create_file(&bci->usb->dev, &dev_attr_mode)) | 1018 | if (device_create_file(&bci->usb->dev, &dev_attr_mode)) |
1003 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 1019 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
1020 | if (device_create_file(&bci->ac->dev, &dev_attr_mode)) | ||
1021 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | ||
1004 | if (device_create_file(&bci->ac->dev, &dev_attr_max_current)) | 1022 | if (device_create_file(&bci->ac->dev, &dev_attr_max_current)) |
1005 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 1023 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
1006 | 1024 | ||
1007 | twl4030_charger_enable_ac(true); | 1025 | twl4030_charger_enable_ac(bci, true); |
1008 | if (!IS_ERR_OR_NULL(bci->transceiver)) | 1026 | if (!IS_ERR_OR_NULL(bci->transceiver)) |
1009 | twl4030_bci_usb_ncb(&bci->usb_nb, | 1027 | twl4030_bci_usb_ncb(&bci->usb_nb, |
1010 | bci->transceiver->last_event, | 1028 | bci->transceiver->last_event, |
@@ -1024,13 +1042,14 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) | |||
1024 | { | 1042 | { |
1025 | struct twl4030_bci *bci = platform_get_drvdata(pdev); | 1043 | struct twl4030_bci *bci = platform_get_drvdata(pdev); |
1026 | 1044 | ||
1027 | twl4030_charger_enable_ac(false); | 1045 | twl4030_charger_enable_ac(bci, false); |
1028 | twl4030_charger_enable_usb(bci, false); | 1046 | twl4030_charger_enable_usb(bci, false); |
1029 | twl4030_charger_enable_backup(0, 0); | 1047 | twl4030_charger_enable_backup(0, 0); |
1030 | 1048 | ||
1031 | device_remove_file(&bci->usb->dev, &dev_attr_max_current); | 1049 | device_remove_file(&bci->usb->dev, &dev_attr_max_current); |
1032 | device_remove_file(&bci->usb->dev, &dev_attr_mode); | 1050 | device_remove_file(&bci->usb->dev, &dev_attr_mode); |
1033 | device_remove_file(&bci->ac->dev, &dev_attr_max_current); | 1051 | device_remove_file(&bci->ac->dev, &dev_attr_max_current); |
1052 | device_remove_file(&bci->ac->dev, &dev_attr_mode); | ||
1034 | /* mask interrupts */ | 1053 | /* mask interrupts */ |
1035 | twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, | 1054 | twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, |
1036 | TWL4030_INTERRUPTS_BCIIMR1A); | 1055 | TWL4030_INTERRUPTS_BCIIMR1A); |