18 #include <linux/module.h>
29 #define DA9052_BAT_CUTOFF_VOLT 2800
30 #define DA9052_BAT_TSH 62000
31 #define DA9052_BAT_LOW_CAP 4
32 #define DA9052_AVG_SZ 4
33 #define DA9052_VC_TBL_SZ 68
34 #define DA9052_VC_TBL_REF_SZ 3
36 #define DA9052_ISET_USB_MASK 0x0F
37 #define DA9052_CHG_USB_ILIM_MASK 0x40
38 #define DA9052_CHG_LIM_COLS 16
40 #define DA9052_MEAN(x, y) ((x + y) / 2)
48 {70, 80, 90, 100, 110, 120, 400, 450,
49 500, 550, 600, 650, 700, 900, 1100, 1300},
50 {80, 90, 100, 110, 120, 400, 450, 500,
51 550, 600, 800, 1000, 1200, 1400, 1600, 1800},
54 static const u16 vc_tbl_ref[3] = {10, 25, 40};
56 static u32 const vc_tbl[3][68][2] = {
59 {4082, 100}, {4036, 98},
60 {4020, 96}, {4008, 95},
61 {3997, 93}, {3983, 91},
62 {3964, 90}, {3943, 88},
63 {3926, 87}, {3912, 85},
64 {3900, 84}, {3890, 82},
65 {3881, 80}, {3873, 79},
66 {3865, 77}, {3857, 76},
67 {3848, 74}, {3839, 73},
68 {3829, 71}, {3820, 70},
69 {3811, 68}, {3802, 67},
70 {3794, 65}, {3785, 64},
71 {3778, 62}, {3770, 61},
72 {3763, 59}, {3756, 58},
73 {3750, 56}, {3744, 55},
74 {3738, 53}, {3732, 52},
75 {3727, 50}, {3722, 49},
76 {3717, 47}, {3712, 46},
77 {3708, 44}, {3703, 43},
78 {3700, 41}, {3696, 40},
79 {3693, 38}, {3691, 37},
80 {3688, 35}, {3686, 34},
81 {3683, 32}, {3681, 31},
82 {3678, 29}, {3675, 28},
83 {3672, 26}, {3669, 25},
84 {3665, 23}, {3661, 22},
85 {3656, 21}, {3651, 19},
86 {3645, 18}, {3639, 16},
87 {3631, 15}, {3622, 13},
88 {3611, 12}, {3600, 10},
96 {4102, 100}, {4065, 98},
97 {4048, 96}, {4034, 95},
98 {4021, 93}, {4011, 92},
99 {4001, 90}, {3986, 88},
100 {3968, 87}, {3952, 85},
101 {3938, 84}, {3926, 82},
102 {3916, 81}, {3908, 79},
103 {3900, 77}, {3892, 76},
104 {3883, 74}, {3874, 73},
105 {3864, 71}, {3855, 70},
106 {3846, 68}, {3836, 67},
107 {3827, 65}, {3819, 64},
108 {3810, 62}, {3801, 61},
109 {3793, 59}, {3786, 58},
110 {3778, 56}, {3772, 55},
111 {3765, 53}, {3759, 52},
112 {3754, 50}, {3748, 49},
113 {3743, 47}, {3738, 46},
114 {3733, 44}, {3728, 43},
115 {3724, 41}, {3720, 40},
116 {3716, 38}, {3712, 37},
117 {3709, 35}, {3706, 34},
118 {3703, 33}, {3701, 31},
119 {3698, 30}, {3696, 28},
120 {3693, 27}, {3690, 25},
121 {3687, 24}, {3683, 22},
122 {3680, 21}, {3675, 19},
123 {3671, 18}, {3666, 17},
124 {3660, 15}, {3654, 14},
125 {3647, 12}, {3639, 11},
126 {3630, 9}, {3621, 8},
127 {3613, 6}, {3606, 5},
128 {3597, 4}, {3582, 2},
133 {4114, 100}, {4081, 98},
134 {4065, 96}, {4050, 95},
135 {4036, 93}, {4024, 92},
136 {4013, 90}, {4002, 88},
137 {3990, 87}, {3976, 85},
138 {3962, 84}, {3950, 82},
139 {3939, 81}, {3930, 79},
140 {3921, 77}, {3912, 76},
141 {3902, 74}, {3893, 73},
142 {3883, 71}, {3874, 70},
143 {3865, 68}, {3856, 67},
144 {3847, 65}, {3838, 64},
145 {3829, 62}, {3820, 61},
146 {3812, 59}, {3803, 58},
147 {3795, 56}, {3787, 55},
148 {3780, 53}, {3773, 52},
149 {3767, 50}, {3761, 49},
150 {3756, 47}, {3751, 46},
151 {3746, 44}, {3741, 43},
152 {3736, 41}, {3732, 40},
153 {3728, 38}, {3724, 37},
154 {3720, 35}, {3716, 34},
155 {3713, 33}, {3710, 31},
156 {3707, 30}, {3704, 28},
157 {3701, 27}, {3698, 25},
158 {3695, 24}, {3691, 22},
159 {3686, 21}, {3681, 19},
160 {3676, 18}, {3671, 17},
161 {3666, 15}, {3661, 14},
162 {3655, 12}, {3648, 11},
163 {3640, 9}, {3632, 8},
164 {3622, 6}, {3616, 5},
165 {3611, 4}, {3604, 2},
179 static inline int volt_reg_to_mV(
int value)
181 return ((value * 1000) / 512) + 2500;
184 static inline int ichg_reg_to_mA(
int value)
186 return (value * 3900) / 1000;
206 static int da9052_read_chg_current(
struct da9052_battery *bat,
int *current_mA)
248 dc = dcinsel && dcindet;
249 vbus = vbussel && vbusdet;
259 ret = da9052_read_chg_current(bat, &chg_current);
262 ret = da9052_read_chgend_current(bat, &chg_end_current);
266 if (chg_current >= chg_end_current)
276 }
else if (dcindet || vbusdet) {
289 static int da9052_bat_read_volt(
struct da9052_battery *bat,
int *volt_mV)
297 *volt_mV = volt_reg_to_mV(volt);
318 static int da9052_bat_interpolate(
int vbat_lower,
int vbat_upper,
319 int level_lower,
int level_upper,
324 tmp = ((level_upper - level_lower) * 1000) / (vbat_upper - vbat_lower);
325 tmp = level_lower + (((bat_voltage - vbat_lower) * tmp) / 1000);
330 static unsigned char da9052_determine_vc_tbl_index(
unsigned char adc_temp)
334 if (adc_temp <= vc_tbl_ref[0])
341 if ((adc_temp > vc_tbl_ref[i]) &&
342 (adc_temp <=
DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1])))
344 if ((adc_temp >
DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1]))
345 && (adc_temp <= vc_tbl_ref[i]))
370 ret = da9052_bat_read_volt(bat, &bat_voltage);
378 i = da9052_determine_vc_tbl_index(adc_temp);
380 if (bat_voltage >= vc_tbl[i][0][0]) {
391 if ((bat_voltage <= vc_tbl[i][j][0]) &&
392 (bat_voltage >= vc_tbl[
i][j + 1][0])) {
393 vbat_upper = vc_tbl[
i][
j][0];
394 vbat_lower = vc_tbl[
i][j + 1][0];
395 level_upper = vc_tbl[
i][
j][1];
396 level_lower = vc_tbl[
i][j + 1][1];
404 *capacity = da9052_bat_interpolate(vbat_lower, vbat_upper, level_lower,
405 level_upper, bat_voltage);
410 static int da9052_bat_check_health(
struct da9052_battery *bat,
int *health)
416 ret = da9052_bat_check_presence(bat, &bat_illegal);
426 ret = da9052_bat_read_capacity(bat, &capacity);
444 irq -= bat->
da9052->irq_base;
449 da9052_bat_check_status(bat,
NULL);
460 unsigned long events,
void *data)
464 int *current_mA =
data;
481 if (*current_mA < da9052_chg_current_lim[row][0] ||
486 if (*current_mA <= da9052_chg_current_lim[row][col])
503 ret = da9052_bat_check_presence(bat, &illegal);
512 ret = da9052_bat_check_status(bat, &val->
intval);
519 ret = da9052_bat_check_presence(bat, &val->
intval);
522 ret = da9052_bat_check_health(bat, &val->
intval);
528 ret = da9052_bat_read_volt(bat, &val->
intval);
531 ret = da9052_read_chg_current(bat, &val->
intval);
534 ret = da9052_bat_read_capacity(bat, &val->
intval);
563 .name =
"da9052-bat",
565 .properties = da9052_bat_props,
566 .num_properties =
ARRAY_SIZE(da9052_bat_props),
567 .get_property = da9052_bat_get_property,
570 static const char *
const da9052_bat_irqs[] = {
592 bat->
psy = template_battery;
596 bat->
nb.notifier_call = da9052_USB_current_notifier;
598 pdata = bat->
da9052->dev->platform_data;
602 bat->
psy.use_for_apm = 1;
604 for (i = 0; i <
ARRAY_SIZE(da9052_bat_irqs); i++) {
607 NULL, da9052_bat_irq,
609 da9052_bat_irqs[i], bat);
612 "DA9052 failed to request %s IRQ %d: %d\n",
613 da9052_bat_irqs[i], irq, ret);
622 platform_set_drvdata(pdev, bat);
639 for (i = 0; i <
ARRAY_SIZE(da9052_bat_irqs); i++) {
650 .probe = da9052_bat_probe,
653 .name =
"da9052-bat",