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>
27 #include <linux/i2c/twl4030-madc.h>
29 #define T2_BATTERY_VOLT 0x04
30 #define T2_BATTERY_TEMP 0x06
31 #define T2_BATTERY_CUR 0x08
33 /* charger constants */
35 #define AC_PW_CONN 0x01
36 #define USB_PW_CONN 0x02
38 /* TWL4030_MODULE_USB */
39 #define REG_POWER_CTRL 0x0AC
41 #define REG_PHY_CLK_CTRL 0x0FE
42 #define REG_PHY_CLK_CTRL_STS 0x0FF
43 #define PHY_DPLL_CLK 0x01
45 #define REG_BCICTL1 0x023
46 #define REG_BCICTL2 0x024
51 /* Boot BCI flag bits */
52 #define BCIAUTOWEN 0x020
53 #define CONFIG_DONE 0x010
54 #define BCIAUTOUSB 0x002
55 #define BCIAUTOAC 0x001
56 #define BCIMSTAT_MASK 0x03F
58 /* Boot BCI register */
59 #define REG_BOOT_BCI 0x007
60 #define REG_CTRL1 0x00
61 #define REG_SW1SELECT_MSB 0x07
62 #define SW1_CH9_SEL 0x02
63 #define REG_CTRL_SW1 0x012
64 #define SW1_TRIGGER 0x020
66 #define REG_GPCH9 0x049
67 #define REG_STS_HW_CONDITIONS 0x0F
68 #define STS_VBUS 0x080
70 #define REG_BCIMSTATEC 0x02
71 #define REG_BCIMFSTS4 0x010
72 #define REG_BCIMFSTS2 0x00E
73 #define REG_BCIMFSTS3 0x00F
74 #define REG_BCIMFSTS1 0x001
75 #define USBFASTMCHG 0x004
76 #define BATSTSPCHG 0x004
77 #define BATSTSMCHG 0x040
82 #define REG_BB_CFG 0x012
85 /* Power supply charge interrupt */
86 #define REG_PWR_ISR1 0x00
87 #define REG_PWR_IMR1 0x01
88 #define REG_PWR_EDR1 0x05
89 #define REG_PWR_SIH_CTRL 0x007
91 #define USB_PRES 0x004
92 #define CHG_PRES 0x002
94 #define USB_PRES_RISING 0x020
95 #define USB_PRES_FALLING 0x010
96 #define CHG_PRES_RISING 0x008
97 #define CHG_PRES_FALLING 0x004
98 #define AC_STATEC 0x20
101 /* interrupt status registers */
102 #define REG_BCIISR1A 0x0
103 #define REG_BCIISR2A 0x01
105 /* Interrupt flags bits BCIISR1 */
106 #define BATSTS_ISR1 0x080
107 #define VBATLVL_ISR1 0x001
109 /* Interrupt mask registers for int1*/
110 #define REG_BCIIMR1A 0x002
111 #define REG_BCIIMR2A 0x003
113 /* Interrupt masks for BCIIMR1 */
114 #define BATSTS_IMR1 0x080
115 #define VBATLVL_IMR1 0x001
117 /* Interrupt edge detection register */
118 #define REG_BCIEDR1 0x00A
119 #define REG_BCIEDR2 0x00B
120 #define REG_BCIEDR3 0x00C
123 #define BATSTS_EDRRISIN 0x080
124 #define BATSTS_EDRFALLING 0x040
127 #define VBATLVL_EDRRISIN 0x02
129 /* Step size and prescaler ratio */
130 #define TEMP_STEP_SIZE 147
131 #define TEMP_PSR_R 100
133 #define VOLT_STEP_SIZE 588
134 #define VOLT_PSR_R 100
136 #define CURR_STEP_SIZE 147
137 #define CURR_PSR_R1 44
138 #define CURR_PSR_R2 80
140 #define BK_VOLT_STEP_SIZE 441
141 #define BK_VOLT_PSR_R 100
146 /* Ptr to thermistor table */
149 static int twl4030_bci_battery_probe(struct platform_device *dev);
150 static int twl4030_bci_battery_remove(struct platform_device *dev);
152 static int twl4030_bci_battery_suspend(struct platform_device *dev,
154 static int twl4030_bci_battery_resume(struct platform_device *dev);
157 struct twl4030_bci_device_info {
160 unsigned long update_time;
168 struct power_supply bat;
169 struct power_supply bk_bat;
170 struct delayed_work twl4030_bci_monitor_work;
171 struct delayed_work twl4030_bk_bci_monitor_work;
174 static struct platform_driver twl4030_bci_battery_driver = {
175 .probe = twl4030_bci_battery_probe,
176 .remove = twl4030_bci_battery_remove,
178 .suspend = twl4030_bci_battery_suspend,
179 .resume = twl4030_bci_battery_resume,
182 .name = "twl4030-bci-battery",
186 static int usb_charger_flag;
187 static int LVL_1, LVL_2, LVL_3, LVL_4;
189 static int read_bci_val(u8 reg_1);
190 static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg);
191 static int twl4030charger_presence(void);
194 * Report and clear the charger presence event.
196 static inline int twl4030charger_presence_evt(void)
199 u8 chg_sts, set = 0, clear = 0;
201 /* read charger power supply status */
202 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &chg_sts,
203 REG_STS_HW_CONDITIONS);
207 /* If the AC charger have been connected */
208 if (chg_sts & STS_CHG) {
209 /* configuring falling edge detection for CHG_PRES */
210 set = CHG_PRES_FALLING;
211 clear = CHG_PRES_RISING;
213 /* If the AC charger have been disconnected */
215 /* configuring rising edge detection for CHG_PRES */
216 set = CHG_PRES_RISING;
217 clear = CHG_PRES_FALLING;
220 /* Update the interrupt edge detection register */
221 clear_n_set(TWL4030_MODULE_INT, clear, set, REG_PWR_EDR1);
227 * Interrupt service routine
229 * Attends to TWL 4030 power module interruptions events, specifically
230 * USB_PRES (USB charger presence) CHG_PRES (AC charger presence) events
233 static irqreturn_t twl4030charger_interrupt(int irq, void *dev_id)
235 struct twl4030_bci_device_info *di = dev_id;
237 twl4030charger_presence_evt();
238 power_supply_changed(&di->bat);
244 * This function handles the twl4030 battery presence interrupt
246 static int twl4030battery_presence_evt(void)
249 u8 batstsmchg, batstspchg;
251 /* check for the battery presence in main charge*/
252 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
253 &batstsmchg, REG_BCIMFSTS3);
257 /* check for the battery presence in precharge */
258 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PRECHARGE,
259 &batstspchg, REG_BCIMFSTS1);
264 * REVISIT: Physically inserting/removing the batt
265 * does not seem to generate an int on 3430ES2 SDP.
268 /* In case of the battery insertion event */
269 if ((batstspchg & BATSTSPCHG) || (batstsmchg & BATSTSMCHG)) {
270 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRRISIN,
271 BATSTS_EDRFALLING, REG_BCIEDR2);
276 /* In case of the battery removal event */
278 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRFALLING,
279 BATSTS_EDRRISIN, REG_BCIEDR2);
288 * This function handles the twl4030 battery voltage level interrupt.
290 static int twl4030battery_level_evt(void)
295 /* checking for threshold event */
296 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
297 &mfst, REG_BCIMFSTS2);
301 if (mfst & VBATOV4) {
303 LVL_3 = LVL_2 = LVL_1 = 0;
304 } else if (mfst & VBATOV3) {
306 LVL_4 = LVL_2 = LVL_1 = 0;
307 } else if (mfst & VBATOV2) {
309 LVL_4 = LVL_3 = LVL_1 = 0;
312 LVL_4 = LVL_3 = LVL_2 = 0;
319 * Interrupt service routine
321 * Attends to BCI interruptions events,
322 * specifically BATSTS (battery connection and removal)
323 * VBATOV (main battery voltage threshold) events
326 static irqreturn_t twl4030battery_interrupt(int irq, void *dev_id)
329 u8 isr1a_val, isr2a_val, clear_2a, clear_1a;
331 ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val,
336 ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr2a_val,
341 clear_2a = (isr2a_val & VBATLVL_ISR1)? (VBATLVL_ISR1): 0;
342 clear_1a = (isr1a_val & BATSTS_ISR1)? (BATSTS_ISR1): 0;
344 /* cleaning BCI interrupt status flags */
345 ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
346 clear_1a , REG_BCIISR1A);
350 ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
351 clear_2a , REG_BCIISR2A);
355 /* battery connetion or removal event */
356 if (isr1a_val & BATSTS_ISR1)
357 twl4030battery_presence_evt();
358 /* battery voltage threshold event*/
359 else if (isr2a_val & VBATLVL_ISR1)
360 twl4030battery_level_evt();
368 * Enable/Disable hardware battery level event notifications.
370 static int twl4030battery_hw_level_en(int enable)
375 /* unmask VBATOV interrupt for INT1 */
376 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, VBATLVL_IMR1,
381 /* configuring interrupt edge detection for VBATOv */
382 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
383 VBATLVL_EDRRISIN, REG_BCIEDR3);
387 /* mask VBATOV interrupt for INT1 */
388 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
389 VBATLVL_IMR1, REG_BCIIMR2A);
398 * Enable/disable hardware battery presence event notifications.
400 static int twl4030battery_hw_presence_en(int enable)
405 /* unmask BATSTS interrupt for INT1 */
406 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_IMR1,
411 /* configuring interrupt edge for BATSTS */
412 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
413 BATSTS_EDRRISIN | BATSTS_EDRFALLING, REG_BCIEDR2);
417 /* mask BATSTS interrupt for INT1 */
418 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
419 BATSTS_IMR1, REG_BCIIMR1A);
428 * Enable/Disable AC Charge funtionality.
430 static int twl4030charger_ac_en(int enable)
435 /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
436 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
437 (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC),
442 /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 0*/
443 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC,
444 (CONFIG_DONE | BCIAUTOWEN),
453 * Enable/Disable USB Charge funtionality.
455 int twl4030charger_usb_en(int enable)
459 unsigned long timeout;
462 /* Check for USB charger conneted */
463 ret = twl4030charger_presence();
467 if (!(ret & USB_PW_CONN))
470 /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
471 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
472 (CONFIG_DONE | BCIAUTOWEN | BCIAUTOUSB),
477 ret = clear_n_set(TWL4030_MODULE_USB, 0, PHY_DPLL_CLK,
483 timeout = jiffies + msecs_to_jiffies(50);
485 while ((!(value & PHY_DPLL_CLK)) &&
486 time_before(jiffies, timeout)) {
488 ret = twl4030_i2c_read_u8(TWL4030_MODULE_USB, &value,
489 REG_PHY_CLK_CTRL_STS);
494 /* OTG_EN (POWER_CTRL[5]) to 1 */
495 ret = clear_n_set(TWL4030_MODULE_USB, 0, OTG_EN,
502 /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
503 ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0,
504 USBFASTMCHG, REG_BCIMFSTS4);
508 twl4030charger_presence();
509 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOUSB,
510 (CONFIG_DONE | BCIAUTOWEN), REG_BOOT_BCI);
519 * Return battery temperature
522 static int twl4030battery_temperature(void)
525 int temp, curr, volt, res, ret;
527 /* Getting and calculating the thermistor voltage */
528 ret = read_bci_val(T2_BATTERY_TEMP);
532 volt = (ret * TEMP_STEP_SIZE) / TEMP_PSR_R;
534 /* Getting and calculating the supply current in micro ampers */
535 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
540 curr = ((val & ITHSENS) + 1) * 10;
542 /* Getting and calculating the thermistor resistance in ohms*/
543 res = volt * 1000 / curr;
545 /*calculating temperature*/
546 for (temp = 58; temp >= 0; temp--) {
547 int actual = therm_tbl [temp];
548 if ((actual - res) >= 0)
552 /* Negative temperature */
566 * Return battery voltage
569 static int twl4030battery_voltage(void)
571 int volt = read_bci_val(T2_BATTERY_VOLT);
573 return (volt * VOLT_STEP_SIZE) / VOLT_PSR_R;
577 * Return the battery current
580 static int twl4030battery_current(void)
582 int ret, curr = read_bci_val(T2_BATTERY_CUR);
585 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
590 if (val & CGAIN) /* slope of 0.44 mV/mA */
591 return (curr * CURR_STEP_SIZE) / CURR_PSR_R1;
592 else /* slope of 0.88 mV/mA */
593 return (curr * CURR_STEP_SIZE) / CURR_PSR_R2;
597 * Return the battery backup voltage
600 static int twl4030backupbatt_voltage(void)
604 struct twl4030_madc_request req;
606 req.channels = (1 << 9);
607 req.method = TWL4030_MADC_SW1;
608 twl4030_madc_conversion(&req);
609 temp = (u16)req.rbuf[9];
611 return (temp * BK_VOLT_STEP_SIZE) / BK_VOLT_PSR_R;
615 * Returns an integer value, that means,
616 * NO_PW_CONN no power supply is connected
617 * AC_PW_CONN if the AC power supply is connected
618 * USB_PW_CONN if the USB power supply is connected
619 * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected
623 static int twl4030charger_presence(void)
628 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
629 REG_STS_HW_CONDITIONS);
631 pr_err("BATTERY DRIVER: error reading STS_HW_CONDITIONS \n");
635 ret = (hwsts & STS_CHG)? AC_PW_CONN: NO_PW_CONN;
636 ret += (hwsts & STS_VBUS)? USB_PW_CONN: NO_PW_CONN;
638 if (ret & USB_PW_CONN)
639 usb_charger_flag = 1;
641 usb_charger_flag = 0;
648 * Returns the main charge FSM status
651 static int twl4030bci_status(void)
656 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
657 &status, REG_BCIMSTATEC);
659 pr_err("BATTERY DRIVER: error reading BCIMSTATEC \n");
663 return (int) (status & BCIMSTAT_MASK);
666 static int read_bci_val(u8 reg)
672 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
677 temp = ((int)(val & 0x03)) << 8;
680 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
689 * Settup the twl4030 BCI module to enable backup
692 static int twl4030backupbatt_voltage_setup(void)
696 /* Starting backup batery charge */
697 ret = clear_n_set(TWL4030_MODULE_PM_RECEIVER, 0, BBCHEN,
706 * Settup the twl4030 BCI module to measure battery
709 static int twl4030battery_temp_setup(void)
713 /* Enabling thermistor current */
714 ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
723 * Sets and clears bits on an given register on a given module
725 static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg)
730 /* Gets the initial register value */
731 ret = twl4030_i2c_read_u8(mod_no, &val, reg);
735 /* Clearing all those bits to clear */
738 /* Setting all those bits to set */
741 /* Update the register */
742 ret = twl4030_i2c_write_u8(mod_no, val, reg);
749 static enum power_supply_property twl4030_bci_battery_props[] = {
750 POWER_SUPPLY_PROP_STATUS,
751 POWER_SUPPLY_PROP_ONLINE,
752 POWER_SUPPLY_PROP_VOLTAGE_NOW,
753 POWER_SUPPLY_PROP_CURRENT_NOW,
754 POWER_SUPPLY_PROP_CAPACITY,
755 POWER_SUPPLY_PROP_TEMP,
758 static enum power_supply_property twl4030_bk_bci_battery_props[] = {
759 POWER_SUPPLY_PROP_VOLTAGE_NOW,
763 twl4030_bk_bci_battery_read_status(struct twl4030_bci_device_info *di)
765 di->bk_voltage_uV = twl4030backupbatt_voltage();
768 static void twl4030_bk_bci_battery_work(struct work_struct *work)
770 struct twl4030_bci_device_info *di = container_of(work,
771 struct twl4030_bci_device_info,
772 twl4030_bk_bci_monitor_work.work);
774 twl4030_bk_bci_battery_read_status(di);
775 schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
778 static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
780 di->temp_C = twl4030battery_temperature();
781 di->voltage_uV = twl4030battery_voltage();
782 di->current_uA = twl4030battery_current();
786 twl4030_bci_battery_update_status(struct twl4030_bci_device_info *di)
788 twl4030_bci_battery_read_status(di);
789 di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
791 if (power_supply_am_i_supplied(&di->bat))
792 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
794 di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
797 static void twl4030_bci_battery_work(struct work_struct *work)
799 struct twl4030_bci_device_info *di = container_of(work,
800 struct twl4030_bci_device_info, twl4030_bci_monitor_work.work);
802 twl4030_bci_battery_update_status(di);
803 schedule_delayed_work(&di->twl4030_bci_monitor_work, 100);
807 #define to_twl4030_bci_device_info(x) container_of((x), \
808 struct twl4030_bci_device_info, bat);
810 static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
812 struct twl4030_bci_device_info *di = to_twl4030_bci_device_info(psy);
814 cancel_delayed_work(&di->twl4030_bci_monitor_work);
815 schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
818 #define to_twl4030_bk_bci_device_info(x) container_of((x), \
819 struct twl4030_bci_device_info, bk_bat);
821 static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
822 enum power_supply_property psp,
823 union power_supply_propval *val)
825 struct twl4030_bci_device_info *di = to_twl4030_bk_bci_device_info(psy);
828 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
829 val->intval = di->bk_voltage_uV;
838 static int twl4030_bci_battery_get_property(struct power_supply *psy,
839 enum power_supply_property psp,
840 union power_supply_propval *val)
842 struct twl4030_bci_device_info *di = to_twl4030_bci_device_info(psy);
846 case POWER_SUPPLY_PROP_STATUS:
847 val->intval = di->charge_status;
854 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
855 val->intval = di->voltage_uV;
857 case POWER_SUPPLY_PROP_CURRENT_NOW:
858 val->intval = di->current_uA;
860 case POWER_SUPPLY_PROP_TEMP:
861 val->intval = di->temp_C;
863 case POWER_SUPPLY_PROP_ONLINE:
864 status = twl4030bci_status();
865 if ((status & AC_STATEC) == AC_STATEC)
866 val->intval = POWER_SUPPLY_TYPE_MAINS;
867 else if (usb_charger_flag)
868 val->intval = POWER_SUPPLY_TYPE_USB;
872 case POWER_SUPPLY_PROP_CAPACITY:
874 * need to get the correct percentage value per the
875 * battery characteristics. Approx values for now.
877 if (di->voltage_uV < 2894 || LVL_1) {
880 } else if ((di->voltage_uV < 3451 && di->voltage_uV > 2894)
884 } else if ((di->voltage_uV < 3902 && di->voltage_uV > 3451)
888 } else if ((di->voltage_uV < 3949 && di->voltage_uV > 3902)
892 } else if (di->voltage_uV > 3949)
901 static char *twl4030_bci_supplied_to[] = {
902 "twl4030_bci_battery",
905 static int twl4030_bci_battery_probe(struct platform_device *dev)
907 struct twl4030_bci_device_info *di;
909 struct twl4030_bci_platform_data *pdata = dev->dev.platform_data;
911 therm_tbl = pdata->battery_tmp_tbl;
913 di = kzalloc(sizeof(*di), GFP_KERNEL);
917 platform_set_drvdata(dev, di);
920 di->bat.name = "twl4030_bci_battery";
921 di->bat.supplied_to = twl4030_bci_supplied_to;
922 di->bat.num_supplicants = ARRAY_SIZE(twl4030_bci_supplied_to);
923 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
924 di->bat.properties = twl4030_bci_battery_props;
925 di->bat.num_properties = ARRAY_SIZE(twl4030_bci_battery_props);
926 di->bat.get_property = twl4030_bci_battery_get_property;
927 di->bat.external_power_changed =
928 twl4030_bci_battery_external_power_changed;
930 di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
932 di->bk_bat.name = "twl4030_bci_bk_battery";
933 di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
934 di->bk_bat.properties = twl4030_bk_bci_battery_props;
935 di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
936 di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
937 di->bk_bat.external_power_changed = NULL;
939 twl4030charger_ac_en(ENABLE);
940 twl4030charger_usb_en(ENABLE);
941 twl4030battery_hw_level_en(ENABLE);
942 twl4030battery_hw_presence_en(ENABLE);
944 /* settings for temperature sensing */
945 ret = twl4030battery_temp_setup();
947 goto temp_setup_fail;
949 /* enabling GPCH09 for read back battery voltage */
950 ret = twl4030backupbatt_voltage_setup();
952 goto voltage_setup_fail;
954 /* request BCI interruption */
955 ret = request_irq(TWL4030_MODIRQ_BCI, twl4030battery_interrupt,
956 IRQF_DISABLED, dev->name, NULL);
958 pr_err("BATTERY DRIVER: (BCI) IRQ%d is not free.\n",
963 /* request Power interruption */
964 ret = request_irq(TWL4030_PWRIRQ_CHG_PRES, twl4030charger_interrupt,
968 pr_err("BATTERY DRIVER: (POWER) IRQ%d is not free.\n",
973 ret = power_supply_register(&dev->dev, &di->bat);
975 pr_err("BATTERY DRIVER: failed to register main battery\n");
979 INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bci_monitor_work,
980 twl4030_bci_battery_work);
981 schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
983 ret = power_supply_register(&dev->dev, &di->bk_bat);
985 pr_err("BATTERY DRIVER: failed to register backup battery\n");
989 INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bk_bci_monitor_work,
990 twl4030_bk_bci_battery_work);
991 schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
996 power_supply_unregister(&di->bat);
998 free_irq(TWL4030_MODIRQ_PWR, di);
1001 free_irq(TWL4030_MODIRQ_BCI, NULL);
1005 twl4030charger_ac_en(DISABLE);
1006 twl4030charger_usb_en(DISABLE);
1007 twl4030battery_hw_level_en(DISABLE);
1008 twl4030battery_hw_presence_en(DISABLE);
1014 static int twl4030_bci_battery_remove(struct platform_device *dev)
1016 struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
1018 twl4030charger_ac_en(DISABLE);
1019 twl4030charger_usb_en(DISABLE);
1020 twl4030battery_hw_level_en(DISABLE);
1021 twl4030battery_hw_presence_en(DISABLE);
1023 free_irq(TWL4030_MODIRQ_BCI, NULL);
1024 free_irq(TWL4030_MODIRQ_PWR, di);
1026 flush_scheduled_work();
1027 power_supply_unregister(&di->bat);
1028 power_supply_unregister(&di->bk_bat);
1029 platform_set_drvdata(dev, NULL);
1036 static int twl4030_bci_battery_suspend(struct platform_device *dev,
1039 struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
1041 di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
1042 cancel_delayed_work(&di->twl4030_bci_monitor_work);
1043 cancel_delayed_work(&di->twl4030_bk_bci_monitor_work);
1047 static int twl4030_bci_battery_resume(struct platform_device *dev)
1049 struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
1051 schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
1052 schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 50);
1055 #endif /* CONFIG_PM */
1058 * Battery driver module initializer function
1059 * registers battery driver structure
1061 static int __init twl4030_battery_init(void)
1063 return platform_driver_register(&twl4030_bci_battery_driver);
1068 * Battery driver module exit function
1069 * unregister battery driver structure
1071 static void __exit twl4030_battery_exit(void)
1073 platform_driver_unregister(&twl4030_bci_battery_driver);
1076 module_init(twl4030_battery_init);
1077 module_exit(twl4030_battery_exit);
1078 MODULE_LICENSE("GPL");
1079 MODULE_ALIAS("twl4030_bci_battery");
1080 MODULE_AUTHOR("Texas Instruments Inc");