* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+#define DEBUG
+/* Boot with automatic charge */
+#define CHARGE_MODE 1
+
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/i2c/twl4030.h>
#include <linux/power_supply.h>
-#include <asm/arch/bci.h>
#include <linux/i2c/twl4030-madc.h>
#define T2_BATTERY_VOLT 0x04
#define REG_PHY_CLK_CTRL_STS 0x0FF
#define PHY_DPLL_CLK 0x01
-#define REG_BCICTL1 0x023
-#define REG_BCICTL2 0x024
+#define REG_BCICTL1 0x023
+#define REG_BCICTL2 0x024
#define CGAIN 0x020
#define ITHEN 0x010
#define ITHSENS 0x007
/* Boot BCI flag bits */
#define BCIAUTOWEN 0x020
#define CONFIG_DONE 0x010
+#define CVENAC 0x004
#define BCIAUTOUSB 0x002
#define BCIAUTOAC 0x001
#define BCIMSTAT_MASK 0x03F
#define REG_BCIMSTATEC 0x02
#define REG_BCIMFSTS4 0x010
#define REG_BCIMFSTS2 0x00E
-#define REG_BCIMFSTS3 0x00F
+#define REG_BCIMFSTS3 0x00F
#define REG_BCIMFSTS1 0x001
#define USBFASTMCHG 0x004
#define BATSTSPCHG 0x004
#define REG_BB_CFG 0x012
#define BBCHEN 0x010
+/* GPBR */
+#define REG_GPBR1 0x0c
+#define MADC_HFCLK_EN 0x80
+#define DEFAULT_MADC_CLK_EN 0x10
+
/* Power supply charge interrupt */
#define REG_PWR_ISR1 0x00
#define REG_PWR_IMR1 0x01
#define COR 0x004
/* interrupt status registers */
-#define REG_BCIISR1A 0x0
-#define REG_BCIISR2A 0x01
+#define REG_BCIISR1A 0x0
+#define REG_BCIISR2A 0x01
/* Interrupt flags bits BCIISR1 */
#define BATSTS_ISR1 0x080
/* BCIEDR3 */
#define VBATLVL_EDRRISIN 0x02
+/* BCIIREF1 */
+#define REG_BCIIREF1 0x027
+#define REG_BCIIREF2 0x028
+
+/* BCIMFTH1 */
+#define REG_BCIMFTH1 0x016
+
+/* Key */
+#define KEY_IIREF 0xE7
+#define KEY_FTH1 0xD2
+#define REG_BCIMFKEY 0x011
+
/* Step size and prescaler ratio */
#define TEMP_STEP_SIZE 147
#define TEMP_PSR_R 100
#define ENABLE 1
#define DISABLE 1
-/* Ptr to thermistor table */
-int *therm_tbl;
-
-static int twl4030_bci_battery_probe(struct platform_device *dev);
-static int twl4030_bci_battery_remove(struct platform_device *dev);
-#ifdef CONFIG_PM
-static int twl4030_bci_battery_suspend(struct platform_device *dev,
- pm_message_t state);
-static int twl4030_bci_battery_resume(struct platform_device *dev);
-#endif
-
struct twl4030_bci_device_info {
struct device *dev;
struct power_supply bk_bat;
struct delayed_work twl4030_bci_monitor_work;
struct delayed_work twl4030_bk_bci_monitor_work;
-};
-static struct platform_driver twl4030_bci_battery_driver = {
- .probe = twl4030_bci_battery_probe,
- .remove = twl4030_bci_battery_remove,
-#ifdef CONFIG_PM
- .suspend = twl4030_bci_battery_suspend,
- .resume = twl4030_bci_battery_resume,
-#endif
- .driver = {
- .name = "twl4030-bci-battery",
- },
+ struct twl4030_bci_platform_data *pdata;
};
static int usb_charger_flag;
if (ret)
return IRQ_NONE;
- /* If the AC charger have been connected */
- if (chg_sts & STS_CHG) {
+ if (chg_sts & STS_CHG) { /* If the AC charger have been connected */
/* configuring falling edge detection for CHG_PRES */
set = CHG_PRES_FALLING;
clear = CHG_PRES_RISING;
- }
- /* If the AC charger have been disconnected */
- else {
+ } else { /* If the AC charger have been disconnected */
/* configuring rising edge detection for CHG_PRES */
set = CHG_PRES_RISING;
clear = CHG_PRES_FALLING;
* USB_PRES (USB charger presence) CHG_PRES (AC charger presence) events
*
*/
-static irqreturn_t twl4030charger_interrupt(int irq, void *dev_id)
+static irqreturn_t twl4030charger_interrupt(int irq, void *_di)
{
- struct twl4030_bci_device_info *di = dev_id;
+ struct twl4030_bci_device_info *di = _di;
+
+#ifdef CONFIG_LOCKDEP
+ /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+ * we don't want and can't tolerate. Although it might be
+ * friendlier not to borrow this thread context...
+ */
+ local_irq_enable();
+#endif
twl4030charger_presence_evt();
power_supply_changed(&di->bat);
* REVISIT: Physically inserting/removing the batt
* does not seem to generate an int on 3430ES2 SDP.
*/
-
- /* In case of the battery insertion event */
if ((batstspchg & BATSTSPCHG) || (batstsmchg & BATSTSMCHG)) {
+ /* In case of the battery insertion event */
ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRRISIN,
BATSTS_EDRFALLING, REG_BCIEDR2);
if (ret)
return ret;
- }
-
- /* In case of the battery removal event */
- else {
+ } else {
+ /* In case of the battery removal event */
ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRFALLING,
BATSTS_EDRRISIN, REG_BCIEDR2);
if (ret)
if (ret)
return ret;
+ /* REVISIT could use a bitmap */
if (mfst & VBATOV4) {
LVL_4 = 1;
- LVL_3 = LVL_2 = LVL_1 = 0;
+ LVL_3 = 0;
+ LVL_2 = 0;
+ LVL_1 = 0;
} else if (mfst & VBATOV3) {
+ LVL_4 = 0;
LVL_3 = 1;
- LVL_4 = LVL_2 = LVL_1 = 0;
+ LVL_2 = 0;
+ LVL_1 = 0;
} else if (mfst & VBATOV2) {
+ LVL_4 = 0;
+ LVL_3 = 0;
LVL_2 = 1;
- LVL_4 = LVL_3 = LVL_1 = 0;
+ LVL_1 = 0;
} else {
+ LVL_4 = 0;
+ LVL_3 = 0;
+ LVL_2 = 0;
LVL_1 = 1;
- LVL_4 = LVL_3 = LVL_2 = 0;
}
return 0;
* VBATOV (main battery voltage threshold) events
*
*/
-static irqreturn_t twl4030battery_interrupt(int irq, void *dev_id)
+static irqreturn_t twl4030battery_interrupt(int irq, void *_di)
{
- int ret;
u8 isr1a_val, isr2a_val, clear_2a, clear_1a;
+ int ret;
+
+#ifdef CONFIG_LOCKDEP
+ /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+ * we don't want and can't tolerate. Although it might be
+ * friendlier not to borrow this thread context...
+ */
+ local_irq_enable();
+#endif
ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val,
REG_BCIISR1A);
if (ret)
return IRQ_NONE;
- clear_2a = (isr2a_val & VBATLVL_ISR1)? (VBATLVL_ISR1): 0;
- clear_1a = (isr1a_val & BATSTS_ISR1)? (BATSTS_ISR1): 0;
+ clear_2a = (isr2a_val & VBATLVL_ISR1) ? (VBATLVL_ISR1) : 0;
+ clear_1a = (isr1a_val & BATSTS_ISR1) ? (BATSTS_ISR1) : 0;
/* cleaning BCI interrupt status flags */
ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
/*
* Enable/Disable AC Charge funtionality.
*/
-static int twl4030charger_ac_en(int enable)
+static int twl4030charger_ac_en(int enable, int automatic)
{
int ret;
if (enable) {
/* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
- ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
- (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC),
- REG_BOOT_BCI);
+ if(!automatic) {
+ ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
+ (CONFIG_DONE | BCIAUTOWEN),
+ REG_BOOT_BCI);
+ } else {
+ ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
+ (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
+ REG_BOOT_BCI);
+ }
if (ret)
return ret;
} else {
if (ret)
return ret;
}
+
return 0;
}
* Return battery temperature
* Or < 0 on failure.
*/
-static int twl4030battery_temperature(void)
+static int twl4030battery_temperature(struct twl4030_bci_device_info *di)
{
u8 val;
int temp, curr, volt, res, ret;
+ /* Is a temperature table specified? */
+ if (!di->pdata->tblsize)
+ return 0;
+
/* Getting and calculating the thermistor voltage */
ret = read_bci_val(T2_BATTERY_TEMP);
if (ret < 0)
/*calculating temperature*/
for (temp = 58; temp >= 0; temp--) {
- int actual = therm_tbl [temp];
+ int actual = di->pdata->battery_tmp_tbl[temp];
if ((actual - res) >= 0)
break;
}
*/
static int twl4030backupbatt_voltage(void)
{
- int ret, temp;
- u8 volt;
struct twl4030_madc_request req;
+ int temp;
req.channels = (1 << 9);
+ req.do_avg = 0;
req.method = TWL4030_MADC_SW1;
+ req.active = 0;
+ req.func_cb = NULL;
twl4030_madc_conversion(&req);
temp = (u16)req.rbuf[9];
ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
REG_STS_HW_CONDITIONS);
if (ret) {
- pr_err("BATTERY DRIVER: error reading STS_HW_CONDITIONS \n");
+ pr_err("twl4030_bci: error reading STS_HW_CONDITIONS\n");
return ret;
}
- ret = (hwsts & STS_CHG)? AC_PW_CONN: NO_PW_CONN;
- ret += (hwsts & STS_VBUS)? USB_PW_CONN: NO_PW_CONN;
+ ret = (hwsts & STS_CHG) ? AC_PW_CONN : NO_PW_CONN;
+ ret += (hwsts & STS_VBUS) ? USB_PW_CONN : NO_PW_CONN;
if (ret & USB_PW_CONN)
usb_charger_flag = 1;
ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
&status, REG_BCIMSTATEC);
if (ret) {
- pr_err("BATTERY DRIVER: error reading BCIMSTATEC \n");
+ pr_err("twl4030_bci: error reading BCIMSTATEC\n");
return ret;
}
+#ifdef DEBUG
+ {
+ static int oldstatus = -1;
+ if (status != oldstatus)
+ printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
+ oldstatus = status;
+ }
+#endif
return (int) (status & BCIMSTAT_MASK);
}
* Settup the twl4030 BCI module to measure battery
* temperature
*/
-static int twl4030battery_temp_setup(void)
+static int twl4030battery_temp_setup(int dump)
{
- int ret;
+#ifdef DEBUG
+ u8 i;
+#endif
+ u8 ret;
/* Enabling thermistor current */
- ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
+ ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
REG_BCICTL1);
if (ret)
return ret;
+ if (!dump)
+ return 0;
+#ifdef DEBUG
+ twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
+ printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
+
+ twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_STS_HW_CONDITIONS);
+ printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
+
+ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
+ printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
+
+ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
+ printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
+
+ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
+ printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
+
+ twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
+ printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
+
+ for(i = 0x0; i <= 0x32; i++)
+ {
+ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
+ printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
+ }
+#endif
+
return 0;
}
ret = twl4030_i2c_read_u8(mod_no, &val, reg);
if (ret)
return ret;
-
/* Clearing all those bits to clear */
val &= ~(clear);
struct twl4030_bci_device_info,
twl4030_bk_bci_monitor_work.work);
- twl4030_bk_bci_battery_read_status(di);
+ if(!di->pdata->no_backup_battery)
+ twl4030_bk_bci_battery_read_status(di);
schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
}
static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
{
- di->temp_C = twl4030battery_temperature();
+ di->temp_C = twl4030battery_temperature(di);
di->voltage_uV = twl4030battery_voltage();
di->current_uA = twl4030battery_current();
}
#define to_twl4030_bk_bci_device_info(x) container_of((x), \
struct twl4030_bci_device_info, bk_bat);
+static ssize_t
+show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 ctl;
+ int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
+ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
+
+ if (ctl & CGAIN)
+ ret |= 0x200;
+
+#ifdef DEBUG
+ /* Dump debug */
+ twl4030battery_temp_setup(1);
+#endif
+
+ return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t
+set_charge_current(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long newCurrent;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &newCurrent);
+ if (ret)
+ return -EINVAL;
+
+ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
+ if (ret)
+ return ret;
+
+ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent & 0xff, REG_BCIIREF1);
+ if (ret)
+ return ret;
+
+ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
+ if (ret)
+ return ret;
+
+ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x1, REG_BCIIREF2);
+ if (ret)
+ return ret;
+
+ /* Set software-controlled charge */
+ twl4030charger_ac_en(ENABLE, 0);
+
+ /* Set CGAIN = 0 or 1 */
+ if(newCurrent > 511) {
+ u8 tmp;
+
+ /* Set CGAIN = 1 -- need to wait until automatic charge turns off */
+ while(!ret) {
+ clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B, REG_BCICTL1);
+ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
+
+ ret = tmp & CGAIN;
+ if(!ret)
+ mdelay(50);
+ }
+ } else {
+ u8 tmp;
+
+ /* Set CGAIN = 0 -- need to wait until automatic charge turns off */
+ while(!ret) {
+ clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
+ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
+
+ ret = !(tmp & CGAIN);
+ if(!ret)
+ mdelay(50);
+ }
+ }
+
+ /* Set automatic charge (CGAIN = 0/1 persists) */
+ twl4030charger_ac_en(ENABLE, 1);
+
+ return count;
+}
+static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUSR, show_charge_current, set_charge_current);
+
+static ssize_t
+show_current2(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret, curr = read_bci_val(T2_BATTERY_CUR);
+ u8 val;
+
+ ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
+ REG_BCICTL1);
+ if (ret)
+ return ret;
+
+ if (val & CGAIN)
+ //ret = (int)((float)curr * 1.6617790811339199f * 2.0f - 1.7f);
+ ret = curr * 16618 * 2 - 1700 * 10000;
+ else
+ //ret = (int)((float)curr * 1.6617790811339199f - 0.85f);
+ ret = curr * 16618 - 850 * 10000;
+ ret /= 10000;
+
+ return sprintf(buf, "%d (BCIICHG2 = 0x%02x, BCIICHG1 = 0x%02x, CGAIN = %d)\n",
+ ret, curr >> 8, curr & 0xff, (val & CGAIN) ? 1 : 0);
+}
+static DEVICE_ATTR(current_now2, S_IRUGO | S_IWUSR, show_current2, NULL);
+
static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
enum power_supply_property psp,
union power_supply_propval *val)
{
- struct twl4030_bci_device_info *di = to_twl4030_bci_device_info(psy);
+ struct twl4030_bci_device_info *di;
int status = 0;
+ di = to_twl4030_bci_device_info(psy);
+
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
val->intval = di->charge_status;
"twl4030_bci_battery",
};
-static int twl4030_bci_battery_probe(struct platform_device *dev)
+static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
{
+ struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
struct twl4030_bci_device_info *di;
+ int irq;
int ret;
- struct twl4030_bci_platform_data *pdata = dev->dev.platform_data;
-
- therm_tbl = pdata->battery_tmp_tbl;
di = kzalloc(sizeof(*di), GFP_KERNEL);
if (!di)
return -ENOMEM;
- platform_set_drvdata(dev, di);
-
- di->dev = &dev->dev;
+ di->dev = &pdev->dev;
di->bat.name = "twl4030_bci_battery";
di->bat.supplied_to = twl4030_bci_supplied_to;
di->bat.num_supplicants = ARRAY_SIZE(twl4030_bci_supplied_to);
di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
di->bk_bat.external_power_changed = NULL;
+ di->pdata = pdata;
+
+ /* Set up clocks */
+ twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, REG_GPBR1);
- twl4030charger_ac_en(ENABLE);
+ twl4030charger_ac_en(ENABLE, CHARGE_MODE);
twl4030charger_usb_en(ENABLE);
twl4030battery_hw_level_en(ENABLE);
twl4030battery_hw_presence_en(ENABLE);
+ platform_set_drvdata(pdev, di);
+
/* settings for temperature sensing */
- ret = twl4030battery_temp_setup();
+ ret = twl4030battery_temp_setup(0);
if (ret)
goto temp_setup_fail;
/* enabling GPCH09 for read back battery voltage */
- ret = twl4030backupbatt_voltage_setup();
- if (ret)
- goto voltage_setup_fail;
+ if(!di->pdata->no_backup_battery)
+ {
+ ret = twl4030backupbatt_voltage_setup();
+ if (ret)
+ goto voltage_setup_fail;
+ }
+
+ /* REVISIT do we need to request both IRQs ?? */
/* request BCI interruption */
ret = request_irq(TWL4030_MODIRQ_BCI, twl4030battery_interrupt,
- IRQF_DISABLED, dev->name, NULL);
+ 0, pdev->name, NULL);
if (ret) {
- pr_err("BATTERY DRIVER: (BCI) IRQ%d is not free.\n",
- TWL4030_MODIRQ_PWR);
+ dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+ TWL4030_MODIRQ_BCI, ret);
goto batt_irq_fail;
}
+ irq = platform_get_irq(pdev, 0);
+
/* request Power interruption */
- ret = request_irq(TWL4030_PWRIRQ_CHG_PRES, twl4030charger_interrupt,
- 0, dev->name, di);
+ ret = request_irq(irq, twl4030charger_interrupt,
+ 0, pdev->name, di);
if (ret) {
- pr_err("BATTERY DRIVER: (POWER) IRQ%d is not free.\n",
- TWL4030_MODIRQ_PWR);
+ dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+ irq, ret);
goto chg_irq_fail;
}
- ret = power_supply_register(&dev->dev, &di->bat);
+ ret = power_supply_register(&pdev->dev, &di->bat);
if (ret) {
- pr_err("BATTERY DRIVER: failed to register main battery\n");
+ dev_dbg(&pdev->dev, "failed to register main battery\n");
goto batt_failed;
}
twl4030_bci_battery_work);
schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
- ret = power_supply_register(&dev->dev, &di->bk_bat);
+ if(!pdata->no_backup_battery)
+ {
+ ret = power_supply_register(&pdev->dev, &di->bk_bat);
+ if (ret) {
+ dev_dbg(&pdev->dev, "failed to register backup battery\n");
+ goto bk_batt_failed;
+ }
+ }
+
+ ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
if (ret) {
- pr_err("BATTERY DRIVER: failed to register backup battery\n");
+ dev_err(&pdev->dev, "failed to create sysfs entries\n");
goto bk_batt_failed;
}
+ device_create_file(di->bat.dev, &dev_attr_current_now2);
INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bk_bci_monitor_work,
twl4030_bk_bci_battery_work);
return 0;
bk_batt_failed:
- power_supply_unregister(&di->bat);
+ if(!pdata->no_backup_battery)
+ power_supply_unregister(&di->bat);
batt_failed:
- free_irq(TWL4030_MODIRQ_PWR, di);
+ free_irq(irq, di);
chg_irq_fail:
-prev_setup_err:
free_irq(TWL4030_MODIRQ_BCI, NULL);
batt_irq_fail:
voltage_setup_fail:
temp_setup_fail:
- twl4030charger_ac_en(DISABLE);
+ twl4030charger_ac_en(DISABLE, CHARGE_MODE);
twl4030charger_usb_en(DISABLE);
twl4030battery_hw_level_en(DISABLE);
twl4030battery_hw_presence_en(DISABLE);
return ret;
}
-static int twl4030_bci_battery_remove(struct platform_device *dev)
+static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
{
- struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
+ struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
- twl4030charger_ac_en(DISABLE);
+ twl4030charger_ac_en(DISABLE, CHARGE_MODE);
twl4030charger_usb_en(DISABLE);
twl4030battery_hw_level_en(DISABLE);
twl4030battery_hw_presence_en(DISABLE);
free_irq(TWL4030_MODIRQ_BCI, NULL);
- free_irq(TWL4030_MODIRQ_PWR, di);
+ free_irq(irq, di);
flush_scheduled_work();
power_supply_unregister(&di->bat);
power_supply_unregister(&di->bk_bat);
- platform_set_drvdata(dev, NULL);
+ platform_set_drvdata(pdev, NULL);
kfree(di);
return 0;
}
#ifdef CONFIG_PM
-static int twl4030_bci_battery_suspend(struct platform_device *dev,
+static int twl4030_bci_battery_suspend(struct platform_device *pdev,
pm_message_t state)
{
- struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
+ struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
cancel_delayed_work(&di->twl4030_bci_monitor_work);
return 0;
}
-static int twl4030_bci_battery_resume(struct platform_device *dev)
+static int twl4030_bci_battery_resume(struct platform_device *pdev)
{
- struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
+ struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 50);
return 0;
}
+#else
+#define twl4030_bci_battery_suspend NULL
+#define twl4030_bci_battery_resume NULL
#endif /* CONFIG_PM */
-/*
- * Battery driver module initializer function
- * registers battery driver structure
- */
+static struct platform_driver twl4030_bci_battery_driver = {
+ .probe = twl4030_bci_battery_probe,
+ .remove = __exit_p(twl4030_bci_battery_remove),
+ .suspend = twl4030_bci_battery_suspend,
+ .resume = twl4030_bci_battery_resume,
+ .driver = {
+ .name = "twl4030_bci",
+ },
+};
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl4030_bci");
+MODULE_AUTHOR("Texas Instruments Inc");
+
static int __init twl4030_battery_init(void)
{
return platform_driver_register(&twl4030_bci_battery_driver);
-
}
+module_init(twl4030_battery_init);
-/*
- * Battery driver module exit function
- * unregister battery driver structure
- */
static void __exit twl4030_battery_exit(void)
{
platform_driver_unregister(&twl4030_bci_battery_driver);
}
-
-module_init(twl4030_battery_init);
module_exit(twl4030_battery_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("twl4030_bci_battery");
-MODULE_AUTHOR("Texas Instruments Inc");
+