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