|
@@ -109,10 +109,16 @@ struct twl4030_bci {
|
|
unsigned int ichg_eoc, ichg_lo, ichg_hi;
|
|
unsigned int ichg_eoc, ichg_lo, ichg_hi;
|
|
unsigned int usb_cur, ac_cur;
|
|
unsigned int usb_cur, ac_cur;
|
|
bool ac_is_active;
|
|
bool ac_is_active;
|
|
|
|
+ int usb_mode; /* charging mode requested */
|
|
|
|
+#define CHARGE_OFF 0
|
|
|
|
+#define CHARGE_AUTO 1
|
|
|
|
|
|
unsigned long event;
|
|
unsigned long event;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* strings for 'usb_mode' values */
|
|
|
|
+static char *modes[] = { "off", "auto" };
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* clear and set bits on an given register on a given module
|
|
* clear and set bits on an given register on a given module
|
|
*/
|
|
*/
|
|
@@ -386,6 +392,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
+ if (bci->usb_mode == CHARGE_OFF)
|
|
|
|
+ enable = false;
|
|
if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
|
|
if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
|
|
|
|
|
|
twl4030_charger_update_current(bci);
|
|
twl4030_charger_update_current(bci);
|
|
@@ -629,6 +637,53 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
|
|
return NOTIFY_OK;
|
|
return NOTIFY_OK;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * sysfs charger enabled store
|
|
|
|
+ */
|
|
|
|
+static ssize_t
|
|
|
|
+twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
+ const char *buf, size_t n)
|
|
|
|
+{
|
|
|
|
+ struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
|
|
|
|
+ int mode;
|
|
|
|
+ int status;
|
|
|
|
+
|
|
|
|
+ if (sysfs_streq(buf, modes[0]))
|
|
|
|
+ mode = 0;
|
|
|
|
+ else if (sysfs_streq(buf, modes[1]))
|
|
|
|
+ mode = 1;
|
|
|
|
+ else
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ twl4030_charger_enable_usb(bci, false);
|
|
|
|
+ bci->usb_mode = mode;
|
|
|
|
+ status = twl4030_charger_enable_usb(bci, true);
|
|
|
|
+ return (status == 0) ? n : status;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * sysfs charger enabled show
|
|
|
|
+ */
|
|
|
|
+static ssize_t
|
|
|
|
+twl4030_bci_mode_show(struct device *dev,
|
|
|
|
+ struct device_attribute *attr, char *buf)
|
|
|
|
+{
|
|
|
|
+ struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
|
|
|
|
+ int len = 0;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(modes); i++)
|
|
|
|
+ if (bci->usb_mode == i)
|
|
|
|
+ len += snprintf(buf+len, PAGE_SIZE-len,
|
|
|
|
+ "[%s] ", modes[i]);
|
|
|
|
+ else
|
|
|
|
+ len += snprintf(buf+len, PAGE_SIZE-len,
|
|
|
|
+ "%s ", modes[i]);
|
|
|
|
+ buf[len-1] = '\n';
|
|
|
|
+ return len;
|
|
|
|
+}
|
|
|
|
+static DEVICE_ATTR(mode, 0644, twl4030_bci_mode_show,
|
|
|
|
+ twl4030_bci_mode_store);
|
|
|
|
+
|
|
static int twl4030_charger_get_current(void)
|
|
static int twl4030_charger_get_current(void)
|
|
{
|
|
{
|
|
int curr;
|
|
int curr;
|
|
@@ -815,6 +870,7 @@ static int twl4030_bci_probe(struct platform_device *pdev)
|
|
bci->usb_cur = 500000; /* 500mA */
|
|
bci->usb_cur = 500000; /* 500mA */
|
|
else
|
|
else
|
|
bci->usb_cur = 100000; /* 100mA */
|
|
bci->usb_cur = 100000; /* 100mA */
|
|
|
|
+ bci->usb_mode = CHARGE_AUTO;
|
|
|
|
|
|
bci->dev = &pdev->dev;
|
|
bci->dev = &pdev->dev;
|
|
bci->irq_chg = platform_get_irq(pdev, 0);
|
|
bci->irq_chg = platform_get_irq(pdev, 0);
|
|
@@ -898,6 +954,8 @@ static int twl4030_bci_probe(struct platform_device *pdev)
|
|
twl4030_charger_update_current(bci);
|
|
twl4030_charger_update_current(bci);
|
|
if (device_create_file(&bci->usb->dev, &dev_attr_max_current))
|
|
if (device_create_file(&bci->usb->dev, &dev_attr_max_current))
|
|
dev_warn(&pdev->dev, "could not create sysfs file\n");
|
|
dev_warn(&pdev->dev, "could not create sysfs file\n");
|
|
|
|
+ if (device_create_file(&bci->usb->dev, &dev_attr_mode))
|
|
|
|
+ dev_warn(&pdev->dev, "could not create sysfs file\n");
|
|
if (device_create_file(&bci->ac->dev, &dev_attr_max_current))
|
|
if (device_create_file(&bci->ac->dev, &dev_attr_max_current))
|
|
dev_warn(&pdev->dev, "could not create sysfs file\n");
|
|
dev_warn(&pdev->dev, "could not create sysfs file\n");
|
|
|
|
|
|
@@ -926,6 +984,7 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
|
|
twl4030_charger_enable_backup(0, 0);
|
|
twl4030_charger_enable_backup(0, 0);
|
|
|
|
|
|
device_remove_file(&bci->usb->dev, &dev_attr_max_current);
|
|
device_remove_file(&bci->usb->dev, &dev_attr_max_current);
|
|
|
|
+ device_remove_file(&bci->usb->dev, &dev_attr_mode);
|
|
device_remove_file(&bci->ac->dev, &dev_attr_max_current);
|
|
device_remove_file(&bci->ac->dev, &dev_attr_max_current);
|
|
/* mask interrupts */
|
|
/* mask interrupts */
|
|
twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
|
|
twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
|