[Gta04-owner] [PATCH] twl4030_charger: add software controlled linear charging mode.
Andreas Kemnade
andreas at kemnade.info
Thu Sep 26 20:09:32 CEST 2013
Hi,
On Thu, 26 Sep 2013 15:19:40 +0200
"Dr. H. Nikolaus Schaller" <hns at goldelico.com> wrote:
> Hi Ben,
> thanks for the patch. I have applied it and now the /sys/.../lin file is back again.
>
> One question (maybe to Andreas): "on" sets the variable do_lin=1 and "auto" resets it if it was on. But "off" does not set it to 0. Is this intended behaviour?
>
yes, that is intended behaviour:
off= manual off (and no auto on, prevented by do_lin still =0 )
auto=automatic charge mode
on = manual on
btw: it is possible to keep the gta04 in suspend mode with do_lin=on when power supply goes on and off. Tested on my bike on the very hilly and windy roads around the North Cape.
> ---
> > drivers/power/twl4030_charger.c | 100 ++++++++++++++++++++++++++++++++++++----
> > 1 file changed, 92 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
> > index e9de746..33be55d 100644
> > --- a/drivers/power/twl4030_charger.c
> > +++ b/drivers/power/twl4030_charger.c
> > @@ -24,6 +24,8 @@
> > #include <linux/usb/otg.h>
> > #include <linux/regulator/machine.h>
> >
> > +#define TWL4030_BCIMDEN 0x00
> > +#define TWL4030_BCIMDKEY 0x01
> > #define TWL4030_BCIMSTATEC 0x02
> > #define TWL4030_BCIICHG 0x08
> > #define TWL4030_BCIVAC 0x0a
> > @@ -34,6 +36,8 @@
> > #define TWL4030_BCIIREF1 0x27
> > #define TWL4030_BCIIREF2 0x28
> > #define TWL4030_BCIMFKEY 0x11
> > +#define TWL4030_BCIMFEN3 0x14
> > +#define TWL4030_BCIWDKEY 0x21
> >
> >
> >
> > @@ -43,6 +47,7 @@
> > #define TWL4030_BCIAUTOAC BIT(0)
> > #define TWL4030_CGAIN BIT(5)
> > #define TWL4030_USBFASTMCHG BIT(2)
> > +#define TWL4030_USBSLOWMCHG BIT(1)
> > #define TWL4030_STS_VBUS BIT(7)
> > #define TWL4030_STS_USB_ID BIT(2)
> > #define TWL4030_BBCHEN BIT(4)
> > @@ -84,6 +89,7 @@ static bool allow_usb;
> > module_param(allow_usb, bool, 0644);
> > MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
> >
> > +static int do_lin;
> > static int default_usb_current = 100000;
> > module_param(default_usb_current, int, 0644);
> > MODULE_PARM_DESC(default_usb_current, "Default usb current for newly connected devices in uA");
> > @@ -262,16 +268,37 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
> > twl4030_charger_set_max_current(600000);
> > else
> > twl4030_charger_set_max_current(default_usb_current);
> > - /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
> > - ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
> > - if (ret < 0)
> > - return ret;
> > -
> > + if (!do_lin) {
> > + /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
> > + ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
> > + if (ret < 0)
> > + return ret;
> > + }
> > /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
> > - ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0,
> > + ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE,
> > + TWL4030_USBSLOWMCHG,
> > TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
> > + if (do_lin) {
> > + ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x33,
> > + TWL4030_BCIWDKEY);
> > + ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
> > + TWL4030_BCIMDKEY);
> > + ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x26,
> > + TWL4030_BCIMDKEY);
> > + ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf3,
> > + TWL4030_BCIWDKEY);
> > + ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x9c,
> > + TWL4030_BCIMFKEY);
> > + ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf0,
> > + TWL4030_BCIMFEN3);
> > + }
> > } else {
> > - ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
> > + if (!do_lin) {
> > + ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
> > + } else {
> > + ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
> > + TWL4030_BCIMDKEY);
> > + }
> > if (bci->usb_enabled) {
> > regulator_disable(bci->usb_reg);
> > bci->usb_enabled = 0;
> > @@ -427,6 +454,58 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
> > return NOTIFY_OK;
> > }
> >
> > +static ssize_t
> > +twl4030_bci_lin_show(struct device *dev, struct device_attribute *attr,
> > + char *buf)
> > +{
> > + int ret = -EINVAL;
> > + u8 val;
> > + twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val, TWL4030_BCIMDEN);
> > + ret = sprintf(buf, "%d\n", (int)val);
> > + return ret;
> > +}
> > +
> > +static ssize_t
> > +twl4030_bci_lin_store(struct device *dev, struct device_attribute *attr,
> > + const char *buf, size_t n)
> > +{
> > + unsigned long flags;
> > + int status = 0;
> > + if (sysfs_streq(buf, "on")) {
> > + status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0x30,
> > + TWL4030_PM_MASTER_BOOT_BCI);
> > +
> > + status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x33,
> > + TWL4030_BCIWDKEY);
> > + status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
> > + TWL4030_BCIMDKEY);
> > + status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x26,
> > + TWL4030_BCIMDKEY);
> > + status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf3,
> > + TWL4030_BCIWDKEY);
> > + do_lin = 1;
> > +
> > + } else if (sysfs_streq(buf, "off")) {
> > + status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
> > + TWL4030_BCIMDKEY);
>
> do_lin = 0; ????
no.
>
> > + } else if (sysfs_streq(buf, "auto")) {
> > + if (do_lin) {
> > + struct twl4030_bci *bci = dev_get_drvdata(dev);
> > + status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
> > + 0x2a, TWL4030_BCIMDKEY);
> > + do_lin = 0;
> > + twl4030_charger_enable_usb(bci, true);
> > + }
> > + } else {
> > + return -EINVAL;
> > + }
> > +
> > +
> > + return (status == 0) ? n : status;
> > +}
> > +
> > +static DEVICE_ATTR(lin, 0644, twl4030_bci_lin_show, twl4030_bci_lin_store);
> > +
> >
> > /*
> > * sysfs max_current store
> > @@ -524,6 +603,7 @@ static int twl4030_bci_get_property(struct power_supply *psy,
> > int is_charging;
> > int state;
> > int ret;
> > + u8 i2cval;
> >
> > state = twl4030bci_state(bci);
> > if (state < 0)
> > @@ -560,7 +640,8 @@ static int twl4030_bci_get_property(struct power_supply *psy,
> > }
> > break;
> > case POWER_SUPPLY_PROP_CURRENT_NOW:
> > - if (!is_charging)
> > + twl4030_bci_read(TWL4030_BCIMFEN3, &i2cval);
> > + if ((!is_charging) && (i2cval == 0))
> > return -ENODATA;
> > /* current measurement is shared between AC and USB */
> > ret = twl4030_charger_get_current();
> > @@ -673,6 +754,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
> >
> > if (device_create_file(&pdev->dev, &dev_attr_max_current))
> > dev_warn(&pdev->dev, "could not create sysfs file\n");
> > + if (device_create_file(&pdev->dev, &dev_attr_lin))
> > + dev_warn(&pdev->dev, "could not create sysfs file\n");
> >
> >
> > twl4030_charger_enable_ac(true);
> > @@ -704,6 +787,7 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
> > {
> > struct twl4030_bci *bci = platform_get_drvdata(pdev);
> > device_remove_file(&pdev->dev, &dev_attr_max_current);
> > + device_remove_file(&pdev->dev, &dev_attr_lin);
> > twl4030_charger_enable_ac(false);
> > twl4030_charger_enable_usb(bci, false);
> > twl4030_charger_enable_backup(0, 0);
> > --
> > 1.7.12
> >
> > _______________________________________________
> > Gta04-owner mailing list
> > Gta04-owner at goldelico.com
> > http://lists.goldelico.com/mailman/listinfo/gta04-owner
>
>
Greetings
Andreas Kemnade
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.goldelico.com/pipermail/gta04-owner/attachments/20130926/ae362810/attachment.bin>
More information about the Gta04-owner
mailing list