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.
19 /* Boot with automatic charge */
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <linux/device.h>
25 #include <linux/interrupt.h>
26 #include <linux/delay.h>
27 #include <linux/platform_device.h>
28 #include <linux/i2c/twl4030.h>
29 #include <linux/power_supply.h>
30 #include <linux/i2c/twl4030-madc.h>
32 #define T2_BATTERY_VOLT 0x04
33 #define T2_BATTERY_TEMP 0x06
34 #define T2_BATTERY_CUR 0x08
36 /* charger constants */
38 #define AC_PW_CONN 0x01
39 #define USB_PW_CONN 0x02
41 /* TWL4030_MODULE_USB */
42 #define REG_POWER_CTRL 0x0AC
44 #define REG_PHY_CLK_CTRL 0x0FE
45 #define REG_PHY_CLK_CTRL_STS 0x0FF
46 #define PHY_DPLL_CLK 0x01
48 #define REG_BCICTL1 0x023
49 #define REG_BCICTL2 0x024
54 /* Boot BCI flag bits */
55 #define BCIAUTOWEN 0x020
56 #define CONFIG_DONE 0x010
58 #define BCIAUTOUSB 0x002
59 #define BCIAUTOAC 0x001
60 #define BCIMSTAT_MASK 0x03F
62 /* Boot BCI register */
63 #define REG_BOOT_BCI 0x007
64 #define REG_CTRL1 0x00
65 #define REG_SW1SELECT_MSB 0x07
66 #define SW1_CH9_SEL 0x02
67 #define REG_CTRL_SW1 0x012
68 #define SW1_TRIGGER 0x020
70 #define REG_GPCH9 0x049
71 #define REG_STS_HW_CONDITIONS 0x0F
72 #define STS_VBUS 0x080
74 #define REG_BCIMSTATEC 0x02
75 #define REG_BCIMFSTS4 0x010
76 #define REG_BCIMFSTS2 0x00E
77 #define REG_BCIMFSTS3 0x00F
78 #define REG_BCIMFSTS1 0x001
79 #define USBFASTMCHG 0x004
80 #define BATSTSPCHG 0x004
81 #define BATSTSMCHG 0x040
86 #define REG_BB_CFG 0x012
90 #define REG_GPBR1 0x0c
91 #define MADC_HFCLK_EN 0x80
92 #define DEFAULT_MADC_CLK_EN 0x10
94 /* Power supply charge interrupt */
95 #define REG_PWR_ISR1 0x00
96 #define REG_PWR_IMR1 0x01
97 #define REG_PWR_EDR1 0x05
98 #define REG_PWR_SIH_CTRL 0x007
100 #define USB_PRES 0x004
101 #define CHG_PRES 0x002
103 #define USB_PRES_RISING 0x020
104 #define USB_PRES_FALLING 0x010
105 #define CHG_PRES_RISING 0x008
106 #define CHG_PRES_FALLING 0x004
107 #define AC_STATEC 0x20
110 /* interrupt status registers */
111 #define REG_BCIISR1A 0x0
112 #define REG_BCIISR2A 0x01
114 /* Interrupt flags bits BCIISR1 */
115 #define BATSTS_ISR1 0x080
116 #define VBATLVL_ISR1 0x001
118 /* Interrupt mask registers for int1*/
119 #define REG_BCIIMR1A 0x002
120 #define REG_BCIIMR2A 0x003
122 /* Interrupt masks for BCIIMR1 */
123 #define BATSTS_IMR1 0x080
124 #define VBATLVL_IMR1 0x001
126 /* Interrupt edge detection register */
127 #define REG_BCIEDR1 0x00A
128 #define REG_BCIEDR2 0x00B
129 #define REG_BCIEDR3 0x00C
132 #define BATSTS_EDRRISIN 0x080
133 #define BATSTS_EDRFALLING 0x040
136 #define VBATLVL_EDRRISIN 0x02
139 #define REG_BCIIREF1 0x027
140 #define REG_BCIIREF2 0x028
143 #define REG_BCIMFTH1 0x016
146 #define KEY_IIREF 0xE7
147 #define KEY_FTH1 0xD2
148 #define REG_BCIMFKEY 0x011
150 /* Step size and prescaler ratio */
151 #define TEMP_STEP_SIZE 147
152 #define TEMP_PSR_R 100
154 #define VOLT_STEP_SIZE 588
155 #define VOLT_PSR_R 100
157 #define CURR_STEP_SIZE 147
158 #define CURR_PSR_R1 44
159 #define CURR_PSR_R2 80
161 #define BK_VOLT_STEP_SIZE 441
162 #define BK_VOLT_PSR_R 100
167 struct twl4030_bci_device_info {
170 unsigned long update_time;
178 struct power_supply bat;
179 struct power_supply bk_bat;
180 struct delayed_work twl4030_bci_monitor_work;
181 struct delayed_work twl4030_bk_bci_monitor_work;
183 struct twl4030_bci_platform_data *pdata;
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 (chg_sts & STS_CHG) { /* If the AC charger have been connected */
208 /* configuring falling edge detection for CHG_PRES */
209 set = CHG_PRES_FALLING;
210 clear = CHG_PRES_RISING;
211 } else { /* If the AC charger have been disconnected */
212 /* configuring rising edge detection for CHG_PRES */
213 set = CHG_PRES_RISING;
214 clear = CHG_PRES_FALLING;
217 /* Update the interrupt edge detection register */
218 clear_n_set(TWL4030_MODULE_INT, clear, set, REG_PWR_EDR1);
224 * Interrupt service routine
226 * Attends to TWL 4030 power module interruptions events, specifically
227 * USB_PRES (USB charger presence) CHG_PRES (AC charger presence) events
230 static irqreturn_t twl4030charger_interrupt(int irq, void *_di)
232 struct twl4030_bci_device_info *di = _di;
234 #ifdef CONFIG_LOCKDEP
235 /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
236 * we don't want and can't tolerate. Although it might be
237 * friendlier not to borrow this thread context...
242 twl4030charger_presence_evt();
243 power_supply_changed(&di->bat);
249 * This function handles the twl4030 battery presence interrupt
251 static int twl4030battery_presence_evt(void)
254 u8 batstsmchg, batstspchg;
256 /* check for the battery presence in main charge*/
257 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
258 &batstsmchg, REG_BCIMFSTS3);
262 /* check for the battery presence in precharge */
263 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PRECHARGE,
264 &batstspchg, REG_BCIMFSTS1);
269 * REVISIT: Physically inserting/removing the batt
270 * does not seem to generate an int on 3430ES2 SDP.
272 if ((batstspchg & BATSTSPCHG) || (batstsmchg & BATSTSMCHG)) {
273 /* In case of the battery insertion event */
274 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRRISIN,
275 BATSTS_EDRFALLING, REG_BCIEDR2);
279 /* In case of the battery removal event */
280 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRFALLING,
281 BATSTS_EDRRISIN, REG_BCIEDR2);
290 * This function handles the twl4030 battery voltage level interrupt.
292 static int twl4030battery_level_evt(void)
297 /* checking for threshold event */
298 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
299 &mfst, REG_BCIMFSTS2);
303 /* REVISIT could use a bitmap */
304 if (mfst & VBATOV4) {
309 } else if (mfst & VBATOV3) {
314 } else if (mfst & VBATOV2) {
330 * Interrupt service routine
332 * Attends to BCI interruptions events,
333 * specifically BATSTS (battery connection and removal)
334 * VBATOV (main battery voltage threshold) events
337 static irqreturn_t twl4030battery_interrupt(int irq, void *_di)
339 u8 isr1a_val, isr2a_val, clear_2a, clear_1a;
342 #ifdef CONFIG_LOCKDEP
343 /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
344 * we don't want and can't tolerate. Although it might be
345 * friendlier not to borrow this thread context...
350 ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val,
355 ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr2a_val,
360 clear_2a = (isr2a_val & VBATLVL_ISR1) ? (VBATLVL_ISR1) : 0;
361 clear_1a = (isr1a_val & BATSTS_ISR1) ? (BATSTS_ISR1) : 0;
363 /* cleaning BCI interrupt status flags */
364 ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
365 clear_1a , REG_BCIISR1A);
369 ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
370 clear_2a , REG_BCIISR2A);
374 /* battery connetion or removal event */
375 if (isr1a_val & BATSTS_ISR1)
376 twl4030battery_presence_evt();
377 /* battery voltage threshold event*/
378 else if (isr2a_val & VBATLVL_ISR1)
379 twl4030battery_level_evt();
387 * Enable/Disable hardware battery level event notifications.
389 static int twl4030battery_hw_level_en(int enable)
394 /* unmask VBATOV interrupt for INT1 */
395 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, VBATLVL_IMR1,
400 /* configuring interrupt edge detection for VBATOv */
401 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
402 VBATLVL_EDRRISIN, REG_BCIEDR3);
406 /* mask VBATOV interrupt for INT1 */
407 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
408 VBATLVL_IMR1, REG_BCIIMR2A);
417 * Enable/disable hardware battery presence event notifications.
419 static int twl4030battery_hw_presence_en(int enable)
424 /* unmask BATSTS interrupt for INT1 */
425 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_IMR1,
430 /* configuring interrupt edge for BATSTS */
431 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
432 BATSTS_EDRRISIN | BATSTS_EDRFALLING, REG_BCIEDR2);
436 /* mask BATSTS interrupt for INT1 */
437 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
438 BATSTS_IMR1, REG_BCIIMR1A);
447 * Enable/Disable AC Charge funtionality.
449 static int twl4030charger_ac_en(int enable, int automatic)
454 /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
456 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
457 (CONFIG_DONE | BCIAUTOWEN),
460 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
461 (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
467 /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 0*/
468 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC,
469 (CONFIG_DONE | BCIAUTOWEN),
479 * Enable/Disable USB Charge funtionality.
481 int twl4030charger_usb_en(int enable)
485 unsigned long timeout;
488 /* Check for USB charger conneted */
489 ret = twl4030charger_presence();
493 if (!(ret & USB_PW_CONN))
496 /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
497 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
498 (CONFIG_DONE | BCIAUTOWEN | BCIAUTOUSB),
503 ret = clear_n_set(TWL4030_MODULE_USB, 0, PHY_DPLL_CLK,
509 timeout = jiffies + msecs_to_jiffies(50);
511 while ((!(value & PHY_DPLL_CLK)) &&
512 time_before(jiffies, timeout)) {
514 ret = twl4030_i2c_read_u8(TWL4030_MODULE_USB, &value,
515 REG_PHY_CLK_CTRL_STS);
520 /* OTG_EN (POWER_CTRL[5]) to 1 */
521 ret = clear_n_set(TWL4030_MODULE_USB, 0, OTG_EN,
528 /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
529 ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0,
530 USBFASTMCHG, REG_BCIMFSTS4);
534 twl4030charger_presence();
535 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOUSB,
536 (CONFIG_DONE | BCIAUTOWEN), REG_BOOT_BCI);
545 * Return battery temperature
548 static int twl4030battery_temperature(struct twl4030_bci_device_info *di)
551 int temp, curr, volt, res, ret;
553 /* Is a temperature table specified? */
554 if (!di->pdata->tblsize)
557 /* Getting and calculating the thermistor voltage */
558 ret = read_bci_val(T2_BATTERY_TEMP);
562 volt = (ret * TEMP_STEP_SIZE) / TEMP_PSR_R;
564 /* Getting and calculating the supply current in micro ampers */
565 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
570 curr = ((val & ITHSENS) + 1) * 10;
572 /* Getting and calculating the thermistor resistance in ohms*/
573 res = volt * 1000 / curr;
575 /*calculating temperature*/
576 for (temp = 58; temp >= 0; temp--) {
577 int actual = di->pdata->battery_tmp_tbl[temp];
578 if ((actual - res) >= 0)
582 /* Negative temperature */
596 * Return battery voltage
599 static int twl4030battery_voltage(void)
601 int volt = read_bci_val(T2_BATTERY_VOLT);
603 return (volt * VOLT_STEP_SIZE) / VOLT_PSR_R;
607 * Return the battery current
610 static int twl4030battery_current(void)
612 int ret, curr = read_bci_val(T2_BATTERY_CUR);
615 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
620 if (val & CGAIN) /* slope of 0.44 mV/mA */
621 return (curr * CURR_STEP_SIZE) / CURR_PSR_R1;
622 else /* slope of 0.88 mV/mA */
623 return (curr * CURR_STEP_SIZE) / CURR_PSR_R2;
627 * Return the battery backup voltage
630 static int twl4030backupbatt_voltage(void)
632 struct twl4030_madc_request req;
635 req.channels = (1 << 9);
637 req.method = TWL4030_MADC_SW1;
640 twl4030_madc_conversion(&req);
641 temp = (u16)req.rbuf[9];
643 return (temp * BK_VOLT_STEP_SIZE) / BK_VOLT_PSR_R;
647 * Returns an integer value, that means,
648 * NO_PW_CONN no power supply is connected
649 * AC_PW_CONN if the AC power supply is connected
650 * USB_PW_CONN if the USB power supply is connected
651 * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected
655 static int twl4030charger_presence(void)
660 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
661 REG_STS_HW_CONDITIONS);
663 pr_err("twl4030_bci: error reading STS_HW_CONDITIONS\n");
667 ret = (hwsts & STS_CHG) ? AC_PW_CONN : NO_PW_CONN;
668 ret += (hwsts & STS_VBUS) ? USB_PW_CONN : NO_PW_CONN;
670 if (ret & USB_PW_CONN)
671 usb_charger_flag = 1;
673 usb_charger_flag = 0;
680 * Returns the main charge FSM status
683 static int twl4030bci_status(void)
688 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
689 &status, REG_BCIMSTATEC);
691 pr_err("twl4030_bci: error reading BCIMSTATEC\n");
697 static int oldstatus = -1;
698 if (status != oldstatus)
699 printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
703 return (int) (status & BCIMSTAT_MASK);
706 static int read_bci_val(u8 reg)
712 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
717 temp = ((int)(val & 0x03)) << 8;
720 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
729 * Settup the twl4030 BCI module to enable backup
732 static int twl4030backupbatt_voltage_setup(void)
736 /* Starting backup batery charge */
737 ret = clear_n_set(TWL4030_MODULE_PM_RECEIVER, 0, BBCHEN,
746 * Settup the twl4030 BCI module to measure battery
749 static int twl4030battery_temp_setup(int dump)
756 /* Enabling thermistor current */
757 ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
765 twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
766 printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
768 twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_STS_HW_CONDITIONS);
769 printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
771 twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
772 printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
774 twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
775 printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
777 twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
778 printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
780 twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
781 printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
783 for(i = 0x0; i <= 0x32; i++)
785 twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
786 printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
794 * Sets and clears bits on an given register on a given module
796 static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg)
801 /* Gets the initial register value */
802 ret = twl4030_i2c_read_u8(mod_no, &val, reg);
805 /* Clearing all those bits to clear */
808 /* Setting all those bits to set */
811 /* Update the register */
812 ret = twl4030_i2c_write_u8(mod_no, val, reg);
819 static enum power_supply_property twl4030_bci_battery_props[] = {
820 POWER_SUPPLY_PROP_STATUS,
821 POWER_SUPPLY_PROP_ONLINE,
822 POWER_SUPPLY_PROP_VOLTAGE_NOW,
823 POWER_SUPPLY_PROP_CURRENT_NOW,
824 POWER_SUPPLY_PROP_CAPACITY,
825 POWER_SUPPLY_PROP_TEMP,
828 static enum power_supply_property twl4030_bk_bci_battery_props[] = {
829 POWER_SUPPLY_PROP_VOLTAGE_NOW,
833 twl4030_bk_bci_battery_read_status(struct twl4030_bci_device_info *di)
835 di->bk_voltage_uV = twl4030backupbatt_voltage();
838 static void twl4030_bk_bci_battery_work(struct work_struct *work)
840 struct twl4030_bci_device_info *di = container_of(work,
841 struct twl4030_bci_device_info,
842 twl4030_bk_bci_monitor_work.work);
844 if(!di->pdata->no_backup_battery)
845 twl4030_bk_bci_battery_read_status(di);
846 schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
849 static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
851 di->temp_C = twl4030battery_temperature(di);
852 di->voltage_uV = twl4030battery_voltage();
853 di->current_uA = twl4030battery_current();
857 twl4030_bci_battery_update_status(struct twl4030_bci_device_info *di)
859 twl4030_bci_battery_read_status(di);
860 di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
862 if (power_supply_am_i_supplied(&di->bat))
863 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
865 di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
868 static void twl4030_bci_battery_work(struct work_struct *work)
870 struct twl4030_bci_device_info *di = container_of(work,
871 struct twl4030_bci_device_info, twl4030_bci_monitor_work.work);
873 twl4030_bci_battery_update_status(di);
874 schedule_delayed_work(&di->twl4030_bci_monitor_work, 100);
878 #define to_twl4030_bci_device_info(x) container_of((x), \
879 struct twl4030_bci_device_info, bat);
881 static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
883 struct twl4030_bci_device_info *di = to_twl4030_bci_device_info(psy);
885 cancel_delayed_work(&di->twl4030_bci_monitor_work);
886 schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
889 #define to_twl4030_bk_bci_device_info(x) container_of((x), \
890 struct twl4030_bci_device_info, bk_bat);
893 show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
896 int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
897 twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
904 twl4030battery_temp_setup(1);
907 return sprintf(buf, "%d\n", ret);
911 set_charge_current(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
913 unsigned long newCurrent;
916 ret = strict_strtoul(buf, 10, &newCurrent);
920 ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
924 ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent & 0xff, REG_BCIIREF1);
928 ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
932 ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x1, REG_BCIIREF2);
936 /* Set software-controlled charge */
937 twl4030charger_ac_en(ENABLE, 0);
939 /* Set CGAIN = 0 or 1 */
940 if(newCurrent > 511) {
943 /* Set CGAIN = 1 -- need to wait until automatic charge turns off */
945 clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B, REG_BCICTL1);
946 twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
955 /* Set CGAIN = 0 -- need to wait until automatic charge turns off */
957 clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
958 twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
960 ret = !(tmp & CGAIN);
966 /* Set automatic charge (CGAIN = 0/1 persists) */
967 twl4030charger_ac_en(ENABLE, 1);
971 static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUSR, show_charge_current, set_charge_current);
974 show_current2(struct device *dev, struct device_attribute *attr, char *buf)
976 int ret, curr = read_bci_val(T2_BATTERY_CUR);
979 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
985 //ret = (int)((float)curr * 1.6617790811339199f * 2.0f - 1.7f);
986 ret = curr * 16618 * 2 - 1700 * 10000;
988 //ret = (int)((float)curr * 1.6617790811339199f - 0.85f);
989 ret = curr * 16618 - 850 * 10000;
992 return sprintf(buf, "%d (BCIICHG2 = 0x%02x, BCIICHG1 = 0x%02x, CGAIN = %d)\n",
993 ret, curr >> 8, curr & 0xff, (val & CGAIN) ? 1 : 0);
995 static DEVICE_ATTR(current_now2, S_IRUGO | S_IWUSR, show_current2, NULL);
997 static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
998 enum power_supply_property psp,
999 union power_supply_propval *val)
1001 struct twl4030_bci_device_info *di = to_twl4030_bk_bci_device_info(psy);
1004 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1005 val->intval = di->bk_voltage_uV;
1014 static int twl4030_bci_battery_get_property(struct power_supply *psy,
1015 enum power_supply_property psp,
1016 union power_supply_propval *val)
1018 struct twl4030_bci_device_info *di;
1021 di = to_twl4030_bci_device_info(psy);
1024 case POWER_SUPPLY_PROP_STATUS:
1025 val->intval = di->charge_status;
1032 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1033 val->intval = di->voltage_uV;
1035 case POWER_SUPPLY_PROP_CURRENT_NOW:
1036 val->intval = di->current_uA;
1038 case POWER_SUPPLY_PROP_TEMP:
1039 val->intval = di->temp_C;
1041 case POWER_SUPPLY_PROP_ONLINE:
1042 status = twl4030bci_status();
1043 if ((status & AC_STATEC) == AC_STATEC)
1044 val->intval = POWER_SUPPLY_TYPE_MAINS;
1045 else if (usb_charger_flag)
1046 val->intval = POWER_SUPPLY_TYPE_USB;
1050 case POWER_SUPPLY_PROP_CAPACITY:
1052 * need to get the correct percentage value per the
1053 * battery characteristics. Approx values for now.
1055 if (di->voltage_uV < 2894 || LVL_1) {
1058 } else if ((di->voltage_uV < 3451 && di->voltage_uV > 2894)
1062 } else if ((di->voltage_uV < 3902 && di->voltage_uV > 3451)
1066 } else if ((di->voltage_uV < 3949 && di->voltage_uV > 3902)
1070 } else if (di->voltage_uV > 3949)
1079 static char *twl4030_bci_supplied_to[] = {
1080 "twl4030_bci_battery",
1083 static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
1085 struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
1086 struct twl4030_bci_device_info *di;
1090 di = kzalloc(sizeof(*di), GFP_KERNEL);
1094 di->dev = &pdev->dev;
1095 di->bat.name = "twl4030_bci_battery";
1096 di->bat.supplied_to = twl4030_bci_supplied_to;
1097 di->bat.num_supplicants = ARRAY_SIZE(twl4030_bci_supplied_to);
1098 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
1099 di->bat.properties = twl4030_bci_battery_props;
1100 di->bat.num_properties = ARRAY_SIZE(twl4030_bci_battery_props);
1101 di->bat.get_property = twl4030_bci_battery_get_property;
1102 di->bat.external_power_changed =
1103 twl4030_bci_battery_external_power_changed;
1105 di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
1107 di->bk_bat.name = "twl4030_bci_bk_battery";
1108 di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
1109 di->bk_bat.properties = twl4030_bk_bci_battery_props;
1110 di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
1111 di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
1112 di->bk_bat.external_power_changed = NULL;
1116 twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, REG_GPBR1);
1118 twl4030charger_ac_en(ENABLE, CHARGE_MODE);
1119 twl4030charger_usb_en(ENABLE);
1120 twl4030battery_hw_level_en(ENABLE);
1121 twl4030battery_hw_presence_en(ENABLE);
1123 platform_set_drvdata(pdev, di);
1125 /* settings for temperature sensing */
1126 ret = twl4030battery_temp_setup(0);
1128 goto temp_setup_fail;
1130 /* enabling GPCH09 for read back battery voltage */
1131 if(!di->pdata->no_backup_battery)
1133 ret = twl4030backupbatt_voltage_setup();
1135 goto voltage_setup_fail;
1138 /* REVISIT do we need to request both IRQs ?? */
1140 /* request BCI interruption */
1141 ret = request_irq(TWL4030_MODIRQ_BCI, twl4030battery_interrupt,
1142 0, pdev->name, NULL);
1144 dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
1145 TWL4030_MODIRQ_BCI, ret);
1149 irq = platform_get_irq(pdev, 0);
1151 /* request Power interruption */
1152 ret = request_irq(irq, twl4030charger_interrupt,
1156 dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
1161 ret = power_supply_register(&pdev->dev, &di->bat);
1163 dev_dbg(&pdev->dev, "failed to register main battery\n");
1167 INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bci_monitor_work,
1168 twl4030_bci_battery_work);
1169 schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
1171 if(!pdata->no_backup_battery)
1173 ret = power_supply_register(&pdev->dev, &di->bk_bat);
1175 dev_dbg(&pdev->dev, "failed to register backup battery\n");
1176 goto bk_batt_failed;
1180 ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
1182 dev_err(&pdev->dev, "failed to create sysfs entries\n");
1183 goto bk_batt_failed;
1185 device_create_file(di->bat.dev, &dev_attr_current_now2);
1187 INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bk_bci_monitor_work,
1188 twl4030_bk_bci_battery_work);
1189 schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
1194 if(!pdata->no_backup_battery)
1195 power_supply_unregister(&di->bat);
1199 free_irq(TWL4030_MODIRQ_BCI, NULL);
1203 twl4030charger_ac_en(DISABLE, CHARGE_MODE);
1204 twl4030charger_usb_en(DISABLE);
1205 twl4030battery_hw_level_en(DISABLE);
1206 twl4030battery_hw_presence_en(DISABLE);
1212 static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
1214 struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
1215 int irq = platform_get_irq(pdev, 0);
1217 twl4030charger_ac_en(DISABLE, CHARGE_MODE);
1218 twl4030charger_usb_en(DISABLE);
1219 twl4030battery_hw_level_en(DISABLE);
1220 twl4030battery_hw_presence_en(DISABLE);
1222 free_irq(TWL4030_MODIRQ_BCI, NULL);
1225 flush_scheduled_work();
1226 power_supply_unregister(&di->bat);
1227 power_supply_unregister(&di->bk_bat);
1228 platform_set_drvdata(pdev, NULL);
1235 static int twl4030_bci_battery_suspend(struct platform_device *pdev,
1238 struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
1240 di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
1241 cancel_delayed_work(&di->twl4030_bci_monitor_work);
1242 cancel_delayed_work(&di->twl4030_bk_bci_monitor_work);
1246 static int twl4030_bci_battery_resume(struct platform_device *pdev)
1248 struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
1250 schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
1251 schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 50);
1255 #define twl4030_bci_battery_suspend NULL
1256 #define twl4030_bci_battery_resume NULL
1257 #endif /* CONFIG_PM */
1259 static struct platform_driver twl4030_bci_battery_driver = {
1260 .probe = twl4030_bci_battery_probe,
1261 .remove = __exit_p(twl4030_bci_battery_remove),
1262 .suspend = twl4030_bci_battery_suspend,
1263 .resume = twl4030_bci_battery_resume,
1265 .name = "twl4030_bci",
1269 MODULE_LICENSE("GPL");
1270 MODULE_ALIAS("platform:twl4030_bci");
1271 MODULE_AUTHOR("Texas Instruments Inc");
1273 static int __init twl4030_battery_init(void)
1275 return platform_driver_register(&twl4030_bci_battery_driver);
1277 module_init(twl4030_battery_init);
1279 static void __exit twl4030_battery_exit(void)
1281 platform_driver_unregister(&twl4030_bci_battery_driver);
1283 module_exit(twl4030_battery_exit);