Merge current mainline tree into linux-omap tree
[pandora-kernel.git] / drivers / power / twl4030_bci_battery.c
1 /*
2  * linux/drivers/power/twl4030_bci_battery.c
3  *
4  * OMAP2430/3430 BCI battery driver for Linux
5  *
6  * Copyright (C) 2008 Texas Instruments, Inc.
7  * Author: Texas Instruments, Inc.
8  *
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.
12  *
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.
16  */
17
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 <asm/arch/bci.h>
27 #include <linux/i2c/twl4030-madc.h>
28
29 #define T2_BATTERY_VOLT         0x04
30 #define T2_BATTERY_TEMP         0x06
31 #define T2_BATTERY_CUR          0x08
32
33 /* charger constants */
34 #define NO_PW_CONN              0
35 #define AC_PW_CONN              0x01
36 #define USB_PW_CONN             0x02
37
38 /* TWL4030_MODULE_USB */
39 #define REG_POWER_CTRL          0x0AC
40 #define OTG_EN                  0x020
41 #define REG_PHY_CLK_CTRL        0x0FE
42 #define REG_PHY_CLK_CTRL_STS    0x0FF
43 #define PHY_DPLL_CLK            0x01
44
45 #define REG_BCICTL1             0x023
46 #define REG_BCICTL2             0x024
47 #define CGAIN                   0x020
48 #define ITHEN                   0x010
49 #define ITHSENS                 0x007
50
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
57
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
65 #define EOC_SW1                 0x002
66 #define REG_GPCH9               0x049
67 #define REG_STS_HW_CONDITIONS   0x0F
68 #define STS_VBUS                0x080
69 #define STS_CHG                 0x02
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
78 #define VBATOV4                 0x020
79 #define VBATOV3                 0x010
80 #define VBATOV2                 0x008
81 #define VBATOV1                 0x004
82 #define REG_BB_CFG              0x012
83 #define BBCHEN                  0x010
84
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
90
91 #define USB_PRES                0x004
92 #define CHG_PRES                0x002
93
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
99 #define COR                     0x004
100
101 /* interrupt status registers */
102 #define REG_BCIISR1A            0x0
103 #define REG_BCIISR2A            0x01
104
105 /* Interrupt flags bits BCIISR1 */
106 #define BATSTS_ISR1             0x080
107 #define VBATLVL_ISR1            0x001
108
109 /* Interrupt mask registers for int1*/
110 #define REG_BCIIMR1A            0x002
111 #define REG_BCIIMR2A            0x003
112
113  /* Interrupt masks for BCIIMR1 */
114 #define BATSTS_IMR1             0x080
115 #define VBATLVL_IMR1            0x001
116
117 /* Interrupt edge detection register */
118 #define REG_BCIEDR1             0x00A
119 #define REG_BCIEDR2             0x00B
120 #define REG_BCIEDR3             0x00C
121
122 /* BCIEDR2 */
123 #define BATSTS_EDRRISIN         0x080
124 #define BATSTS_EDRFALLING       0x040
125
126 /* BCIEDR3 */
127 #define VBATLVL_EDRRISIN        0x02
128
129 /* Step size and prescaler ratio */
130 #define TEMP_STEP_SIZE          147
131 #define TEMP_PSR_R              100
132
133 #define VOLT_STEP_SIZE          588
134 #define VOLT_PSR_R              100
135
136 #define CURR_STEP_SIZE          147
137 #define CURR_PSR_R1             44
138 #define CURR_PSR_R2             80
139
140 #define BK_VOLT_STEP_SIZE       441
141 #define BK_VOLT_PSR_R           100
142
143 #define ENABLE          1
144 #define DISABLE         1
145
146 /* Ptr to thermistor table */
147 int *therm_tbl;
148
149 static int twl4030_bci_battery_probe(struct platform_device *dev);
150 static int twl4030_bci_battery_remove(struct platform_device *dev);
151 #ifdef CONFIG_PM
152 static int twl4030_bci_battery_suspend(struct platform_device *dev,
153                                         pm_message_t state);
154 static int twl4030_bci_battery_resume(struct platform_device *dev);
155 #endif
156
157 struct twl4030_bci_device_info {
158         struct device           *dev;
159
160         unsigned long           update_time;
161         int                     voltage_uV;
162         int                     bk_voltage_uV;
163         int                     current_uA;
164         int                     temp_C;
165         int                     charge_rsoc;
166         int                     charge_status;
167
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;
172 };
173
174 static struct platform_driver twl4030_bci_battery_driver = {
175         .probe =        twl4030_bci_battery_probe,
176         .remove =       twl4030_bci_battery_remove,
177 #ifdef CONFIG_PM
178         .suspend =      twl4030_bci_battery_suspend,
179         .resume =       twl4030_bci_battery_resume,
180 #endif
181         .driver = {
182                 .name = "twl4030-bci-battery",
183         },
184 };
185
186 static int usb_charger_flag;
187 static int LVL_1, LVL_2, LVL_3, LVL_4;
188
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);
192
193 /*
194  * Report and clear the charger presence event.
195  */
196 static inline int twl4030charger_presence_evt(void)
197 {
198         int ret;
199         u8 chg_sts, set = 0, clear = 0;
200
201         /* read charger power supply status */
202         ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &chg_sts,
203                 REG_STS_HW_CONDITIONS);
204         if (ret)
205                 return IRQ_NONE;
206
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;
212         }
213         /* If the AC charger have been disconnected */
214         else {
215                 /* configuring rising edge detection for CHG_PRES */
216                 set = CHG_PRES_RISING;
217                 clear = CHG_PRES_FALLING;
218         }
219
220         /* Update the interrupt edge detection register */
221         clear_n_set(TWL4030_MODULE_INT, clear, set, REG_PWR_EDR1);
222
223         return 0;
224 }
225
226 /*
227  * Interrupt service routine
228  *
229  * Attends to TWL 4030 power module interruptions events, specifically
230  * USB_PRES (USB charger presence) CHG_PRES (AC charger presence) events
231  *
232  */
233 static irqreturn_t twl4030charger_interrupt(int irq, void *dev_id)
234 {
235         struct twl4030_bci_device_info *di = dev_id;
236
237         twl4030charger_presence_evt();
238         power_supply_changed(&di->bat);
239
240         return IRQ_HANDLED;
241 }
242
243 /*
244  * This function handles the twl4030 battery presence interrupt
245  */
246 static int twl4030battery_presence_evt(void)
247 {
248         int ret;
249         u8 batstsmchg, batstspchg;
250
251         /* check for the battery presence in main charge*/
252         ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
253                         &batstsmchg, REG_BCIMFSTS3);
254         if (ret)
255                 return ret;
256
257         /* check for the battery presence in precharge */
258         ret = twl4030_i2c_read_u8(TWL4030_MODULE_PRECHARGE,
259                         &batstspchg, REG_BCIMFSTS1);
260         if (ret)
261                 return ret;
262
263         /*
264          * REVISIT: Physically inserting/removing the batt
265          * does not seem to generate an int on 3430ES2 SDP.
266          */
267
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);
272                 if (ret)
273                         return ret;
274         }
275
276         /* In case of the battery removal event */
277         else {
278                 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRFALLING,
279                         BATSTS_EDRRISIN, REG_BCIEDR2);
280                 if (ret)
281                         return ret;
282         }
283
284         return 0;
285 }
286
287 /*
288  * This function handles the twl4030 battery voltage level interrupt.
289  */
290 static int twl4030battery_level_evt(void)
291 {
292         int ret;
293         u8 mfst;
294
295         /* checking for threshold event */
296         ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
297                         &mfst, REG_BCIMFSTS2);
298         if (ret)
299                 return ret;
300
301         if (mfst & VBATOV4) {
302                 LVL_4 = 1;
303                 LVL_3 = LVL_2 = LVL_1 = 0;
304         } else if (mfst & VBATOV3) {
305                 LVL_3 = 1;
306                 LVL_4 = LVL_2 = LVL_1 = 0;
307         } else if (mfst & VBATOV2) {
308                 LVL_2 = 1;
309                 LVL_4 = LVL_3 = LVL_1 = 0;
310         } else {
311                 LVL_1 = 1;
312                 LVL_4 = LVL_3 = LVL_2 = 0;
313         }
314
315         return 0;
316 }
317
318 /*
319  * Interrupt service routine
320  *
321  * Attends to BCI interruptions events,
322  * specifically BATSTS (battery connection and removal)
323  * VBATOV (main battery voltage threshold) events
324  *
325  */
326 static irqreturn_t twl4030battery_interrupt(int irq, void *dev_id)
327 {
328         int ret;
329         u8 isr1a_val, isr2a_val, clear_2a, clear_1a;
330
331         ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val,
332                                 REG_BCIISR1A);
333         if (ret)
334                 return IRQ_NONE;
335
336         ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr2a_val,
337                                 REG_BCIISR2A);
338         if (ret)
339                 return IRQ_NONE;
340
341         clear_2a = (isr2a_val & VBATLVL_ISR1)? (VBATLVL_ISR1): 0;
342         clear_1a = (isr1a_val & BATSTS_ISR1)? (BATSTS_ISR1): 0;
343
344         /* cleaning BCI interrupt status flags */
345         ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
346                         clear_1a , REG_BCIISR1A);
347         if (ret)
348                 return IRQ_NONE;
349
350         ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
351                         clear_2a , REG_BCIISR2A);
352         if (ret)
353                 return IRQ_NONE;
354
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();
361         else
362                 return IRQ_NONE;
363
364         return IRQ_HANDLED;
365 }
366
367 /*
368  * Enable/Disable hardware battery level event notifications.
369  */
370 static int twl4030battery_hw_level_en(int enable)
371 {
372         int ret;
373
374         if (enable) {
375                 /* unmask VBATOV interrupt for INT1 */
376                 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, VBATLVL_IMR1,
377                         0, REG_BCIIMR2A);
378                 if (ret)
379                         return ret;
380
381                 /* configuring interrupt edge detection for VBATOv */
382                 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
383                         VBATLVL_EDRRISIN, REG_BCIEDR3);
384                 if (ret)
385                         return ret;
386         } else {
387                 /* mask VBATOV interrupt for INT1 */
388                 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
389                         VBATLVL_IMR1, REG_BCIIMR2A);
390                 if (ret)
391                         return ret;
392         }
393
394         return 0;
395 }
396
397 /*
398  * Enable/disable hardware battery presence event notifications.
399  */
400 static int twl4030battery_hw_presence_en(int enable)
401 {
402         int ret;
403
404         if (enable) {
405                 /* unmask BATSTS interrupt for INT1 */
406                 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_IMR1,
407                         0, REG_BCIIMR1A);
408                 if (ret)
409                         return ret;
410
411                 /* configuring interrupt edge for BATSTS */
412                 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
413                         BATSTS_EDRRISIN | BATSTS_EDRFALLING, REG_BCIEDR2);
414                 if (ret)
415                         return ret;
416         } else {
417                 /* mask BATSTS interrupt for INT1 */
418                 ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
419                         BATSTS_IMR1, REG_BCIIMR1A);
420                 if (ret)
421                         return ret;
422         }
423
424         return 0;
425 }
426
427 /*
428  * Enable/Disable AC Charge funtionality.
429  */
430 static int twl4030charger_ac_en(int enable)
431 {
432         int ret;
433
434         if (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),
438                         REG_BOOT_BCI);
439                 if (ret)
440                         return ret;
441         } else {
442                 /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 0*/
443                 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC,
444                         (CONFIG_DONE | BCIAUTOWEN),
445                         REG_BOOT_BCI);
446                 if (ret)
447                         return ret;
448         }
449         return 0;
450 }
451
452 /*
453  * Enable/Disable USB Charge funtionality.
454  */
455 int twl4030charger_usb_en(int enable)
456 {
457         u8 value;
458         int ret;
459         unsigned long timeout;
460
461         if (enable) {
462                 /* Check for USB charger conneted */
463                 ret = twl4030charger_presence();
464                 if (ret < 0)
465                         return ret;
466
467                 if (!(ret & USB_PW_CONN))
468                         return -ENXIO;
469
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),
473                         REG_BOOT_BCI);
474                 if (ret)
475                         return ret;
476
477                 ret = clear_n_set(TWL4030_MODULE_USB, 0, PHY_DPLL_CLK,
478                         REG_PHY_CLK_CTRL);
479                 if (ret)
480                         return ret;
481
482                 value = 0;
483                 timeout = jiffies + msecs_to_jiffies(50);
484
485                 while ((!(value & PHY_DPLL_CLK)) &&
486                         time_before(jiffies, timeout)) {
487                         udelay(10);
488                         ret = twl4030_i2c_read_u8(TWL4030_MODULE_USB, &value,
489                                 REG_PHY_CLK_CTRL_STS);
490                         if (ret)
491                                 return ret;
492                 }
493
494                 /* OTG_EN (POWER_CTRL[5]) to 1 */
495                 ret = clear_n_set(TWL4030_MODULE_USB, 0, OTG_EN,
496                         REG_POWER_CTRL);
497                 if (ret)
498                         return ret;
499
500                 mdelay(50);
501
502                 /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
503                 ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0,
504                         USBFASTMCHG, REG_BCIMFSTS4);
505                 if (ret)
506                         return ret;
507         } else {
508                 twl4030charger_presence();
509                 ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOUSB,
510                         (CONFIG_DONE | BCIAUTOWEN), REG_BOOT_BCI);
511                 if (ret)
512                         return ret;
513         }
514
515         return 0;
516 }
517
518 /*
519  * Return battery temperature
520  * Or < 0 on failure.
521  */
522 static int twl4030battery_temperature(void)
523 {
524         u8 val;
525         int temp, curr, volt, res, ret;
526
527         /* Getting and calculating the thermistor voltage */
528         ret = read_bci_val(T2_BATTERY_TEMP);
529         if (ret < 0)
530                 return ret;
531
532         volt = (ret * TEMP_STEP_SIZE) / TEMP_PSR_R;
533
534         /* Getting and calculating the supply current in micro ampers */
535         ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
536                  REG_BCICTL2);
537         if (ret)
538                 return 0;
539
540         curr = ((val & ITHSENS) + 1) * 10;
541
542         /* Getting and calculating the thermistor resistance in ohms*/
543         res = volt * 1000 / curr;
544
545         /*calculating temperature*/
546         for (temp = 58; temp >= 0; temp--) {
547                 int actual = therm_tbl [temp];
548                 if ((actual - res) >= 0)
549                         break;
550         }
551
552         /* Negative temperature */
553         if (temp < 3) {
554                 if (temp == 2)
555                         temp = -1;
556                 else if (temp == 1)
557                         temp = -2;
558                 else
559                         temp = -3;
560         }
561
562         return temp + 1;
563 }
564
565 /*
566  * Return battery voltage
567  * Or < 0 on failure.
568  */
569 static int twl4030battery_voltage(void)
570 {
571         int volt = read_bci_val(T2_BATTERY_VOLT);
572
573         return (volt * VOLT_STEP_SIZE) / VOLT_PSR_R;
574 }
575
576 /*
577  * Return the battery current
578  * Or < 0 on failure.
579  */
580 static int twl4030battery_current(void)
581 {
582         int ret, curr = read_bci_val(T2_BATTERY_CUR);
583         u8 val;
584
585         ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
586                 REG_BCICTL1);
587         if (ret)
588                 return ret;
589
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;
594 }
595
596 /*
597  * Return the battery backup voltage
598  * Or < 0 on failure.
599  */
600 static int twl4030backupbatt_voltage(void)
601 {
602         int ret, temp;
603         u8 volt;
604         struct twl4030_madc_request req;
605
606         req.channels = (1 << 9);
607         req.method = TWL4030_MADC_SW1;
608         twl4030_madc_conversion(&req);
609         temp = (u16)req.rbuf[9];
610
611         return  (temp * BK_VOLT_STEP_SIZE) / BK_VOLT_PSR_R;
612 }
613
614 /*
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
620  *
621  * Or < 0 on failure.
622  */
623 static int twl4030charger_presence(void)
624 {
625         int ret;
626         u8 hwsts;
627
628         ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
629                 REG_STS_HW_CONDITIONS);
630         if (ret) {
631                 pr_err("BATTERY DRIVER: error reading STS_HW_CONDITIONS \n");
632                 return ret;
633         }
634
635         ret = (hwsts & STS_CHG)? AC_PW_CONN: NO_PW_CONN;
636         ret += (hwsts & STS_VBUS)? USB_PW_CONN: NO_PW_CONN;
637
638         if (ret & USB_PW_CONN)
639                 usb_charger_flag = 1;
640         else
641                 usb_charger_flag = 0;
642
643         return ret;
644
645 }
646
647 /*
648  * Returns the main charge FSM status
649  * Or < 0 on failure.
650  */
651 static int twl4030bci_status(void)
652 {
653         int ret;
654         u8 status;
655
656         ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
657                 &status, REG_BCIMSTATEC);
658         if (ret) {
659                 pr_err("BATTERY DRIVER: error reading BCIMSTATEC \n");
660                 return ret;
661         }
662
663         return (int) (status & BCIMSTAT_MASK);
664 }
665
666 static int read_bci_val(u8 reg)
667 {
668         int ret, temp;
669         u8 val;
670
671         /* reading MSB */
672         ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
673                 reg + 1);
674         if (ret)
675                 return ret;
676
677         temp = ((int)(val & 0x03)) << 8;
678
679         /* reading LSB */
680         ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
681                 reg);
682         if (ret)
683                 return ret;
684
685         return temp | val;
686 }
687
688 /*
689  * Settup the twl4030 BCI module to enable backup
690  * battery charging.
691  */
692 static int twl4030backupbatt_voltage_setup(void)
693 {
694         int ret;
695
696         /* Starting backup batery charge */
697         ret = clear_n_set(TWL4030_MODULE_PM_RECEIVER, 0, BBCHEN,
698                 REG_BB_CFG);
699         if (ret)
700                 return ret;
701
702         return 0;
703 }
704
705 /*
706  * Settup the twl4030 BCI module to measure battery
707  * temperature
708  */
709 static int twl4030battery_temp_setup(void)
710 {
711         int ret;
712
713         /* Enabling thermistor current */
714         ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
715                 REG_BCICTL1);
716         if (ret)
717                 return ret;
718
719         return 0;
720 }
721
722 /*
723  * Sets and clears bits on an given register on a given module
724  */
725 static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg)
726 {
727         int ret;
728         u8 val = 0;
729
730         /* Gets the initial register value */
731         ret = twl4030_i2c_read_u8(mod_no, &val, reg);
732         if (ret)
733                 return ret;
734
735         /* Clearing all those bits to clear */
736         val &= ~(clear);
737
738         /* Setting all those bits to set */
739         val |= set;
740
741         /* Update the register */
742         ret = twl4030_i2c_write_u8(mod_no, val, reg);
743         if (ret)
744                 return ret;
745
746         return 0;
747 }
748
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,
756 };
757
758 static enum power_supply_property twl4030_bk_bci_battery_props[] = {
759         POWER_SUPPLY_PROP_VOLTAGE_NOW,
760 };
761
762 static void
763 twl4030_bk_bci_battery_read_status(struct twl4030_bci_device_info *di)
764 {
765         di->bk_voltage_uV = twl4030backupbatt_voltage();
766 }
767
768 static void twl4030_bk_bci_battery_work(struct work_struct *work)
769 {
770         struct twl4030_bci_device_info *di = container_of(work,
771                 struct twl4030_bci_device_info,
772                 twl4030_bk_bci_monitor_work.work);
773
774         twl4030_bk_bci_battery_read_status(di);
775         schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
776 }
777
778 static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
779 {
780         di->temp_C = twl4030battery_temperature();
781         di->voltage_uV = twl4030battery_voltage();
782         di->current_uA = twl4030battery_current();
783 }
784
785 static void
786 twl4030_bci_battery_update_status(struct twl4030_bci_device_info *di)
787 {
788         twl4030_bci_battery_read_status(di);
789         di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
790
791         if (power_supply_am_i_supplied(&di->bat))
792                 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
793         else
794                 di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
795 }
796
797 static void twl4030_bci_battery_work(struct work_struct *work)
798 {
799         struct twl4030_bci_device_info *di = container_of(work,
800                 struct twl4030_bci_device_info, twl4030_bci_monitor_work.work);
801
802         twl4030_bci_battery_update_status(di);
803         schedule_delayed_work(&di->twl4030_bci_monitor_work, 100);
804 }
805
806
807 #define to_twl4030_bci_device_info(x) container_of((x), \
808                         struct twl4030_bci_device_info, bat);
809
810 static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
811 {
812         struct twl4030_bci_device_info *di = to_twl4030_bci_device_info(psy);
813
814         cancel_delayed_work(&di->twl4030_bci_monitor_work);
815         schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
816 }
817
818 #define to_twl4030_bk_bci_device_info(x) container_of((x), \
819                 struct twl4030_bci_device_info, bk_bat);
820
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)
824 {
825         struct twl4030_bci_device_info *di = to_twl4030_bk_bci_device_info(psy);
826
827         switch (psp) {
828         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
829                 val->intval = di->bk_voltage_uV;
830                 break;
831         default:
832                 return -EINVAL;
833         }
834
835         return 0;
836 }
837
838 static int twl4030_bci_battery_get_property(struct power_supply *psy,
839                                         enum power_supply_property psp,
840                                         union power_supply_propval *val)
841 {
842         struct twl4030_bci_device_info *di = to_twl4030_bci_device_info(psy);
843         int status = 0;
844
845         switch (psp) {
846         case POWER_SUPPLY_PROP_STATUS:
847                 val->intval = di->charge_status;
848                 return 0;
849         default:
850                 break;
851         }
852
853         switch (psp) {
854         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
855                 val->intval = di->voltage_uV;
856                 break;
857         case POWER_SUPPLY_PROP_CURRENT_NOW:
858                 val->intval = di->current_uA;
859                 break;
860         case POWER_SUPPLY_PROP_TEMP:
861                 val->intval = di->temp_C;
862                 break;
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;
869                 else
870                         val->intval = 0;
871                 break;
872         case POWER_SUPPLY_PROP_CAPACITY:
873                 /*
874                  * need to get the correct percentage value per the
875                  * battery characteristics. Approx values for now.
876                  */
877                 if (di->voltage_uV < 2894 || LVL_1) {
878                         val->intval = 5;
879                         LVL_1 = 0;
880                 } else if ((di->voltage_uV < 3451 && di->voltage_uV > 2894)
881                         || LVL_2) {
882                         val->intval = 20;
883                         LVL_2 = 0;
884                 } else if ((di->voltage_uV < 3902 && di->voltage_uV > 3451)
885                         || LVL_3) {
886                         val->intval = 50;
887                         LVL_3 = 0;
888                 } else if ((di->voltage_uV < 3949 && di->voltage_uV > 3902)
889                         || LVL_4) {
890                         val->intval = 75;
891                         LVL_4 = 0;
892                 } else if (di->voltage_uV > 3949)
893                         val->intval = 90;
894                 break;
895         default:
896                 return -EINVAL;
897         }
898         return 0;
899 }
900
901 static char *twl4030_bci_supplied_to[] = {
902         "twl4030_bci_battery",
903 };
904
905 static int twl4030_bci_battery_probe(struct  platform_device *dev)
906 {
907         struct twl4030_bci_device_info *di;
908         int ret;
909         struct twl4030_bci_platform_data *pdata = dev->dev.platform_data;
910
911         therm_tbl = pdata->battery_tmp_tbl;
912
913         di = kzalloc(sizeof(*di), GFP_KERNEL);
914         if (!di)
915                 return -ENOMEM;
916
917         platform_set_drvdata(dev, di);
918
919         di->dev = &dev->dev;
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;
929
930         di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
931
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;
938
939         twl4030charger_ac_en(ENABLE);
940         twl4030charger_usb_en(ENABLE);
941         twl4030battery_hw_level_en(ENABLE);
942         twl4030battery_hw_presence_en(ENABLE);
943
944         /* settings for temperature sensing */
945         ret = twl4030battery_temp_setup();
946         if (ret)
947                 goto temp_setup_fail;
948
949         /* enabling GPCH09 for read back battery voltage */
950         ret = twl4030backupbatt_voltage_setup();
951         if (ret)
952                 goto voltage_setup_fail;
953
954         /* request BCI interruption */
955         ret = request_irq(TWL4030_MODIRQ_BCI, twl4030battery_interrupt,
956                 IRQF_DISABLED, dev->name, NULL);
957         if (ret) {
958                 pr_err("BATTERY DRIVER: (BCI) IRQ%d is not free.\n",
959                         TWL4030_MODIRQ_PWR);
960                 goto batt_irq_fail;
961         }
962
963         /* request Power interruption */
964         ret = request_irq(TWL4030_PWRIRQ_CHG_PRES, twl4030charger_interrupt,
965                 0, dev->name, di);
966
967         if (ret) {
968                 pr_err("BATTERY DRIVER: (POWER) IRQ%d is not free.\n",
969                         TWL4030_MODIRQ_PWR);
970                 goto chg_irq_fail;
971         }
972
973         ret = power_supply_register(&dev->dev, &di->bat);
974         if (ret) {
975                 pr_err("BATTERY DRIVER: failed to register main battery\n");
976                 goto batt_failed;
977         }
978
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);
982
983         ret = power_supply_register(&dev->dev, &di->bk_bat);
984         if (ret) {
985                 pr_err("BATTERY DRIVER: failed to register backup battery\n");
986                 goto bk_batt_failed;
987         }
988
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);
992
993         return 0;
994
995 bk_batt_failed:
996         power_supply_unregister(&di->bat);
997 batt_failed:
998         free_irq(TWL4030_MODIRQ_PWR, di);
999 chg_irq_fail:
1000 prev_setup_err:
1001         free_irq(TWL4030_MODIRQ_BCI, NULL);
1002 batt_irq_fail:
1003 voltage_setup_fail:
1004 temp_setup_fail:
1005         twl4030charger_ac_en(DISABLE);
1006         twl4030charger_usb_en(DISABLE);
1007         twl4030battery_hw_level_en(DISABLE);
1008         twl4030battery_hw_presence_en(DISABLE);
1009         kfree(di);
1010
1011         return ret;
1012 }
1013
1014 static int twl4030_bci_battery_remove(struct  platform_device *dev)
1015 {
1016         struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
1017
1018         twl4030charger_ac_en(DISABLE);
1019         twl4030charger_usb_en(DISABLE);
1020         twl4030battery_hw_level_en(DISABLE);
1021         twl4030battery_hw_presence_en(DISABLE);
1022
1023         free_irq(TWL4030_MODIRQ_BCI, NULL);
1024         free_irq(TWL4030_MODIRQ_PWR, di);
1025
1026         flush_scheduled_work();
1027         power_supply_unregister(&di->bat);
1028         power_supply_unregister(&di->bk_bat);
1029         platform_set_drvdata(dev, NULL);
1030         kfree(di);
1031
1032         return 0;
1033 }
1034
1035 #ifdef CONFIG_PM
1036 static int twl4030_bci_battery_suspend(struct platform_device *dev,
1037         pm_message_t state)
1038 {
1039         struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
1040
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);
1044         return 0;
1045 }
1046
1047 static int twl4030_bci_battery_resume(struct platform_device *dev)
1048 {
1049         struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
1050
1051         schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
1052         schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 50);
1053         return 0;
1054 }
1055 #endif /* CONFIG_PM */
1056
1057 /*
1058  * Battery driver module initializer function
1059  * registers battery driver structure
1060  */
1061 static int __init twl4030_battery_init(void)
1062 {
1063         return platform_driver_register(&twl4030_bci_battery_driver);
1064
1065 }
1066
1067 /*
1068  * Battery driver module exit function
1069  * unregister battery driver structure
1070  */
1071 static void __exit twl4030_battery_exit(void)
1072 {
1073         platform_driver_unregister(&twl4030_bci_battery_driver);
1074 }
1075
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");