Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

NeilBrown and committed by
Sebastian Reichel
b04b908d 7f4a633d

+37 -8
+10
Documentation/ABI/testing/sysfs-class-power-twl4030
··· 33 33 This is useful for unstable power sources 34 34 such as bicycle dynamo, but care should 35 35 be taken that battery is not over-charged. 36 + 37 + What: /sys/class/power_supply/twl4030_ac/mode 38 + Description: 39 + Changing mode for 'ac' port. 40 + Writing to this can disable charging. 41 + 42 + Possible values are: 43 + "auto" - draw power as appropriate for detected 44 + power source and battery status. 45 + "off" - do not draw any power.
+27 -8
drivers/power/twl4030_charger.c
··· 114 114 unsigned int ichg_eoc, ichg_lo, ichg_hi; 115 115 unsigned int usb_cur, ac_cur; 116 116 bool ac_is_active; 117 - int usb_mode; /* charging mode requested */ 117 + int usb_mode, ac_mode; /* charging mode requested */ 118 118 #define CHARGE_OFF 0 119 119 #define CHARGE_AUTO 1 120 120 #define CHARGE_LINEAR 2 ··· 459 459 /* 460 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 464 int ret; 465 + 466 + if (bci->ac_mode == CHARGE_OFF) 467 + enable = false; 465 468 466 469 if (enable) 467 470 ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC); ··· 691 688 mode = 2; 692 689 else 693 690 return -EINVAL; 694 - twl4030_charger_enable_usb(bci, false); 695 - bci->usb_mode = mode; 696 - status = twl4030_charger_enable_usb(bci, true); 691 + if (dev == &bci->ac->dev) { 692 + if (mode == 2) 693 + return -EINVAL; 694 + twl4030_charger_enable_ac(bci, false); 695 + bci->ac_mode = mode; 696 + status = twl4030_charger_enable_ac(bci, true); 697 + } else { 698 + twl4030_charger_enable_usb(bci, false); 699 + bci->usb_mode = mode; 700 + status = twl4030_charger_enable_usb(bci, true); 701 + } 697 702 return (status == 0) ? n : status; 698 703 } 699 704 ··· 715 704 struct twl4030_bci *bci = dev_get_drvdata(dev->parent); 716 705 int len = 0; 717 706 int i; 707 + int mode = bci->usb_mode; 708 + 709 + if (dev == &bci->ac->dev) 710 + mode = bci->ac_mode; 718 711 719 712 for (i = 0; i < ARRAY_SIZE(modes); i++) 720 - if (bci->usb_mode == i) 713 + if (mode == i) 721 714 len += snprintf(buf+len, PAGE_SIZE-len, 722 715 "[%s] ", modes[i]); 723 716 else ··· 931 916 else 932 917 bci->usb_cur = 100000; /* 100mA */ 933 918 bci->usb_mode = CHARGE_AUTO; 919 + bci->ac_mode = CHARGE_AUTO; 934 920 935 921 bci->dev = &pdev->dev; 936 922 bci->irq_chg = platform_get_irq(pdev, 0); ··· 1017 1001 dev_warn(&pdev->dev, "could not create sysfs file\n"); 1018 1002 if (device_create_file(&bci->usb->dev, &dev_attr_mode)) 1019 1003 dev_warn(&pdev->dev, "could not create sysfs file\n"); 1004 + if (device_create_file(&bci->ac->dev, &dev_attr_mode)) 1005 + dev_warn(&pdev->dev, "could not create sysfs file\n"); 1020 1006 if (device_create_file(&bci->ac->dev, &dev_attr_max_current)) 1021 1007 dev_warn(&pdev->dev, "could not create sysfs file\n"); 1022 1008 1023 - twl4030_charger_enable_ac(true); 1009 + twl4030_charger_enable_ac(bci, true); 1024 1010 if (!IS_ERR_OR_NULL(bci->transceiver)) 1025 1011 twl4030_bci_usb_ncb(&bci->usb_nb, 1026 1012 bci->transceiver->last_event, ··· 1042 1024 { 1043 1025 struct twl4030_bci *bci = platform_get_drvdata(pdev); 1044 1026 1045 - twl4030_charger_enable_ac(false); 1027 + twl4030_charger_enable_ac(bci, false); 1046 1028 twl4030_charger_enable_usb(bci, false); 1047 1029 twl4030_charger_enable_backup(0, 0); 1048 1030 1049 1031 device_remove_file(&bci->usb->dev, &dev_attr_max_current); 1050 1032 device_remove_file(&bci->usb->dev, &dev_attr_mode); 1051 1033 device_remove_file(&bci->ac->dev, &dev_attr_max_current); 1034 + device_remove_file(&bci->ac->dev, &dev_attr_mode); 1052 1035 /* mask interrupts */ 1053 1036 twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, 1054 1037 TWL4030_INTERRUPTS_BCIIMR1A);