2 * linux/drivers/power/twl4030_bci_battery.c
4 * OMAP2430/3430 BCI battery driver for Linux
6 * Copyright (C) 2008 Texas Instruments, Inc.
7 * Author: Texas Instruments, Inc.
9 * This package is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 #include <linux/init.h>
19 #include <linux/module.h>
20 #include <linux/device.h>
21 #include <linux/interrupt.h>
22 #include <linux/delay.h>
23 #include <linux/platform_device.h>
24 #include <linux/i2c/twl4030.h>
25 #include <linux/power_supply.h>
26 #include <linux/i2c/twl4030-madc.h>
28 #define T2_BATTERY_VOLT 0x04
29 #define T2_BATTERY_TEMP 0x06
30 #define T2_BATTERY_CUR 0x08
32 /* charger constants */
34 #define AC_PW_CONN 0x01
35 #define USB_PW_CONN 0x02
37 /* TWL4030_MODULE_USB */
38 #define REG_POWER_CTRL 0x0AC
40 #define REG_PHY_CLK_CTRL 0x0FE
41 #define REG_PHY_CLK_CTRL_STS 0x0FF
42 #define PHY_DPLL_CLK 0x01
44 #define REG_BCICTL1 0x023
45 #define REG_BCICTL2 0x024
50 /* Boot BCI flag bits */
51 #define BCIAUTOWEN 0x020
52 #define CONFIG_DONE 0x010
53 #define BCIAUTOUSB 0x002
54 #define BCIAUTOAC 0x001
55 #define BCIMSTAT_MASK 0x03F
57 /* Boot BCI register */
58 #define REG_BOOT_BCI 0x007
59 #define REG_CTRL1 0x00
60 #define REG_SW1SELECT_MSB 0x07
61 #define SW1_CH9_SEL 0x02
62 #define REG_CTRL_SW1 0x012
63 #define SW1_TRIGGER 0x020
65 #define REG_GPCH9 0x049
66 #define REG_STS_HW_CONDITIONS 0x0F
67 #define STS_VBUS 0x080
69 #define REG_BCIMSTATEC 0x02
70 #define REG_BCIMFSTS4 0x010
71 #define REG_BCIMFSTS2 0x00E
72 #define REG_BCIMFSTS3 0x00F
73 #define REG_BCIMFSTS1 0x001
74 #define USBFASTMCHG 0x004
75 #define BATSTSPCHG 0x004
76 #define BATSTSMCHG 0x040
81 #define REG_BB_CFG 0x012
84 /* Power supply charge interrupt */
85 #define REG_PWR_ISR1 0x00
86 #define REG_PWR_IMR1 0x01
87 #define REG_PWR_EDR1 0x05
88 #define REG_PWR_SIH_CTRL 0x007
90 #define USB_PRES 0x004
91 #define CHG_PRES 0x002
93 #define USB_PRES_RISING 0x020
94 #define USB_PRES_FALLING 0x010
95 #define CHG_PRES_RISING 0x008
96 #define CHG_PRES_FALLING 0x004
97 #define AC_STATEC 0x20
100 /* interrupt status registers */
101 #define REG_BCIISR1A 0x0
102 #define REG_BCIISR2A 0x01
104 /* Interrupt flags bits BCIISR1 */
105 #define BATSTS_ISR1 0x080
106 #define VBATLVL_ISR1 0x001
108 /* Interrupt mask registers for int1*/
109 #define REG_BCIIMR1A 0x002
110 #define REG_BCIIMR2A 0x003
112 /* Interrupt masks for BCIIMR1 */
113 #define BATSTS_IMR1 0x080
114 #define VBATLVL_IMR1 0x001
116 /* Interrupt edge detection register */
117 #define REG_BCIEDR1 0x00A
118 #define REG_BCIEDR2 0x00B
119 #define REG_BCIEDR3 0x00C
122 #define BATSTS_EDRRISIN 0x080
123 #define BATSTS_EDRFALLING 0x040
126 #define VBATLVL_EDRRISIN 0x02
128 /* Step size and prescaler ratio */
129 #define TEMP_STEP_SIZE 147
130 #define TEMP_PSR_R 100
132 #define VOLT_STEP_SIZE 588
133 #define VOLT_PSR_R 100
135 #define CURR_STEP_SIZE 147
136 #define CURR_PSR_R1 44
137 #define CURR_PSR_R2 80
139 #define BK_VOLT_STEP_SIZE 441
140 #define BK_VOLT_PSR_R 100
145 /* Ptr to thermistor table */
148 struct twl4030_bci_device_info {
151 unsigned long update_time;
159 struct power_supply bat;
160 struct power_supply bk_bat;
161 struct delayed_work twl4030_bci_monitor_work;
162 struct delayed_work twl4030_bk_bci_monitor_work;
165 static int usb_charger_flag;
166 static int LVL_1, LVL_2, LVL_3, LVL_4;
168 static int read_bci_val(u8 reg_1);
169 static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg);
170 static int twl4030charger_presence(void);
173 * Report and clear the charger presence event.
175 static inline int twl4030charger_presence_evt(void)
178 u8 chg_sts, set = 0, clear = 0;
180 /* read charger power supply status */
181 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &chg_sts,
182 REG_STS_HW_CONDITIONS);
186 if (chg_sts & STS_CHG) { /* If the AC charger have been connected */
187 /* configuring falling edge detection for CHG_PRES */
188 set = CHG_PRES_FALLING;
189 clear = CHG_PRES_RISING;
190 } else { /* If the AC charger have been disconnected */
191 /* configuring rising edge detection for CHG_PRES */
192 set = CHG_PRES_RISING;
193 clear = CHG_PRES_FALLING;
196 /* Update the interrupt edge detection register */
197 clear_n_set(TWL4030_MODULE_INT, clear, set, REG_PWR_EDR1);
203 * Interrupt service routine
205 * Attends to TWL 4030 power module interruptions events, specifically
206 * USB_PRES (USB charger presence) CHG_PRES (AC charger presence) events
209 static irqreturn_t twl4030charger_interrupt(int irq, void *_di)
211 struct twl4030_bci_device_info *di = _di;
213 twl4030charger_presence_evt();
214 power_supply_changed(&di->bat);
220 * This function handles the twl4030 battery presence interrupt
222 static int twl4030battery_presence_evt(void)
225 u8 batstsmchg, batstspchg;
227 /* check for the battery presence in main charge*/
228 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
229 &batstsmchg, REG_BCIMFSTS3);
233 /* check for the battery presence in precharge */
234 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PRECHARGE,
235 &batstspchg, REG_BCIMFSTS1);
240 * REVISIT: Physically inserting/removing the batt
241 * does not seem to generate an int on 3430ES2 SDP.
243 if ((batstspchg & BATSTSPCHG) || (batstsmchg & BATSTSMCHG)) {
244 /* In case of the battery insertion event */
245 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRRISIN,
246 BATSTS_EDRFALLING, REG_BCIEDR2);
250 /* In case of the battery removal event */
251 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRFALLING,
252 BATSTS_EDRRISIN, REG_BCIEDR2);
261 * This function handles the twl4030 battery voltage level interrupt.
263 static int twl4030battery_level_evt(void)
268 /* checking for threshold event */
269 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
270 &mfst, REG_BCIMFSTS2);
274 /* REVISIT could use a bitmap */
275 if (mfst & VBATOV4) {
280 } else if (mfst & VBATOV3) {
285 } else if (mfst & VBATOV2) {
301 * Interrupt service routine
303 * Attends to BCI interruptions events,
304 * specifically BATSTS (battery connection and removal)
305 * VBATOV (main battery voltage threshold) events
308 static irqreturn_t twl4030battery_interrupt(int irq, void *_di)
310 u8 isr1a_val, isr2a_val, clear_2a, clear_1a;
313 ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val,
318 ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr2a_val,
323 clear_2a = (isr2a_val & VBATLVL_ISR1) ? (VBATLVL_ISR1) : 0;
324 clear_1a = (isr1a_val & BATSTS_ISR1) ? (BATSTS_ISR1) : 0;
326 /* cleaning BCI interrupt status flags */
327 ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
328 clear_1a , REG_BCIISR1A);
332 ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
333 clear_2a , REG_BCIISR2A);
337 /* battery connetion or removal event */
338 if (isr1a_val & BATSTS_ISR1)
339 twl4030battery_presence_evt();
340 /* battery voltage threshold event*/
341 else if (isr2a_val & VBATLVL_ISR1)
342 twl4030battery_level_evt();
350 * Enable/Disable hardware battery level event notifications.
352 static int twl4030battery_hw_level_en(int enable)
357 /* unmask VBATOV interrupt for INT1 */
358 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, VBATLVL_IMR1,
363 /* configuring interrupt edge detection for VBATOv */
364 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
365 VBATLVL_EDRRISIN, REG_BCIEDR3);
369 /* mask VBATOV interrupt for INT1 */
370 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
371 VBATLVL_IMR1, REG_BCIIMR2A);
380 * Enable/disable hardware battery presence event notifications.
382 static int twl4030battery_hw_presence_en(int enable)
387 /* unmask BATSTS interrupt for INT1 */
388 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_IMR1,
393 /* configuring interrupt edge for BATSTS */
394 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
395 BATSTS_EDRRISIN | BATSTS_EDRFALLING, REG_BCIEDR2);
399 /* mask BATSTS interrupt for INT1 */
400 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
401 BATSTS_IMR1, REG_BCIIMR1A);
410 * Enable/Disable AC Charge funtionality.
412 static int twl4030charger_ac_en(int enable)
417 /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
418 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
419 (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC),
424 /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 0*/
425 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC,
426 (CONFIG_DONE | BCIAUTOWEN),
436 * Enable/Disable USB Charge funtionality.
438 int twl4030charger_usb_en(int enable)
442 unsigned long timeout;
445 /* Check for USB charger conneted */
446 ret = twl4030charger_presence();
450 if (!(ret & USB_PW_CONN))
453 /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
454 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
455 (CONFIG_DONE | BCIAUTOWEN | BCIAUTOUSB),
460 ret = clear_n_set(TWL4030_MODULE_USB, 0, PHY_DPLL_CLK,
466 timeout = jiffies + msecs_to_jiffies(50);
468 while ((!(value & PHY_DPLL_CLK)) &&
469 time_before(jiffies, timeout)) {
471 ret = twl4030_i2c_read_u8(TWL4030_MODULE_USB, &value,
472 REG_PHY_CLK_CTRL_STS);
477 /* OTG_EN (POWER_CTRL[5]) to 1 */
478 ret = clear_n_set(TWL4030_MODULE_USB, 0, OTG_EN,
485 /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
486 ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0,
487 USBFASTMCHG, REG_BCIMFSTS4);
491 twl4030charger_presence();
492 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOUSB,
493 (CONFIG_DONE | BCIAUTOWEN), REG_BOOT_BCI);
502 * Return battery temperature
505 static int twl4030battery_temperature(void)
508 int temp, curr, volt, res, ret;
510 /* Getting and calculating the thermistor voltage */
511 ret = read_bci_val(T2_BATTERY_TEMP);
515 volt = (ret * TEMP_STEP_SIZE) / TEMP_PSR_R;
517 /* Getting and calculating the supply current in micro ampers */
518 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
523 curr = ((val & ITHSENS) + 1) * 10;
525 /* Getting and calculating the thermistor resistance in ohms*/
526 res = volt * 1000 / curr;
528 /*calculating temperature*/
529 for (temp = 58; temp >= 0; temp--) {
530 int actual = therm_tbl[temp];
531 if ((actual - res) >= 0)
535 /* Negative temperature */
549 * Return battery voltage
552 static int twl4030battery_voltage(void)
554 int volt = read_bci_val(T2_BATTERY_VOLT);
556 return (volt * VOLT_STEP_SIZE) / VOLT_PSR_R;
560 * Return the battery current
563 static int twl4030battery_current(void)
565 int ret, curr = read_bci_val(T2_BATTERY_CUR);
568 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
573 if (val & CGAIN) /* slope of 0.44 mV/mA */
574 return (curr * CURR_STEP_SIZE) / CURR_PSR_R1;
575 else /* slope of 0.88 mV/mA */
576 return (curr * CURR_STEP_SIZE) / CURR_PSR_R2;
580 * Return the battery backup voltage
583 static int twl4030backupbatt_voltage(void)
585 struct twl4030_madc_request req;
588 req.channels = (1 << 9);
590 req.method = TWL4030_MADC_SW1;
593 twl4030_madc_conversion(&req);
594 temp = (u16)req.rbuf[9];
596 return (temp * BK_VOLT_STEP_SIZE) / BK_VOLT_PSR_R;
600 * Returns an integer value, that means,
601 * NO_PW_CONN no power supply is connected
602 * AC_PW_CONN if the AC power supply is connected
603 * USB_PW_CONN if the USB power supply is connected
604 * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected
608 static int twl4030charger_presence(void)
613 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
614 REG_STS_HW_CONDITIONS);
616 pr_err("twl4030_bci: error reading STS_HW_CONDITIONS\n");
620 ret = (hwsts & STS_CHG) ? AC_PW_CONN : NO_PW_CONN;
621 ret += (hwsts & STS_VBUS) ? USB_PW_CONN : NO_PW_CONN;
623 if (ret & USB_PW_CONN)
624 usb_charger_flag = 1;
626 usb_charger_flag = 0;
633 * Returns the main charge FSM status
636 static int twl4030bci_status(void)
641 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
642 &status, REG_BCIMSTATEC);
644 pr_err("twl4030_bci: error reading BCIMSTATEC\n");
648 return (int) (status & BCIMSTAT_MASK);
651 static int read_bci_val(u8 reg)
657 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
662 temp = ((int)(val & 0x03)) << 8;
665 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
674 * Settup the twl4030 BCI module to enable backup
677 static int twl4030backupbatt_voltage_setup(void)
681 /* Starting backup batery charge */
682 ret = clear_n_set(TWL4030_MODULE_PM_RECEIVER, 0, BBCHEN,
691 * Settup the twl4030 BCI module to measure battery
694 static int twl4030battery_temp_setup(void)
698 /* Enabling thermistor current */
699 ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
708 * Sets and clears bits on an given register on a given module
710 static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg)
715 /* Gets the initial register value */
716 ret = twl4030_i2c_read_u8(mod_no, &val, reg);
720 /* Clearing all those bits to clear */
723 /* Setting all those bits to set */
726 /* Update the register */
727 ret = twl4030_i2c_write_u8(mod_no, val, reg);
734 static enum power_supply_property twl4030_bci_battery_props[] = {
735 POWER_SUPPLY_PROP_STATUS,
736 POWER_SUPPLY_PROP_ONLINE,
737 POWER_SUPPLY_PROP_VOLTAGE_NOW,
738 POWER_SUPPLY_PROP_CURRENT_NOW,
739 POWER_SUPPLY_PROP_CAPACITY,
740 POWER_SUPPLY_PROP_TEMP,
743 static enum power_supply_property twl4030_bk_bci_battery_props[] = {
744 POWER_SUPPLY_PROP_VOLTAGE_NOW,
748 twl4030_bk_bci_battery_read_status(struct twl4030_bci_device_info *di)
750 di->bk_voltage_uV = twl4030backupbatt_voltage();
753 static void twl4030_bk_bci_battery_work(struct work_struct *work)
755 struct twl4030_bci_device_info *di = container_of(work,
756 struct twl4030_bci_device_info,
757 twl4030_bk_bci_monitor_work.work);
759 twl4030_bk_bci_battery_read_status(di);
760 schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
763 static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
765 di->temp_C = twl4030battery_temperature();
766 di->voltage_uV = twl4030battery_voltage();
767 di->current_uA = twl4030battery_current();
771 twl4030_bci_battery_update_status(struct twl4030_bci_device_info *di)
773 twl4030_bci_battery_read_status(di);
774 di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
776 if (power_supply_am_i_supplied(&di->bat))
777 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
779 di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
782 static void twl4030_bci_battery_work(struct work_struct *work)
784 struct twl4030_bci_device_info *di = container_of(work,
785 struct twl4030_bci_device_info, twl4030_bci_monitor_work.work);
787 twl4030_bci_battery_update_status(di);
788 schedule_delayed_work(&di->twl4030_bci_monitor_work, 100);
792 #define to_twl4030_bci_device_info(x) container_of((x), \
793 struct twl4030_bci_device_info, bat);
795 static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
797 struct twl4030_bci_device_info *di = to_twl4030_bci_device_info(psy);
799 cancel_delayed_work(&di->twl4030_bci_monitor_work);
800 schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
803 #define to_twl4030_bk_bci_device_info(x) container_of((x), \
804 struct twl4030_bci_device_info, bk_bat);
806 static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
807 enum power_supply_property psp,
808 union power_supply_propval *val)
810 struct twl4030_bci_device_info *di = to_twl4030_bk_bci_device_info(psy);
813 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
814 val->intval = di->bk_voltage_uV;
823 static int twl4030_bci_battery_get_property(struct power_supply *psy,
824 enum power_supply_property psp,
825 union power_supply_propval *val)
827 struct twl4030_bci_device_info *di;
830 di = to_twl4030_bci_device_info(psy);
833 case POWER_SUPPLY_PROP_STATUS:
834 val->intval = di->charge_status;
841 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
842 val->intval = di->voltage_uV;
844 case POWER_SUPPLY_PROP_CURRENT_NOW:
845 val->intval = di->current_uA;
847 case POWER_SUPPLY_PROP_TEMP:
848 val->intval = di->temp_C;
850 case POWER_SUPPLY_PROP_ONLINE:
851 status = twl4030bci_status();
852 if ((status & AC_STATEC) == AC_STATEC)
853 val->intval = POWER_SUPPLY_TYPE_MAINS;
854 else if (usb_charger_flag)
855 val->intval = POWER_SUPPLY_TYPE_USB;
859 case POWER_SUPPLY_PROP_CAPACITY:
861 * need to get the correct percentage value per the
862 * battery characteristics. Approx values for now.
864 if (di->voltage_uV < 2894 || LVL_1) {
867 } else if ((di->voltage_uV < 3451 && di->voltage_uV > 2894)
871 } else if ((di->voltage_uV < 3902 && di->voltage_uV > 3451)
875 } else if ((di->voltage_uV < 3949 && di->voltage_uV > 3902)
879 } else if (di->voltage_uV > 3949)
888 static char *twl4030_bci_supplied_to[] = {
889 "twl4030_bci_battery",
892 static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
894 struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
895 struct twl4030_bci_device_info *di;
899 therm_tbl = pdata->battery_tmp_tbl;
901 di = kzalloc(sizeof(*di), GFP_KERNEL);
905 di->dev = &pdev->dev;
906 di->bat.name = "twl4030_bci_battery";
907 di->bat.supplied_to = twl4030_bci_supplied_to;
908 di->bat.num_supplicants = ARRAY_SIZE(twl4030_bci_supplied_to);
909 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
910 di->bat.properties = twl4030_bci_battery_props;
911 di->bat.num_properties = ARRAY_SIZE(twl4030_bci_battery_props);
912 di->bat.get_property = twl4030_bci_battery_get_property;
913 di->bat.external_power_changed =
914 twl4030_bci_battery_external_power_changed;
916 di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
918 di->bk_bat.name = "twl4030_bci_bk_battery";
919 di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
920 di->bk_bat.properties = twl4030_bk_bci_battery_props;
921 di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
922 di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
923 di->bk_bat.external_power_changed = NULL;
925 twl4030charger_ac_en(ENABLE);
926 twl4030charger_usb_en(ENABLE);
927 twl4030battery_hw_level_en(ENABLE);
928 twl4030battery_hw_presence_en(ENABLE);
930 platform_set_drvdata(pdev, di);
932 /* settings for temperature sensing */
933 ret = twl4030battery_temp_setup();
935 goto temp_setup_fail;
937 /* enabling GPCH09 for read back battery voltage */
938 ret = twl4030backupbatt_voltage_setup();
940 goto voltage_setup_fail;
942 /* REVISIT do we need to request both IRQs ?? */
944 /* request BCI interruption */
945 ret = request_irq(TWL4030_MODIRQ_BCI, twl4030battery_interrupt,
946 IRQF_DISABLED, pdev->name, NULL);
948 dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
949 TWL4030_MODIRQ_BCI, ret);
953 irq = platform_get_irq(pdev, 0);
955 /* request Power interruption */
956 ret = request_irq(irq, twl4030charger_interrupt,
960 dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
965 ret = power_supply_register(&pdev->dev, &di->bat);
967 dev_dbg(&pdev->dev, "failed to register main battery\n");
971 INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bci_monitor_work,
972 twl4030_bci_battery_work);
973 schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
975 ret = power_supply_register(&pdev->dev, &di->bk_bat);
977 dev_dbg(&pdev->dev, "failed to register backup battery\n");
981 INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bk_bci_monitor_work,
982 twl4030_bk_bci_battery_work);
983 schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
988 power_supply_unregister(&di->bat);
992 free_irq(TWL4030_MODIRQ_BCI, NULL);
996 twl4030charger_ac_en(DISABLE);
997 twl4030charger_usb_en(DISABLE);
998 twl4030battery_hw_level_en(DISABLE);
999 twl4030battery_hw_presence_en(DISABLE);
1005 static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
1007 struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
1008 int irq = platform_get_irq(pdev, 0);
1010 twl4030charger_ac_en(DISABLE);
1011 twl4030charger_usb_en(DISABLE);
1012 twl4030battery_hw_level_en(DISABLE);
1013 twl4030battery_hw_presence_en(DISABLE);
1015 free_irq(TWL4030_MODIRQ_BCI, NULL);
1018 flush_scheduled_work();
1019 power_supply_unregister(&di->bat);
1020 power_supply_unregister(&di->bk_bat);
1021 platform_set_drvdata(pdev, NULL);
1028 static int twl4030_bci_battery_suspend(struct platform_device *pdev,
1031 struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
1033 di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
1034 cancel_delayed_work(&di->twl4030_bci_monitor_work);
1035 cancel_delayed_work(&di->twl4030_bk_bci_monitor_work);
1039 static int twl4030_bci_battery_resume(struct platform_device *pdev)
1041 struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
1043 schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
1044 schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 50);
1048 #define twl4030_bci_battery_suspend NULL
1049 #define twl4030_bci_battery_resume NULL
1050 #endif /* CONFIG_PM */
1052 static struct platform_driver twl4030_bci_battery_driver = {
1053 .probe = twl4030_bci_battery_probe,
1054 .remove = __exit_p(twl4030_bci_battery_remove),
1055 .suspend = twl4030_bci_battery_suspend,
1056 .resume = twl4030_bci_battery_resume,
1058 .name = "twl4030_bci",
1062 MODULE_LICENSE("GPL");
1063 MODULE_ALIAS("platform:twl4030_bci");
1064 MODULE_AUTHOR("Texas Instruments Inc");
1066 static int __init twl4030_battery_init(void)
1068 return platform_driver_register(&twl4030_bci_battery_driver);
1070 module_init(twl4030_battery_init);
1072 static void __exit twl4030_battery_exit(void)
1074 platform_driver_unregister(&twl4030_bci_battery_driver);
1076 module_exit(twl4030_battery_exit);