diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/power | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/power')
58 files changed, 1151 insertions, 23277 deletions
diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c deleted file mode 100644 index 8bc80b05c63..00000000000 --- a/drivers/power/88pm860x_battery.c +++ /dev/null | |||
@@ -1,1041 +0,0 @@ | |||
1 | /* | ||
2 | * Battery driver for Marvell 88PM860x PMIC | ||
3 | * | ||
4 | * Copyright (c) 2012 Marvell International Ltd. | ||
5 | * Author: Jett Zhou <jtzhou@marvell.com> | ||
6 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/mutex.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/power_supply.h> | ||
20 | #include <linux/mfd/88pm860x.h> | ||
21 | #include <linux/delay.h> | ||
22 | |||
23 | /* bit definitions of Status Query Interface 2 */ | ||
24 | #define STATUS2_CHG (1 << 2) | ||
25 | #define STATUS2_BAT (1 << 3) | ||
26 | #define STATUS2_VBUS (1 << 4) | ||
27 | |||
28 | /* bit definitions of Measurement Enable 1 Register */ | ||
29 | #define MEAS1_TINT (1 << 3) | ||
30 | #define MEAS1_GP1 (1 << 5) | ||
31 | |||
32 | /* bit definitions of Measurement Enable 3 Register */ | ||
33 | #define MEAS3_IBAT (1 << 0) | ||
34 | #define MEAS3_BAT_DET (1 << 1) | ||
35 | #define MEAS3_CC (1 << 2) | ||
36 | |||
37 | /* bit definitions of Measurement Off Time Register */ | ||
38 | #define MEAS_OFF_SLEEP_EN (1 << 1) | ||
39 | |||
40 | /* bit definitions of GPADC Bias Current 2 Register */ | ||
41 | #define GPBIAS2_GPADC1_SET (2 << 4) | ||
42 | /* GPADC1 Bias Current value in uA unit */ | ||
43 | #define GPBIAS2_GPADC1_UA ((GPBIAS2_GPADC1_SET >> 4) * 5 + 1) | ||
44 | |||
45 | /* bit definitions of GPADC Misc 1 Register */ | ||
46 | #define GPMISC1_GPADC_EN (1 << 0) | ||
47 | |||
48 | /* bit definitions of Charger Control 6 Register */ | ||
49 | #define CC6_BAT_DET_GPADC1 1 | ||
50 | |||
51 | /* bit definitions of Coulomb Counter Reading Register */ | ||
52 | #define CCNT_AVG_SEL (4 << 3) | ||
53 | |||
54 | /* bit definitions of RTC miscellaneous Register1 */ | ||
55 | #define RTC_SOC_5LSB (0x1F << 3) | ||
56 | |||
57 | /* bit definitions of RTC Register1 */ | ||
58 | #define RTC_SOC_3MSB (0x7) | ||
59 | |||
60 | /* bit definitions of Power up Log register */ | ||
61 | #define BAT_WU_LOG (1<<6) | ||
62 | |||
63 | /* coulomb counter index */ | ||
64 | #define CCNT_POS1 0 | ||
65 | #define CCNT_POS2 1 | ||
66 | #define CCNT_NEG1 2 | ||
67 | #define CCNT_NEG2 3 | ||
68 | #define CCNT_SPOS 4 | ||
69 | #define CCNT_SNEG 5 | ||
70 | |||
71 | /* OCV -- Open Circuit Voltage */ | ||
72 | #define OCV_MODE_ACTIVE 0 | ||
73 | #define OCV_MODE_SLEEP 1 | ||
74 | |||
75 | /* Vbat range of CC for measuring Rbat */ | ||
76 | #define LOW_BAT_THRESHOLD 3600 | ||
77 | #define VBATT_RESISTOR_MIN 3800 | ||
78 | #define VBATT_RESISTOR_MAX 4100 | ||
79 | |||
80 | /* TBAT for batt, TINT for chip itself */ | ||
81 | #define PM860X_TEMP_TINT (0) | ||
82 | #define PM860X_TEMP_TBAT (1) | ||
83 | |||
84 | /* | ||
85 | * Battery temperature based on NTC resistor, defined | ||
86 | * corresponding resistor value -- Ohm / C degeree. | ||
87 | */ | ||
88 | #define TBAT_NEG_25D 127773 /* -25 */ | ||
89 | #define TBAT_NEG_10D 54564 /* -10 */ | ||
90 | #define TBAT_0D 32330 /* 0 */ | ||
91 | #define TBAT_10D 19785 /* 10 */ | ||
92 | #define TBAT_20D 12468 /* 20 */ | ||
93 | #define TBAT_30D 8072 /* 30 */ | ||
94 | #define TBAT_40D 5356 /* 40 */ | ||
95 | |||
96 | struct pm860x_battery_info { | ||
97 | struct pm860x_chip *chip; | ||
98 | struct i2c_client *i2c; | ||
99 | struct device *dev; | ||
100 | |||
101 | struct power_supply battery; | ||
102 | struct mutex lock; | ||
103 | int status; | ||
104 | int irq_cc; | ||
105 | int irq_batt; | ||
106 | int max_capacity; | ||
107 | int resistor; /* Battery Internal Resistor */ | ||
108 | int last_capacity; | ||
109 | int start_soc; | ||
110 | unsigned present:1; | ||
111 | unsigned temp_type:1; /* TINT or TBAT */ | ||
112 | }; | ||
113 | |||
114 | struct ccnt { | ||
115 | unsigned long long int pos; | ||
116 | unsigned long long int neg; | ||
117 | unsigned int spos; | ||
118 | unsigned int sneg; | ||
119 | |||
120 | int total_chg; /* mAh(3.6C) */ | ||
121 | int total_dischg; /* mAh(3.6C) */ | ||
122 | }; | ||
123 | |||
124 | /* | ||
125 | * State of Charge. | ||
126 | * The first number is mAh(=3.6C), and the second number is percent point. | ||
127 | */ | ||
128 | static int array_soc[][2] = { | ||
129 | {4170, 100}, {4154, 99}, {4136, 98}, {4122, 97}, {4107, 96}, | ||
130 | {4102, 95}, {4088, 94}, {4081, 93}, {4070, 92}, {4060, 91}, | ||
131 | {4053, 90}, {4044, 89}, {4035, 88}, {4028, 87}, {4019, 86}, | ||
132 | {4013, 85}, {4006, 84}, {3995, 83}, {3987, 82}, {3982, 81}, | ||
133 | {3976, 80}, {3968, 79}, {3962, 78}, {3954, 77}, {3946, 76}, | ||
134 | {3941, 75}, {3934, 74}, {3929, 73}, {3922, 72}, {3916, 71}, | ||
135 | {3910, 70}, {3904, 69}, {3898, 68}, {3892, 67}, {3887, 66}, | ||
136 | {3880, 65}, {3874, 64}, {3868, 63}, {3862, 62}, {3854, 61}, | ||
137 | {3849, 60}, {3843, 59}, {3840, 58}, {3833, 57}, {3829, 56}, | ||
138 | {3824, 55}, {3818, 54}, {3815, 53}, {3810, 52}, {3808, 51}, | ||
139 | {3804, 50}, {3801, 49}, {3798, 48}, {3796, 47}, {3792, 46}, | ||
140 | {3789, 45}, {3785, 44}, {3784, 43}, {3782, 42}, {3780, 41}, | ||
141 | {3777, 40}, {3776, 39}, {3774, 38}, {3772, 37}, {3771, 36}, | ||
142 | {3769, 35}, {3768, 34}, {3764, 33}, {3763, 32}, {3760, 31}, | ||
143 | {3760, 30}, {3754, 29}, {3750, 28}, {3749, 27}, {3744, 26}, | ||
144 | {3740, 25}, {3734, 24}, {3732, 23}, {3728, 22}, {3726, 21}, | ||
145 | {3720, 20}, {3716, 19}, {3709, 18}, {3703, 17}, {3698, 16}, | ||
146 | {3692, 15}, {3683, 14}, {3675, 13}, {3670, 12}, {3665, 11}, | ||
147 | {3661, 10}, {3649, 9}, {3637, 8}, {3622, 7}, {3609, 6}, | ||
148 | {3580, 5}, {3558, 4}, {3540, 3}, {3510, 2}, {3429, 1}, | ||
149 | }; | ||
150 | |||
151 | static struct ccnt ccnt_data; | ||
152 | |||
153 | /* | ||
154 | * register 1 bit[7:0] -- bit[11:4] of measured value of voltage | ||
155 | * register 0 bit[3:0] -- bit[3:0] of measured value of voltage | ||
156 | */ | ||
157 | static int measure_12bit_voltage(struct pm860x_battery_info *info, | ||
158 | int offset, int *data) | ||
159 | { | ||
160 | unsigned char buf[2]; | ||
161 | int ret; | ||
162 | |||
163 | ret = pm860x_bulk_read(info->i2c, offset, 2, buf); | ||
164 | if (ret < 0) | ||
165 | return ret; | ||
166 | |||
167 | *data = ((buf[0] & 0xff) << 4) | (buf[1] & 0x0f); | ||
168 | /* V_MEAS(mV) = data * 1.8 * 1000 / (2^12) */ | ||
169 | *data = ((*data & 0xfff) * 9 * 25) >> 9; | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int measure_vbatt(struct pm860x_battery_info *info, int state, | ||
174 | int *data) | ||
175 | { | ||
176 | unsigned char buf[5]; | ||
177 | int ret; | ||
178 | |||
179 | switch (state) { | ||
180 | case OCV_MODE_ACTIVE: | ||
181 | ret = measure_12bit_voltage(info, PM8607_VBAT_MEAS1, data); | ||
182 | if (ret) | ||
183 | return ret; | ||
184 | /* V_BATT_MEAS(mV) = value * 3 * 1.8 * 1000 / (2^12) */ | ||
185 | *data *= 3; | ||
186 | break; | ||
187 | case OCV_MODE_SLEEP: | ||
188 | /* | ||
189 | * voltage value of VBATT in sleep mode is saved in different | ||
190 | * registers. | ||
191 | * bit[11:10] -- bit[7:6] of LDO9(0x18) | ||
192 | * bit[9:8] -- bit[7:6] of LDO8(0x17) | ||
193 | * bit[7:6] -- bit[7:6] of LDO7(0x16) | ||
194 | * bit[5:4] -- bit[7:6] of LDO6(0x15) | ||
195 | * bit[3:0] -- bit[7:4] of LDO5(0x14) | ||
196 | */ | ||
197 | ret = pm860x_bulk_read(info->i2c, PM8607_LDO5, 5, buf); | ||
198 | if (ret < 0) | ||
199 | return ret; | ||
200 | ret = ((buf[4] >> 6) << 10) | ((buf[3] >> 6) << 8) | ||
201 | | ((buf[2] >> 6) << 6) | ((buf[1] >> 6) << 4) | ||
202 | | (buf[0] >> 4); | ||
203 | /* V_BATT_MEAS(mV) = data * 3 * 1.8 * 1000 / (2^12) */ | ||
204 | *data = ((*data & 0xff) * 27 * 25) >> 9; | ||
205 | break; | ||
206 | default: | ||
207 | return -EINVAL; | ||
208 | } | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * Return value is signed data. | ||
214 | * Negative value means discharging, and positive value means charging. | ||
215 | */ | ||
216 | static int measure_current(struct pm860x_battery_info *info, int *data) | ||
217 | { | ||
218 | unsigned char buf[2]; | ||
219 | short s; | ||
220 | int ret; | ||
221 | |||
222 | ret = pm860x_bulk_read(info->i2c, PM8607_IBAT_MEAS1, 2, buf); | ||
223 | if (ret < 0) | ||
224 | return ret; | ||
225 | |||
226 | s = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff); | ||
227 | /* current(mA) = value * 0.125 */ | ||
228 | *data = s >> 3; | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int set_charger_current(struct pm860x_battery_info *info, int data, | ||
233 | int *old) | ||
234 | { | ||
235 | int ret; | ||
236 | |||
237 | if (data < 50 || data > 1600 || !old) | ||
238 | return -EINVAL; | ||
239 | |||
240 | data = ((data - 50) / 50) & 0x1f; | ||
241 | *old = pm860x_reg_read(info->i2c, PM8607_CHG_CTRL2); | ||
242 | *old = (*old & 0x1f) * 50 + 50; | ||
243 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL2, 0x1f, data); | ||
244 | if (ret < 0) | ||
245 | return ret; | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static int read_ccnt(struct pm860x_battery_info *info, int offset, | ||
250 | int *ccnt) | ||
251 | { | ||
252 | unsigned char buf[2]; | ||
253 | int ret; | ||
254 | |||
255 | ret = pm860x_set_bits(info->i2c, PM8607_CCNT, 7, offset & 7); | ||
256 | if (ret < 0) | ||
257 | goto out; | ||
258 | ret = pm860x_bulk_read(info->i2c, PM8607_CCNT_MEAS1, 2, buf); | ||
259 | if (ret < 0) | ||
260 | goto out; | ||
261 | *ccnt = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff); | ||
262 | return 0; | ||
263 | out: | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | static int calc_ccnt(struct pm860x_battery_info *info, struct ccnt *ccnt) | ||
268 | { | ||
269 | unsigned int sum; | ||
270 | int ret; | ||
271 | int data; | ||
272 | |||
273 | ret = read_ccnt(info, CCNT_POS1, &data); | ||
274 | if (ret) | ||
275 | goto out; | ||
276 | sum = data & 0xffff; | ||
277 | ret = read_ccnt(info, CCNT_POS2, &data); | ||
278 | if (ret) | ||
279 | goto out; | ||
280 | sum |= (data & 0xffff) << 16; | ||
281 | ccnt->pos += sum; | ||
282 | |||
283 | ret = read_ccnt(info, CCNT_NEG1, &data); | ||
284 | if (ret) | ||
285 | goto out; | ||
286 | sum = data & 0xffff; | ||
287 | ret = read_ccnt(info, CCNT_NEG2, &data); | ||
288 | if (ret) | ||
289 | goto out; | ||
290 | sum |= (data & 0xffff) << 16; | ||
291 | sum = ~sum + 1; /* since it's negative */ | ||
292 | ccnt->neg += sum; | ||
293 | |||
294 | ret = read_ccnt(info, CCNT_SPOS, &data); | ||
295 | if (ret) | ||
296 | goto out; | ||
297 | ccnt->spos += data; | ||
298 | ret = read_ccnt(info, CCNT_SNEG, &data); | ||
299 | if (ret) | ||
300 | goto out; | ||
301 | |||
302 | /* | ||
303 | * charge(mAh) = count * 1.6984 * 1e(-8) | ||
304 | * = count * 16984 * 1.024 * 1.024 * 1.024 / (2 ^ 40) | ||
305 | * = count * 18236 / (2 ^ 40) | ||
306 | */ | ||
307 | ccnt->total_chg = (int) ((ccnt->pos * 18236) >> 40); | ||
308 | ccnt->total_dischg = (int) ((ccnt->neg * 18236) >> 40); | ||
309 | return 0; | ||
310 | out: | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static int clear_ccnt(struct pm860x_battery_info *info, struct ccnt *ccnt) | ||
315 | { | ||
316 | int data; | ||
317 | |||
318 | memset(ccnt, 0, sizeof(*ccnt)); | ||
319 | /* read to clear ccnt */ | ||
320 | read_ccnt(info, CCNT_POS1, &data); | ||
321 | read_ccnt(info, CCNT_POS2, &data); | ||
322 | read_ccnt(info, CCNT_NEG1, &data); | ||
323 | read_ccnt(info, CCNT_NEG2, &data); | ||
324 | read_ccnt(info, CCNT_SPOS, &data); | ||
325 | read_ccnt(info, CCNT_SNEG, &data); | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | /* Calculate Open Circuit Voltage */ | ||
330 | static int calc_ocv(struct pm860x_battery_info *info, int *ocv) | ||
331 | { | ||
332 | int ret; | ||
333 | int i; | ||
334 | int data; | ||
335 | int vbatt_avg; | ||
336 | int vbatt_sum; | ||
337 | int ibatt_avg; | ||
338 | int ibatt_sum; | ||
339 | |||
340 | if (!ocv) | ||
341 | return -EINVAL; | ||
342 | |||
343 | for (i = 0, ibatt_sum = 0, vbatt_sum = 0; i < 10; i++) { | ||
344 | ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); | ||
345 | if (ret) | ||
346 | goto out; | ||
347 | vbatt_sum += data; | ||
348 | ret = measure_current(info, &data); | ||
349 | if (ret) | ||
350 | goto out; | ||
351 | ibatt_sum += data; | ||
352 | } | ||
353 | vbatt_avg = vbatt_sum / 10; | ||
354 | ibatt_avg = ibatt_sum / 10; | ||
355 | |||
356 | mutex_lock(&info->lock); | ||
357 | if (info->present) | ||
358 | *ocv = vbatt_avg - ibatt_avg * info->resistor / 1000; | ||
359 | else | ||
360 | *ocv = vbatt_avg; | ||
361 | mutex_unlock(&info->lock); | ||
362 | dev_dbg(info->dev, "VBAT average:%d, OCV:%d\n", vbatt_avg, *ocv); | ||
363 | return 0; | ||
364 | out: | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | /* Calculate State of Charge (percent points) */ | ||
369 | static int calc_soc(struct pm860x_battery_info *info, int state, int *soc) | ||
370 | { | ||
371 | int i; | ||
372 | int ocv; | ||
373 | int count; | ||
374 | int ret = -EINVAL; | ||
375 | |||
376 | if (!soc) | ||
377 | return -EINVAL; | ||
378 | |||
379 | switch (state) { | ||
380 | case OCV_MODE_ACTIVE: | ||
381 | ret = calc_ocv(info, &ocv); | ||
382 | break; | ||
383 | case OCV_MODE_SLEEP: | ||
384 | ret = measure_vbatt(info, OCV_MODE_SLEEP, &ocv); | ||
385 | break; | ||
386 | } | ||
387 | if (ret) | ||
388 | return ret; | ||
389 | |||
390 | count = ARRAY_SIZE(array_soc); | ||
391 | if (ocv < array_soc[count - 1][0]) { | ||
392 | *soc = 0; | ||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | for (i = 0; i < count; i++) { | ||
397 | if (ocv >= array_soc[i][0]) { | ||
398 | *soc = array_soc[i][1]; | ||
399 | break; | ||
400 | } | ||
401 | } | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static irqreturn_t pm860x_coulomb_handler(int irq, void *data) | ||
406 | { | ||
407 | struct pm860x_battery_info *info = data; | ||
408 | |||
409 | calc_ccnt(info, &ccnt_data); | ||
410 | return IRQ_HANDLED; | ||
411 | } | ||
412 | |||
413 | static irqreturn_t pm860x_batt_handler(int irq, void *data) | ||
414 | { | ||
415 | struct pm860x_battery_info *info = data; | ||
416 | int ret; | ||
417 | |||
418 | mutex_lock(&info->lock); | ||
419 | ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); | ||
420 | if (ret & STATUS2_BAT) { | ||
421 | info->present = 1; | ||
422 | info->temp_type = PM860X_TEMP_TBAT; | ||
423 | } else { | ||
424 | info->present = 0; | ||
425 | info->temp_type = PM860X_TEMP_TINT; | ||
426 | } | ||
427 | mutex_unlock(&info->lock); | ||
428 | /* clear ccnt since battery is attached or dettached */ | ||
429 | clear_ccnt(info, &ccnt_data); | ||
430 | return IRQ_HANDLED; | ||
431 | } | ||
432 | |||
433 | static void pm860x_init_battery(struct pm860x_battery_info *info) | ||
434 | { | ||
435 | unsigned char buf[2]; | ||
436 | int ret; | ||
437 | int data; | ||
438 | int bat_remove; | ||
439 | int soc; | ||
440 | |||
441 | /* measure enable on GPADC1 */ | ||
442 | data = MEAS1_GP1; | ||
443 | if (info->temp_type == PM860X_TEMP_TINT) | ||
444 | data |= MEAS1_TINT; | ||
445 | ret = pm860x_set_bits(info->i2c, PM8607_MEAS_EN1, data, data); | ||
446 | if (ret) | ||
447 | goto out; | ||
448 | |||
449 | /* measure enable on IBAT, BAT_DET, CC. IBAT is depend on CC. */ | ||
450 | data = MEAS3_IBAT | MEAS3_BAT_DET | MEAS3_CC; | ||
451 | ret = pm860x_set_bits(info->i2c, PM8607_MEAS_EN3, data, data); | ||
452 | if (ret) | ||
453 | goto out; | ||
454 | |||
455 | /* measure disable CC in sleep time */ | ||
456 | ret = pm860x_reg_write(info->i2c, PM8607_MEAS_OFF_TIME1, 0x82); | ||
457 | if (ret) | ||
458 | goto out; | ||
459 | ret = pm860x_reg_write(info->i2c, PM8607_MEAS_OFF_TIME2, 0x6c); | ||
460 | if (ret) | ||
461 | goto out; | ||
462 | |||
463 | /* enable GPADC */ | ||
464 | ret = pm860x_set_bits(info->i2c, PM8607_GPADC_MISC1, | ||
465 | GPMISC1_GPADC_EN, GPMISC1_GPADC_EN); | ||
466 | if (ret < 0) | ||
467 | goto out; | ||
468 | |||
469 | /* detect battery via GPADC1 */ | ||
470 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL6, | ||
471 | CC6_BAT_DET_GPADC1, CC6_BAT_DET_GPADC1); | ||
472 | if (ret < 0) | ||
473 | goto out; | ||
474 | |||
475 | ret = pm860x_set_bits(info->i2c, PM8607_CCNT, 7 << 3, | ||
476 | CCNT_AVG_SEL); | ||
477 | if (ret < 0) | ||
478 | goto out; | ||
479 | |||
480 | /* set GPADC1 bias */ | ||
481 | ret = pm860x_set_bits(info->i2c, PM8607_GP_BIAS2, 0xF << 4, | ||
482 | GPBIAS2_GPADC1_SET); | ||
483 | if (ret < 0) | ||
484 | goto out; | ||
485 | |||
486 | /* check whether battery present) */ | ||
487 | mutex_lock(&info->lock); | ||
488 | ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); | ||
489 | if (ret < 0) { | ||
490 | mutex_unlock(&info->lock); | ||
491 | goto out; | ||
492 | } | ||
493 | if (ret & STATUS2_BAT) { | ||
494 | info->present = 1; | ||
495 | info->temp_type = PM860X_TEMP_TBAT; | ||
496 | } else { | ||
497 | info->present = 0; | ||
498 | info->temp_type = PM860X_TEMP_TINT; | ||
499 | } | ||
500 | mutex_unlock(&info->lock); | ||
501 | |||
502 | calc_soc(info, OCV_MODE_ACTIVE, &soc); | ||
503 | |||
504 | data = pm860x_reg_read(info->i2c, PM8607_POWER_UP_LOG); | ||
505 | bat_remove = data & BAT_WU_LOG; | ||
506 | |||
507 | dev_dbg(info->dev, "battery wake up? %s\n", | ||
508 | bat_remove != 0 ? "yes" : "no"); | ||
509 | |||
510 | /* restore SOC from RTC domain register */ | ||
511 | if (bat_remove == 0) { | ||
512 | buf[0] = pm860x_reg_read(info->i2c, PM8607_RTC_MISC2); | ||
513 | buf[1] = pm860x_reg_read(info->i2c, PM8607_RTC1); | ||
514 | data = ((buf[1] & 0x3) << 5) | ((buf[0] >> 3) & 0x1F); | ||
515 | if (data > soc + 15) | ||
516 | info->start_soc = soc; | ||
517 | else if (data < soc - 15) | ||
518 | info->start_soc = soc; | ||
519 | else | ||
520 | info->start_soc = data; | ||
521 | dev_dbg(info->dev, "soc_rtc %d, soc_ocv :%d\n", data, soc); | ||
522 | } else { | ||
523 | pm860x_set_bits(info->i2c, PM8607_POWER_UP_LOG, | ||
524 | BAT_WU_LOG, BAT_WU_LOG); | ||
525 | info->start_soc = soc; | ||
526 | } | ||
527 | info->last_capacity = info->start_soc; | ||
528 | dev_dbg(info->dev, "init soc : %d\n", info->last_capacity); | ||
529 | out: | ||
530 | return; | ||
531 | } | ||
532 | |||
533 | static void set_temp_threshold(struct pm860x_battery_info *info, | ||
534 | int min, int max) | ||
535 | { | ||
536 | int data; | ||
537 | |||
538 | /* (tmp << 8) / 1800 */ | ||
539 | if (min <= 0) | ||
540 | data = 0; | ||
541 | else | ||
542 | data = (min << 8) / 1800; | ||
543 | pm860x_reg_write(info->i2c, PM8607_GPADC1_HIGHTH, data); | ||
544 | dev_dbg(info->dev, "TEMP_HIGHTH : min: %d, 0x%x\n", min, data); | ||
545 | |||
546 | if (max <= 0) | ||
547 | data = 0xff; | ||
548 | else | ||
549 | data = (max << 8) / 1800; | ||
550 | pm860x_reg_write(info->i2c, PM8607_GPADC1_LOWTH, data); | ||
551 | dev_dbg(info->dev, "TEMP_LOWTH:max : %d, 0x%x\n", max, data); | ||
552 | } | ||
553 | |||
554 | static int measure_temp(struct pm860x_battery_info *info, int *data) | ||
555 | { | ||
556 | int ret; | ||
557 | int temp; | ||
558 | int min; | ||
559 | int max; | ||
560 | |||
561 | if (info->temp_type == PM860X_TEMP_TINT) { | ||
562 | ret = measure_12bit_voltage(info, PM8607_TINT_MEAS1, data); | ||
563 | if (ret) | ||
564 | return ret; | ||
565 | *data = (*data - 884) * 1000 / 3611; | ||
566 | } else { | ||
567 | ret = measure_12bit_voltage(info, PM8607_GPADC1_MEAS1, data); | ||
568 | if (ret) | ||
569 | return ret; | ||
570 | /* meausered Vtbat(mV) / Ibias_current(11uA)*/ | ||
571 | *data = (*data * 1000) / GPBIAS2_GPADC1_UA; | ||
572 | |||
573 | if (*data > TBAT_NEG_25D) { | ||
574 | temp = -30; /* over cold , suppose -30 roughly */ | ||
575 | max = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000; | ||
576 | set_temp_threshold(info, 0, max); | ||
577 | } else if (*data > TBAT_NEG_10D) { | ||
578 | temp = -15; /* -15 degree, code */ | ||
579 | max = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000; | ||
580 | set_temp_threshold(info, 0, max); | ||
581 | } else if (*data > TBAT_0D) { | ||
582 | temp = -5; /* -5 degree */ | ||
583 | min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000; | ||
584 | max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000; | ||
585 | set_temp_threshold(info, min, max); | ||
586 | } else if (*data > TBAT_10D) { | ||
587 | temp = 5; /* in range of (0, 10) */ | ||
588 | min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000; | ||
589 | max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000; | ||
590 | set_temp_threshold(info, min, max); | ||
591 | } else if (*data > TBAT_20D) { | ||
592 | temp = 15; /* in range of (10, 20) */ | ||
593 | min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000; | ||
594 | max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000; | ||
595 | set_temp_threshold(info, min, max); | ||
596 | } else if (*data > TBAT_30D) { | ||
597 | temp = 25; /* in range of (20, 30) */ | ||
598 | min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000; | ||
599 | max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000; | ||
600 | set_temp_threshold(info, min, max); | ||
601 | } else if (*data > TBAT_40D) { | ||
602 | temp = 35; /* in range of (30, 40) */ | ||
603 | min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000; | ||
604 | max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000; | ||
605 | set_temp_threshold(info, min, max); | ||
606 | } else { | ||
607 | min = TBAT_40D * GPBIAS2_GPADC1_UA / 1000; | ||
608 | set_temp_threshold(info, min, 0); | ||
609 | temp = 45; /* over heat ,suppose 45 roughly */ | ||
610 | } | ||
611 | |||
612 | dev_dbg(info->dev, "temp_C:%d C,temp_mv:%d mv\n", temp, *data); | ||
613 | *data = temp; | ||
614 | } | ||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int calc_resistor(struct pm860x_battery_info *info) | ||
619 | { | ||
620 | int vbatt_sum1; | ||
621 | int vbatt_sum2; | ||
622 | int chg_current; | ||
623 | int ibatt_sum1; | ||
624 | int ibatt_sum2; | ||
625 | int data; | ||
626 | int ret; | ||
627 | int i; | ||
628 | |||
629 | ret = measure_current(info, &data); | ||
630 | /* make sure that charging is launched by data > 0 */ | ||
631 | if (ret || data < 0) | ||
632 | goto out; | ||
633 | |||
634 | ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); | ||
635 | if (ret) | ||
636 | goto out; | ||
637 | /* calculate resistor only in CC charge mode */ | ||
638 | if (data < VBATT_RESISTOR_MIN || data > VBATT_RESISTOR_MAX) | ||
639 | goto out; | ||
640 | |||
641 | /* current is saved */ | ||
642 | if (set_charger_current(info, 500, &chg_current)) | ||
643 | goto out; | ||
644 | |||
645 | /* | ||
646 | * set charge current as 500mA, wait about 500ms till charging | ||
647 | * process is launched and stable with the newer charging current. | ||
648 | */ | ||
649 | msleep(500); | ||
650 | |||
651 | for (i = 0, vbatt_sum1 = 0, ibatt_sum1 = 0; i < 10; i++) { | ||
652 | ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); | ||
653 | if (ret) | ||
654 | goto out_meas; | ||
655 | vbatt_sum1 += data; | ||
656 | ret = measure_current(info, &data); | ||
657 | if (ret) | ||
658 | goto out_meas; | ||
659 | |||
660 | if (data < 0) | ||
661 | ibatt_sum1 = ibatt_sum1 - data; /* discharging */ | ||
662 | else | ||
663 | ibatt_sum1 = ibatt_sum1 + data; /* charging */ | ||
664 | } | ||
665 | |||
666 | if (set_charger_current(info, 100, &ret)) | ||
667 | goto out_meas; | ||
668 | /* | ||
669 | * set charge current as 100mA, wait about 500ms till charging | ||
670 | * process is launched and stable with the newer charging current. | ||
671 | */ | ||
672 | msleep(500); | ||
673 | |||
674 | for (i = 0, vbatt_sum2 = 0, ibatt_sum2 = 0; i < 10; i++) { | ||
675 | ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); | ||
676 | if (ret) | ||
677 | goto out_meas; | ||
678 | vbatt_sum2 += data; | ||
679 | ret = measure_current(info, &data); | ||
680 | if (ret) | ||
681 | goto out_meas; | ||
682 | |||
683 | if (data < 0) | ||
684 | ibatt_sum2 = ibatt_sum2 - data; /* discharging */ | ||
685 | else | ||
686 | ibatt_sum2 = ibatt_sum2 + data; /* charging */ | ||
687 | } | ||
688 | |||
689 | /* restore current setting */ | ||
690 | if (set_charger_current(info, chg_current, &ret)) | ||
691 | goto out_meas; | ||
692 | |||
693 | if ((vbatt_sum1 > vbatt_sum2) && (ibatt_sum1 > ibatt_sum2) && | ||
694 | (ibatt_sum2 > 0)) { | ||
695 | /* calculate resistor in discharging case */ | ||
696 | data = 1000 * (vbatt_sum1 - vbatt_sum2) | ||
697 | / (ibatt_sum1 - ibatt_sum2); | ||
698 | if ((data - info->resistor > 0) && | ||
699 | (data - info->resistor < info->resistor)) | ||
700 | info->resistor = data; | ||
701 | if ((info->resistor - data > 0) && | ||
702 | (info->resistor - data < data)) | ||
703 | info->resistor = data; | ||
704 | } | ||
705 | return 0; | ||
706 | |||
707 | out_meas: | ||
708 | set_charger_current(info, chg_current, &ret); | ||
709 | out: | ||
710 | return -EINVAL; | ||
711 | } | ||
712 | |||
713 | static int calc_capacity(struct pm860x_battery_info *info, int *cap) | ||
714 | { | ||
715 | int ret; | ||
716 | int data; | ||
717 | int ibat; | ||
718 | int cap_ocv = 0; | ||
719 | int cap_cc = 0; | ||
720 | |||
721 | ret = calc_ccnt(info, &ccnt_data); | ||
722 | if (ret) | ||
723 | goto out; | ||
724 | soc: | ||
725 | data = info->max_capacity * info->start_soc / 100; | ||
726 | if (ccnt_data.total_dischg - ccnt_data.total_chg <= data) { | ||
727 | cap_cc = | ||
728 | data + ccnt_data.total_chg - ccnt_data.total_dischg; | ||
729 | } else { | ||
730 | clear_ccnt(info, &ccnt_data); | ||
731 | calc_soc(info, OCV_MODE_ACTIVE, &info->start_soc); | ||
732 | dev_dbg(info->dev, "restart soc = %d !\n", | ||
733 | info->start_soc); | ||
734 | goto soc; | ||
735 | } | ||
736 | |||
737 | cap_cc = cap_cc * 100 / info->max_capacity; | ||
738 | if (cap_cc < 0) | ||
739 | cap_cc = 0; | ||
740 | else if (cap_cc > 100) | ||
741 | cap_cc = 100; | ||
742 | |||
743 | dev_dbg(info->dev, "%s, last cap : %d", __func__, | ||
744 | info->last_capacity); | ||
745 | |||
746 | ret = measure_current(info, &ibat); | ||
747 | if (ret) | ||
748 | goto out; | ||
749 | /* Calculate the capacity when discharging(ibat < 0) */ | ||
750 | if (ibat < 0) { | ||
751 | ret = calc_soc(info, OCV_MODE_ACTIVE, &cap_ocv); | ||
752 | if (ret) | ||
753 | cap_ocv = info->last_capacity; | ||
754 | ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); | ||
755 | if (ret) | ||
756 | goto out; | ||
757 | if (data <= LOW_BAT_THRESHOLD) { | ||
758 | /* choose the lower capacity value to report | ||
759 | * between vbat and CC when vbat < 3.6v; | ||
760 | * than 3.6v; | ||
761 | */ | ||
762 | *cap = min(cap_ocv, cap_cc); | ||
763 | } else { | ||
764 | /* when detect vbat > 3.6v, but cap_cc < 15,and | ||
765 | * cap_ocv is 10% larger than cap_cc, we can think | ||
766 | * CC have some accumulation error, switch to OCV | ||
767 | * to estimate capacity; | ||
768 | * */ | ||
769 | if (cap_cc < 15 && cap_ocv - cap_cc > 10) | ||
770 | *cap = cap_ocv; | ||
771 | else | ||
772 | *cap = cap_cc; | ||
773 | } | ||
774 | /* when discharging, make sure current capacity | ||
775 | * is lower than last*/ | ||
776 | if (*cap > info->last_capacity) | ||
777 | *cap = info->last_capacity; | ||
778 | } else { | ||
779 | *cap = cap_cc; | ||
780 | } | ||
781 | info->last_capacity = *cap; | ||
782 | |||
783 | dev_dbg(info->dev, "%s, cap_ocv:%d cap_cc:%d, cap:%d\n", | ||
784 | (ibat < 0) ? "discharging" : "charging", | ||
785 | cap_ocv, cap_cc, *cap); | ||
786 | /* | ||
787 | * store the current capacity to RTC domain register, | ||
788 | * after next power up , it will be restored. | ||
789 | */ | ||
790 | pm860x_set_bits(info->i2c, PM8607_RTC_MISC2, RTC_SOC_5LSB, | ||
791 | (*cap & 0x1F) << 3); | ||
792 | pm860x_set_bits(info->i2c, PM8607_RTC1, RTC_SOC_3MSB, | ||
793 | ((*cap >> 5) & 0x3)); | ||
794 | return 0; | ||
795 | out: | ||
796 | return ret; | ||
797 | } | ||
798 | |||
799 | static void pm860x_external_power_changed(struct power_supply *psy) | ||
800 | { | ||
801 | struct pm860x_battery_info *info; | ||
802 | |||
803 | info = container_of(psy, struct pm860x_battery_info, battery); | ||
804 | calc_resistor(info); | ||
805 | } | ||
806 | |||
807 | static int pm860x_batt_get_prop(struct power_supply *psy, | ||
808 | enum power_supply_property psp, | ||
809 | union power_supply_propval *val) | ||
810 | { | ||
811 | struct pm860x_battery_info *info = dev_get_drvdata(psy->dev->parent); | ||
812 | int data; | ||
813 | int ret; | ||
814 | |||
815 | switch (psp) { | ||
816 | case POWER_SUPPLY_PROP_PRESENT: | ||
817 | val->intval = info->present; | ||
818 | break; | ||
819 | case POWER_SUPPLY_PROP_CAPACITY: | ||
820 | ret = calc_capacity(info, &data); | ||
821 | if (ret) | ||
822 | return ret; | ||
823 | if (data < 0) | ||
824 | data = 0; | ||
825 | else if (data > 100) | ||
826 | data = 100; | ||
827 | /* return 100 if battery is not attached */ | ||
828 | if (!info->present) | ||
829 | data = 100; | ||
830 | val->intval = data; | ||
831 | break; | ||
832 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
833 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | ||
834 | break; | ||
835 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
836 | /* return real vbatt Voltage */ | ||
837 | ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data); | ||
838 | if (ret) | ||
839 | return ret; | ||
840 | val->intval = data * 1000; | ||
841 | break; | ||
842 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | ||
843 | /* return Open Circuit Voltage (not measured voltage) */ | ||
844 | ret = calc_ocv(info, &data); | ||
845 | if (ret) | ||
846 | return ret; | ||
847 | val->intval = data * 1000; | ||
848 | break; | ||
849 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
850 | ret = measure_current(info, &data); | ||
851 | if (ret) | ||
852 | return ret; | ||
853 | val->intval = data; | ||
854 | break; | ||
855 | case POWER_SUPPLY_PROP_TEMP: | ||
856 | if (info->present) { | ||
857 | ret = measure_temp(info, &data); | ||
858 | if (ret) | ||
859 | return ret; | ||
860 | data *= 10; | ||
861 | } else { | ||
862 | /* Fake Temp 25C Without Battery */ | ||
863 | data = 250; | ||
864 | } | ||
865 | val->intval = data; | ||
866 | break; | ||
867 | default: | ||
868 | return -ENODEV; | ||
869 | } | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | static int pm860x_batt_set_prop(struct power_supply *psy, | ||
874 | enum power_supply_property psp, | ||
875 | const union power_supply_propval *val) | ||
876 | { | ||
877 | struct pm860x_battery_info *info = dev_get_drvdata(psy->dev->parent); | ||
878 | |||
879 | switch (psp) { | ||
880 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
881 | clear_ccnt(info, &ccnt_data); | ||
882 | info->start_soc = 100; | ||
883 | dev_dbg(info->dev, "chg done, update soc = %d\n", | ||
884 | info->start_soc); | ||
885 | break; | ||
886 | default: | ||
887 | return -EPERM; | ||
888 | } | ||
889 | |||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | |||
894 | static enum power_supply_property pm860x_batt_props[] = { | ||
895 | POWER_SUPPLY_PROP_PRESENT, | ||
896 | POWER_SUPPLY_PROP_CAPACITY, | ||
897 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
898 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
899 | POWER_SUPPLY_PROP_VOLTAGE_AVG, | ||
900 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
901 | POWER_SUPPLY_PROP_TEMP, | ||
902 | }; | ||
903 | |||
904 | static int pm860x_battery_probe(struct platform_device *pdev) | ||
905 | { | ||
906 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
907 | struct pm860x_battery_info *info; | ||
908 | struct pm860x_power_pdata *pdata; | ||
909 | int ret; | ||
910 | |||
911 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | ||
912 | if (!info) | ||
913 | return -ENOMEM; | ||
914 | |||
915 | info->irq_cc = platform_get_irq(pdev, 0); | ||
916 | if (info->irq_cc <= 0) { | ||
917 | dev_err(&pdev->dev, "No IRQ resource!\n"); | ||
918 | ret = -EINVAL; | ||
919 | goto out; | ||
920 | } | ||
921 | |||
922 | info->irq_batt = platform_get_irq(pdev, 1); | ||
923 | if (info->irq_batt <= 0) { | ||
924 | dev_err(&pdev->dev, "No IRQ resource!\n"); | ||
925 | ret = -EINVAL; | ||
926 | goto out; | ||
927 | } | ||
928 | |||
929 | info->chip = chip; | ||
930 | info->i2c = | ||
931 | (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | ||
932 | info->dev = &pdev->dev; | ||
933 | info->status = POWER_SUPPLY_STATUS_UNKNOWN; | ||
934 | pdata = pdev->dev.platform_data; | ||
935 | |||
936 | mutex_init(&info->lock); | ||
937 | platform_set_drvdata(pdev, info); | ||
938 | |||
939 | pm860x_init_battery(info); | ||
940 | |||
941 | info->battery.name = "battery-monitor"; | ||
942 | info->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
943 | info->battery.properties = pm860x_batt_props; | ||
944 | info->battery.num_properties = ARRAY_SIZE(pm860x_batt_props); | ||
945 | info->battery.get_property = pm860x_batt_get_prop; | ||
946 | info->battery.set_property = pm860x_batt_set_prop; | ||
947 | info->battery.external_power_changed = pm860x_external_power_changed; | ||
948 | |||
949 | if (pdata && pdata->max_capacity) | ||
950 | info->max_capacity = pdata->max_capacity; | ||
951 | else | ||
952 | info->max_capacity = 1500; /* set default capacity */ | ||
953 | if (pdata && pdata->resistor) | ||
954 | info->resistor = pdata->resistor; | ||
955 | else | ||
956 | info->resistor = 300; /* set default internal resistor */ | ||
957 | |||
958 | ret = power_supply_register(&pdev->dev, &info->battery); | ||
959 | if (ret) | ||
960 | goto out; | ||
961 | info->battery.dev->parent = &pdev->dev; | ||
962 | |||
963 | ret = request_threaded_irq(info->irq_cc, NULL, | ||
964 | pm860x_coulomb_handler, IRQF_ONESHOT, | ||
965 | "coulomb", info); | ||
966 | if (ret < 0) { | ||
967 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
968 | info->irq_cc, ret); | ||
969 | goto out_reg; | ||
970 | } | ||
971 | |||
972 | ret = request_threaded_irq(info->irq_batt, NULL, pm860x_batt_handler, | ||
973 | IRQF_ONESHOT, "battery", info); | ||
974 | if (ret < 0) { | ||
975 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
976 | info->irq_batt, ret); | ||
977 | goto out_coulomb; | ||
978 | } | ||
979 | |||
980 | |||
981 | return 0; | ||
982 | |||
983 | out_coulomb: | ||
984 | free_irq(info->irq_cc, info); | ||
985 | out_reg: | ||
986 | power_supply_unregister(&info->battery); | ||
987 | out: | ||
988 | kfree(info); | ||
989 | return ret; | ||
990 | } | ||
991 | |||
992 | static int pm860x_battery_remove(struct platform_device *pdev) | ||
993 | { | ||
994 | struct pm860x_battery_info *info = platform_get_drvdata(pdev); | ||
995 | |||
996 | power_supply_unregister(&info->battery); | ||
997 | free_irq(info->irq_batt, info); | ||
998 | free_irq(info->irq_cc, info); | ||
999 | kfree(info); | ||
1000 | platform_set_drvdata(pdev, NULL); | ||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | #ifdef CONFIG_PM_SLEEP | ||
1005 | static int pm860x_battery_suspend(struct device *dev) | ||
1006 | { | ||
1007 | struct platform_device *pdev = to_platform_device(dev); | ||
1008 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
1009 | |||
1010 | if (device_may_wakeup(dev)) | ||
1011 | chip->wakeup_flag |= 1 << PM8607_IRQ_CC; | ||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | static int pm860x_battery_resume(struct device *dev) | ||
1016 | { | ||
1017 | struct platform_device *pdev = to_platform_device(dev); | ||
1018 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
1019 | |||
1020 | if (device_may_wakeup(dev)) | ||
1021 | chip->wakeup_flag &= ~(1 << PM8607_IRQ_CC); | ||
1022 | return 0; | ||
1023 | } | ||
1024 | #endif | ||
1025 | |||
1026 | static SIMPLE_DEV_PM_OPS(pm860x_battery_pm_ops, | ||
1027 | pm860x_battery_suspend, pm860x_battery_resume); | ||
1028 | |||
1029 | static struct platform_driver pm860x_battery_driver = { | ||
1030 | .driver = { | ||
1031 | .name = "88pm860x-battery", | ||
1032 | .owner = THIS_MODULE, | ||
1033 | .pm = &pm860x_battery_pm_ops, | ||
1034 | }, | ||
1035 | .probe = pm860x_battery_probe, | ||
1036 | .remove = pm860x_battery_remove, | ||
1037 | }; | ||
1038 | module_platform_driver(pm860x_battery_driver); | ||
1039 | |||
1040 | MODULE_DESCRIPTION("Marvell 88PM860x Battery driver"); | ||
1041 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c deleted file mode 100644 index 4b37a5af8de..00000000000 --- a/drivers/power/88pm860x_charger.c +++ /dev/null | |||
@@ -1,746 +0,0 @@ | |||
1 | /* | ||
2 | * Battery driver for Marvell 88PM860x PMIC | ||
3 | * | ||
4 | * Copyright (c) 2012 Marvell International Ltd. | ||
5 | * Author: Jett Zhou <jtzhou@marvell.com> | ||
6 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/power_supply.h> | ||
18 | #include <linux/mfd/88pm860x.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/uaccess.h> | ||
21 | #include <asm/div64.h> | ||
22 | |||
23 | /* bit definitions of Status Query Interface 2 */ | ||
24 | #define STATUS2_CHG (1 << 2) | ||
25 | |||
26 | /* bit definitions of Reset Out Register */ | ||
27 | #define RESET_SW_PD (1 << 7) | ||
28 | |||
29 | /* bit definitions of PreReg 1 */ | ||
30 | #define PREREG1_90MA (0x0) | ||
31 | #define PREREG1_180MA (0x1) | ||
32 | #define PREREG1_450MA (0x4) | ||
33 | #define PREREG1_540MA (0x5) | ||
34 | #define PREREG1_1350MA (0xE) | ||
35 | #define PREREG1_VSYS_4_5V (3 << 4) | ||
36 | |||
37 | /* bit definitions of Charger Control 1 Register */ | ||
38 | #define CC1_MODE_OFF (0) | ||
39 | #define CC1_MODE_PRECHARGE (1) | ||
40 | #define CC1_MODE_FASTCHARGE (2) | ||
41 | #define CC1_MODE_PULSECHARGE (3) | ||
42 | #define CC1_ITERM_20MA (0 << 2) | ||
43 | #define CC1_ITERM_60MA (2 << 2) | ||
44 | #define CC1_VFCHG_4_2V (9 << 4) | ||
45 | |||
46 | /* bit definitions of Charger Control 2 Register */ | ||
47 | #define CC2_ICHG_100MA (0x1) | ||
48 | #define CC2_ICHG_500MA (0x9) | ||
49 | #define CC2_ICHG_1000MA (0x13) | ||
50 | |||
51 | /* bit definitions of Charger Control 3 Register */ | ||
52 | #define CC3_180MIN_TIMEOUT (0x6 << 4) | ||
53 | #define CC3_270MIN_TIMEOUT (0x7 << 4) | ||
54 | #define CC3_360MIN_TIMEOUT (0xA << 4) | ||
55 | #define CC3_DISABLE_TIMEOUT (0xF << 4) | ||
56 | |||
57 | /* bit definitions of Charger Control 4 Register */ | ||
58 | #define CC4_IPRE_40MA (7) | ||
59 | #define CC4_VPCHG_3_2V (3 << 4) | ||
60 | #define CC4_IFCHG_MON_EN (1 << 6) | ||
61 | #define CC4_BTEMP_MON_EN (1 << 7) | ||
62 | |||
63 | /* bit definitions of Charger Control 6 Register */ | ||
64 | #define CC6_BAT_OV_EN (1 << 2) | ||
65 | #define CC6_BAT_UV_EN (1 << 3) | ||
66 | #define CC6_UV_VBAT_SET (0x3 << 6) /* 2.8v */ | ||
67 | |||
68 | /* bit definitions of Charger Control 7 Register */ | ||
69 | #define CC7_BAT_REM_EN (1 << 3) | ||
70 | #define CC7_IFSM_EN (1 << 7) | ||
71 | |||
72 | /* bit definitions of Measurement Enable 1 Register */ | ||
73 | #define MEAS1_VBAT (1 << 0) | ||
74 | |||
75 | /* bit definitions of Measurement Enable 3 Register */ | ||
76 | #define MEAS3_IBAT_EN (1 << 0) | ||
77 | #define MEAS3_CC_EN (1 << 2) | ||
78 | |||
79 | #define FSM_INIT 0 | ||
80 | #define FSM_DISCHARGE 1 | ||
81 | #define FSM_PRECHARGE 2 | ||
82 | #define FSM_FASTCHARGE 3 | ||
83 | |||
84 | #define PRECHARGE_THRESHOLD 3100 | ||
85 | #define POWEROFF_THRESHOLD 3400 | ||
86 | #define CHARGE_THRESHOLD 4000 | ||
87 | #define DISCHARGE_THRESHOLD 4180 | ||
88 | |||
89 | /* over-temperature on PM8606 setting */ | ||
90 | #define OVER_TEMP_FLAG (1 << 6) | ||
91 | #define OVTEMP_AUTORECOVER (1 << 3) | ||
92 | |||
93 | /* over-voltage protect on vchg setting mv */ | ||
94 | #define VCHG_NORMAL_LOW 4200 | ||
95 | #define VCHG_NORMAL_CHECK 5800 | ||
96 | #define VCHG_NORMAL_HIGH 6000 | ||
97 | #define VCHG_OVP_LOW 5500 | ||
98 | |||
99 | struct pm860x_charger_info { | ||
100 | struct pm860x_chip *chip; | ||
101 | struct i2c_client *i2c; | ||
102 | struct i2c_client *i2c_8606; | ||
103 | struct device *dev; | ||
104 | |||
105 | struct power_supply usb; | ||
106 | struct mutex lock; | ||
107 | int irq_nums; | ||
108 | int irq[7]; | ||
109 | unsigned state:3; /* fsm state */ | ||
110 | unsigned online:1; /* usb charger */ | ||
111 | unsigned present:1; /* battery present */ | ||
112 | unsigned allowed:1; | ||
113 | }; | ||
114 | |||
115 | static char *pm860x_supplied_to[] = { | ||
116 | "battery-monitor", | ||
117 | }; | ||
118 | |||
119 | static int measure_vchg(struct pm860x_charger_info *info, int *data) | ||
120 | { | ||
121 | unsigned char buf[2]; | ||
122 | int ret = 0; | ||
123 | |||
124 | ret = pm860x_bulk_read(info->i2c, PM8607_VCHG_MEAS1, 2, buf); | ||
125 | if (ret < 0) | ||
126 | return ret; | ||
127 | |||
128 | *data = ((buf[0] & 0xff) << 4) | (buf[1] & 0x0f); | ||
129 | /* V_BATT_MEAS(mV) = value * 5 * 1.8 * 1000 / (2^12) */ | ||
130 | *data = ((*data & 0xfff) * 9 * 125) >> 9; | ||
131 | |||
132 | dev_dbg(info->dev, "%s, vchg: %d mv\n", __func__, *data); | ||
133 | |||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | static void set_vchg_threshold(struct pm860x_charger_info *info, | ||
138 | int min, int max) | ||
139 | { | ||
140 | int data; | ||
141 | |||
142 | /* (tmp << 8) * / 5 / 1800 */ | ||
143 | if (min <= 0) | ||
144 | data = 0; | ||
145 | else | ||
146 | data = (min << 5) / 1125; | ||
147 | pm860x_reg_write(info->i2c, PM8607_VCHG_LOWTH, data); | ||
148 | dev_dbg(info->dev, "VCHG_LOWTH:%dmv, 0x%x\n", min, data); | ||
149 | |||
150 | if (max <= 0) | ||
151 | data = 0xff; | ||
152 | else | ||
153 | data = (max << 5) / 1125; | ||
154 | pm860x_reg_write(info->i2c, PM8607_VCHG_HIGHTH, data); | ||
155 | dev_dbg(info->dev, "VCHG_HIGHTH:%dmv, 0x%x\n", max, data); | ||
156 | |||
157 | } | ||
158 | |||
159 | static void set_vbatt_threshold(struct pm860x_charger_info *info, | ||
160 | int min, int max) | ||
161 | { | ||
162 | int data; | ||
163 | |||
164 | /* (tmp << 8) * 3 / 1800 */ | ||
165 | if (min <= 0) | ||
166 | data = 0; | ||
167 | else | ||
168 | data = (min << 5) / 675; | ||
169 | pm860x_reg_write(info->i2c, PM8607_VBAT_LOWTH, data); | ||
170 | dev_dbg(info->dev, "VBAT Min:%dmv, LOWTH:0x%x\n", min, data); | ||
171 | |||
172 | if (max <= 0) | ||
173 | data = 0xff; | ||
174 | else | ||
175 | data = (max << 5) / 675; | ||
176 | pm860x_reg_write(info->i2c, PM8607_VBAT_HIGHTH, data); | ||
177 | dev_dbg(info->dev, "VBAT Max:%dmv, HIGHTH:0x%x\n", max, data); | ||
178 | |||
179 | return; | ||
180 | } | ||
181 | |||
182 | static int start_precharge(struct pm860x_charger_info *info) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | dev_dbg(info->dev, "Start Pre-charging!\n"); | ||
187 | set_vbatt_threshold(info, 0, 0); | ||
188 | |||
189 | ret = pm860x_reg_write(info->i2c_8606, PM8606_PREREGULATORA, | ||
190 | PREREG1_1350MA | PREREG1_VSYS_4_5V); | ||
191 | if (ret < 0) | ||
192 | goto out; | ||
193 | /* stop charging */ | ||
194 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL1, 3, | ||
195 | CC1_MODE_OFF); | ||
196 | if (ret < 0) | ||
197 | goto out; | ||
198 | /* set 270 minutes timeout */ | ||
199 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL3, (0xf << 4), | ||
200 | CC3_270MIN_TIMEOUT); | ||
201 | if (ret < 0) | ||
202 | goto out; | ||
203 | /* set precharge current, termination voltage, IBAT & TBAT monitor */ | ||
204 | ret = pm860x_reg_write(info->i2c, PM8607_CHG_CTRL4, | ||
205 | CC4_IPRE_40MA | CC4_VPCHG_3_2V | | ||
206 | CC4_IFCHG_MON_EN | CC4_BTEMP_MON_EN); | ||
207 | if (ret < 0) | ||
208 | goto out; | ||
209 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL7, | ||
210 | CC7_BAT_REM_EN | CC7_IFSM_EN, | ||
211 | CC7_BAT_REM_EN | CC7_IFSM_EN); | ||
212 | if (ret < 0) | ||
213 | goto out; | ||
214 | /* trigger precharge */ | ||
215 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL1, 3, | ||
216 | CC1_MODE_PRECHARGE); | ||
217 | out: | ||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | static int start_fastcharge(struct pm860x_charger_info *info) | ||
222 | { | ||
223 | int ret; | ||
224 | |||
225 | dev_dbg(info->dev, "Start Fast-charging!\n"); | ||
226 | |||
227 | /* set fastcharge termination current & voltage, disable charging */ | ||
228 | ret = pm860x_reg_write(info->i2c, PM8607_CHG_CTRL1, | ||
229 | CC1_MODE_OFF | CC1_ITERM_60MA | | ||
230 | CC1_VFCHG_4_2V); | ||
231 | if (ret < 0) | ||
232 | goto out; | ||
233 | ret = pm860x_reg_write(info->i2c_8606, PM8606_PREREGULATORA, | ||
234 | PREREG1_540MA | PREREG1_VSYS_4_5V); | ||
235 | if (ret < 0) | ||
236 | goto out; | ||
237 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL2, 0x1f, | ||
238 | CC2_ICHG_500MA); | ||
239 | if (ret < 0) | ||
240 | goto out; | ||
241 | /* set 270 minutes timeout */ | ||
242 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL3, (0xf << 4), | ||
243 | CC3_270MIN_TIMEOUT); | ||
244 | if (ret < 0) | ||
245 | goto out; | ||
246 | /* set IBAT & TBAT monitor */ | ||
247 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL4, | ||
248 | CC4_IFCHG_MON_EN | CC4_BTEMP_MON_EN, | ||
249 | CC4_IFCHG_MON_EN | CC4_BTEMP_MON_EN); | ||
250 | if (ret < 0) | ||
251 | goto out; | ||
252 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL6, | ||
253 | CC6_BAT_OV_EN | CC6_BAT_UV_EN | | ||
254 | CC6_UV_VBAT_SET, | ||
255 | CC6_BAT_OV_EN | CC6_BAT_UV_EN | | ||
256 | CC6_UV_VBAT_SET); | ||
257 | if (ret < 0) | ||
258 | goto out; | ||
259 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL7, | ||
260 | CC7_BAT_REM_EN | CC7_IFSM_EN, | ||
261 | CC7_BAT_REM_EN | CC7_IFSM_EN); | ||
262 | if (ret < 0) | ||
263 | goto out; | ||
264 | /* launch fast-charge */ | ||
265 | ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL1, 3, | ||
266 | CC1_MODE_FASTCHARGE); | ||
267 | /* vchg threshold setting */ | ||
268 | set_vchg_threshold(info, VCHG_NORMAL_LOW, VCHG_NORMAL_HIGH); | ||
269 | out: | ||
270 | return ret; | ||
271 | } | ||
272 | |||
273 | static void stop_charge(struct pm860x_charger_info *info, int vbatt) | ||
274 | { | ||
275 | dev_dbg(info->dev, "Stop charging!\n"); | ||
276 | pm860x_set_bits(info->i2c, PM8607_CHG_CTRL1, 3, CC1_MODE_OFF); | ||
277 | if (vbatt > CHARGE_THRESHOLD && info->online) | ||
278 | set_vbatt_threshold(info, CHARGE_THRESHOLD, 0); | ||
279 | } | ||
280 | |||
281 | static void power_off_notification(struct pm860x_charger_info *info) | ||
282 | { | ||
283 | dev_dbg(info->dev, "Power-off notification!\n"); | ||
284 | } | ||
285 | |||
286 | static int set_charging_fsm(struct pm860x_charger_info *info) | ||
287 | { | ||
288 | struct power_supply *psy; | ||
289 | union power_supply_propval data; | ||
290 | unsigned char fsm_state[][16] = { "init", "discharge", "precharge", | ||
291 | "fastcharge", | ||
292 | }; | ||
293 | int ret; | ||
294 | int vbatt; | ||
295 | |||
296 | psy = power_supply_get_by_name(pm860x_supplied_to[0]); | ||
297 | if (!psy) | ||
298 | return -EINVAL; | ||
299 | ret = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &data); | ||
300 | if (ret) | ||
301 | return ret; | ||
302 | vbatt = data.intval / 1000; | ||
303 | |||
304 | ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT, &data); | ||
305 | if (ret) | ||
306 | return ret; | ||
307 | |||
308 | mutex_lock(&info->lock); | ||
309 | info->present = data.intval; | ||
310 | |||
311 | dev_dbg(info->dev, "Entering FSM:%s, Charger:%s, Battery:%s, " | ||
312 | "Allowed:%d\n", | ||
313 | &fsm_state[info->state][0], | ||
314 | (info->online) ? "online" : "N/A", | ||
315 | (info->present) ? "present" : "N/A", info->allowed); | ||
316 | dev_dbg(info->dev, "set_charging_fsm:vbatt:%d(mV)\n", vbatt); | ||
317 | |||
318 | switch (info->state) { | ||
319 | case FSM_INIT: | ||
320 | if (info->online && info->present && info->allowed) { | ||
321 | if (vbatt < PRECHARGE_THRESHOLD) { | ||
322 | info->state = FSM_PRECHARGE; | ||
323 | start_precharge(info); | ||
324 | } else if (vbatt > DISCHARGE_THRESHOLD) { | ||
325 | info->state = FSM_DISCHARGE; | ||
326 | stop_charge(info, vbatt); | ||
327 | } else if (vbatt < DISCHARGE_THRESHOLD) { | ||
328 | info->state = FSM_FASTCHARGE; | ||
329 | start_fastcharge(info); | ||
330 | } | ||
331 | } else { | ||
332 | if (vbatt < POWEROFF_THRESHOLD) { | ||
333 | power_off_notification(info); | ||
334 | } else { | ||
335 | info->state = FSM_DISCHARGE; | ||
336 | stop_charge(info, vbatt); | ||
337 | } | ||
338 | } | ||
339 | break; | ||
340 | case FSM_PRECHARGE: | ||
341 | if (info->online && info->present && info->allowed) { | ||
342 | if (vbatt > PRECHARGE_THRESHOLD) { | ||
343 | info->state = FSM_FASTCHARGE; | ||
344 | start_fastcharge(info); | ||
345 | } | ||
346 | } else { | ||
347 | info->state = FSM_DISCHARGE; | ||
348 | stop_charge(info, vbatt); | ||
349 | } | ||
350 | break; | ||
351 | case FSM_FASTCHARGE: | ||
352 | if (info->online && info->present && info->allowed) { | ||
353 | if (vbatt < PRECHARGE_THRESHOLD) { | ||
354 | info->state = FSM_PRECHARGE; | ||
355 | start_precharge(info); | ||
356 | } | ||
357 | } else { | ||
358 | info->state = FSM_DISCHARGE; | ||
359 | stop_charge(info, vbatt); | ||
360 | } | ||
361 | break; | ||
362 | case FSM_DISCHARGE: | ||
363 | if (info->online && info->present && info->allowed) { | ||
364 | if (vbatt < PRECHARGE_THRESHOLD) { | ||
365 | info->state = FSM_PRECHARGE; | ||
366 | start_precharge(info); | ||
367 | } else if (vbatt < DISCHARGE_THRESHOLD) { | ||
368 | info->state = FSM_FASTCHARGE; | ||
369 | start_fastcharge(info); | ||
370 | } | ||
371 | } else { | ||
372 | if (vbatt < POWEROFF_THRESHOLD) | ||
373 | power_off_notification(info); | ||
374 | else if (vbatt > CHARGE_THRESHOLD && info->online) | ||
375 | set_vbatt_threshold(info, CHARGE_THRESHOLD, 0); | ||
376 | } | ||
377 | break; | ||
378 | default: | ||
379 | dev_warn(info->dev, "FSM meets wrong state:%d\n", | ||
380 | info->state); | ||
381 | break; | ||
382 | } | ||
383 | dev_dbg(info->dev, | ||
384 | "Out FSM:%s, Charger:%s, Battery:%s, Allowed:%d\n", | ||
385 | &fsm_state[info->state][0], | ||
386 | (info->online) ? "online" : "N/A", | ||
387 | (info->present) ? "present" : "N/A", info->allowed); | ||
388 | mutex_unlock(&info->lock); | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static irqreturn_t pm860x_charger_handler(int irq, void *data) | ||
394 | { | ||
395 | struct pm860x_charger_info *info = data; | ||
396 | int ret; | ||
397 | |||
398 | mutex_lock(&info->lock); | ||
399 | ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); | ||
400 | if (ret < 0) { | ||
401 | mutex_unlock(&info->lock); | ||
402 | goto out; | ||
403 | } | ||
404 | if (ret & STATUS2_CHG) { | ||
405 | info->online = 1; | ||
406 | info->allowed = 1; | ||
407 | } else { | ||
408 | info->online = 0; | ||
409 | info->allowed = 0; | ||
410 | } | ||
411 | mutex_unlock(&info->lock); | ||
412 | dev_dbg(info->dev, "%s, Charger:%s, Allowed:%d\n", __func__, | ||
413 | (info->online) ? "online" : "N/A", info->allowed); | ||
414 | |||
415 | set_charging_fsm(info); | ||
416 | |||
417 | power_supply_changed(&info->usb); | ||
418 | out: | ||
419 | return IRQ_HANDLED; | ||
420 | } | ||
421 | |||
422 | static irqreturn_t pm860x_temp_handler(int irq, void *data) | ||
423 | { | ||
424 | struct power_supply *psy; | ||
425 | struct pm860x_charger_info *info = data; | ||
426 | union power_supply_propval temp; | ||
427 | int value; | ||
428 | int ret; | ||
429 | |||
430 | psy = power_supply_get_by_name(pm860x_supplied_to[0]); | ||
431 | if (!psy) | ||
432 | goto out; | ||
433 | ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &temp); | ||
434 | if (ret) | ||
435 | goto out; | ||
436 | value = temp.intval / 10; | ||
437 | |||
438 | mutex_lock(&info->lock); | ||
439 | /* Temperature < -10 C or >40 C, Will not allow charge */ | ||
440 | if (value < -10 || value > 40) | ||
441 | info->allowed = 0; | ||
442 | else | ||
443 | info->allowed = 1; | ||
444 | dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed); | ||
445 | mutex_unlock(&info->lock); | ||
446 | |||
447 | set_charging_fsm(info); | ||
448 | out: | ||
449 | return IRQ_HANDLED; | ||
450 | } | ||
451 | |||
452 | static irqreturn_t pm860x_exception_handler(int irq, void *data) | ||
453 | { | ||
454 | struct pm860x_charger_info *info = data; | ||
455 | |||
456 | mutex_lock(&info->lock); | ||
457 | info->allowed = 0; | ||
458 | mutex_unlock(&info->lock); | ||
459 | dev_dbg(info->dev, "%s, irq: %d\n", __func__, irq); | ||
460 | |||
461 | set_charging_fsm(info); | ||
462 | return IRQ_HANDLED; | ||
463 | } | ||
464 | |||
465 | static irqreturn_t pm860x_done_handler(int irq, void *data) | ||
466 | { | ||
467 | struct pm860x_charger_info *info = data; | ||
468 | struct power_supply *psy; | ||
469 | union power_supply_propval val; | ||
470 | int ret; | ||
471 | int vbatt; | ||
472 | |||
473 | mutex_lock(&info->lock); | ||
474 | /* pre-charge done, will transimit to fast-charge stage */ | ||
475 | if (info->state == FSM_PRECHARGE) { | ||
476 | info->allowed = 1; | ||
477 | goto out; | ||
478 | } | ||
479 | /* | ||
480 | * Fast charge done, delay to read | ||
481 | * the correct status of CHG_DET. | ||
482 | */ | ||
483 | mdelay(5); | ||
484 | info->allowed = 0; | ||
485 | psy = power_supply_get_by_name(pm860x_supplied_to[0]); | ||
486 | if (!psy) | ||
487 | goto out; | ||
488 | ret = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &val); | ||
489 | if (ret) | ||
490 | goto out; | ||
491 | vbatt = val.intval / 1000; | ||
492 | /* | ||
493 | * CHG_DONE interrupt is faster than CHG_DET interrupt when | ||
494 | * plug in/out usb, So we can not rely on info->online, we | ||
495 | * need check pm8607 status register to check usb is online | ||
496 | * or not, then we can decide it is real charge done | ||
497 | * automatically or it is triggered by usb plug out; | ||
498 | */ | ||
499 | ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); | ||
500 | if (ret < 0) | ||
501 | goto out; | ||
502 | if (vbatt > CHARGE_THRESHOLD && ret & STATUS2_CHG) | ||
503 | psy->set_property(psy, POWER_SUPPLY_PROP_CHARGE_FULL, &val); | ||
504 | |||
505 | out: | ||
506 | mutex_unlock(&info->lock); | ||
507 | dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed); | ||
508 | set_charging_fsm(info); | ||
509 | |||
510 | return IRQ_HANDLED; | ||
511 | } | ||
512 | |||
513 | static irqreturn_t pm860x_vbattery_handler(int irq, void *data) | ||
514 | { | ||
515 | struct pm860x_charger_info *info = data; | ||
516 | |||
517 | mutex_lock(&info->lock); | ||
518 | |||
519 | set_vbatt_threshold(info, 0, 0); | ||
520 | |||
521 | if (info->present && info->online) | ||
522 | info->allowed = 1; | ||
523 | else | ||
524 | info->allowed = 0; | ||
525 | mutex_unlock(&info->lock); | ||
526 | dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed); | ||
527 | |||
528 | set_charging_fsm(info); | ||
529 | |||
530 | return IRQ_HANDLED; | ||
531 | } | ||
532 | |||
533 | static irqreturn_t pm860x_vchg_handler(int irq, void *data) | ||
534 | { | ||
535 | struct pm860x_charger_info *info = data; | ||
536 | int vchg = 0; | ||
537 | |||
538 | if (info->present) | ||
539 | goto out; | ||
540 | |||
541 | measure_vchg(info, &vchg); | ||
542 | |||
543 | mutex_lock(&info->lock); | ||
544 | if (!info->online) { | ||
545 | int status; | ||
546 | /* check if over-temp on pm8606 or not */ | ||
547 | status = pm860x_reg_read(info->i2c_8606, PM8606_FLAGS); | ||
548 | if (status & OVER_TEMP_FLAG) { | ||
549 | /* clear over temp flag and set auto recover */ | ||
550 | pm860x_set_bits(info->i2c_8606, PM8606_FLAGS, | ||
551 | OVER_TEMP_FLAG, OVER_TEMP_FLAG); | ||
552 | pm860x_set_bits(info->i2c_8606, | ||
553 | PM8606_VSYS, | ||
554 | OVTEMP_AUTORECOVER, | ||
555 | OVTEMP_AUTORECOVER); | ||
556 | dev_dbg(info->dev, | ||
557 | "%s, pm8606 over-temp occure\n", __func__); | ||
558 | } | ||
559 | } | ||
560 | |||
561 | if (vchg > VCHG_NORMAL_CHECK) { | ||
562 | set_vchg_threshold(info, VCHG_OVP_LOW, 0); | ||
563 | info->allowed = 0; | ||
564 | dev_dbg(info->dev, | ||
565 | "%s,pm8607 over-vchg occure,vchg = %dmv\n", | ||
566 | __func__, vchg); | ||
567 | } else if (vchg < VCHG_OVP_LOW) { | ||
568 | set_vchg_threshold(info, VCHG_NORMAL_LOW, | ||
569 | VCHG_NORMAL_HIGH); | ||
570 | info->allowed = 1; | ||
571 | dev_dbg(info->dev, | ||
572 | "%s,pm8607 over-vchg recover,vchg = %dmv\n", | ||
573 | __func__, vchg); | ||
574 | } | ||
575 | mutex_unlock(&info->lock); | ||
576 | |||
577 | dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed); | ||
578 | set_charging_fsm(info); | ||
579 | out: | ||
580 | return IRQ_HANDLED; | ||
581 | } | ||
582 | |||
583 | static int pm860x_usb_get_prop(struct power_supply *psy, | ||
584 | enum power_supply_property psp, | ||
585 | union power_supply_propval *val) | ||
586 | { | ||
587 | struct pm860x_charger_info *info = | ||
588 | dev_get_drvdata(psy->dev->parent); | ||
589 | |||
590 | switch (psp) { | ||
591 | case POWER_SUPPLY_PROP_STATUS: | ||
592 | if (info->state == FSM_FASTCHARGE || | ||
593 | info->state == FSM_PRECHARGE) | ||
594 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
595 | else | ||
596 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
597 | break; | ||
598 | case POWER_SUPPLY_PROP_ONLINE: | ||
599 | val->intval = info->online; | ||
600 | break; | ||
601 | default: | ||
602 | return -ENODEV; | ||
603 | } | ||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | static enum power_supply_property pm860x_usb_props[] = { | ||
608 | POWER_SUPPLY_PROP_STATUS, | ||
609 | POWER_SUPPLY_PROP_ONLINE, | ||
610 | }; | ||
611 | |||
612 | static int pm860x_init_charger(struct pm860x_charger_info *info) | ||
613 | { | ||
614 | int ret; | ||
615 | |||
616 | ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); | ||
617 | if (ret < 0) | ||
618 | return ret; | ||
619 | |||
620 | mutex_lock(&info->lock); | ||
621 | info->state = FSM_INIT; | ||
622 | if (ret & STATUS2_CHG) { | ||
623 | info->online = 1; | ||
624 | info->allowed = 1; | ||
625 | } else { | ||
626 | info->online = 0; | ||
627 | info->allowed = 0; | ||
628 | } | ||
629 | mutex_unlock(&info->lock); | ||
630 | |||
631 | set_charging_fsm(info); | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | static struct pm860x_irq_desc { | ||
636 | const char *name; | ||
637 | irqreturn_t (*handler)(int irq, void *data); | ||
638 | } pm860x_irq_descs[] = { | ||
639 | { "usb supply detect", pm860x_charger_handler }, | ||
640 | { "charge done", pm860x_done_handler }, | ||
641 | { "charge timeout", pm860x_exception_handler }, | ||
642 | { "charge fault", pm860x_exception_handler }, | ||
643 | { "temperature", pm860x_temp_handler }, | ||
644 | { "vbatt", pm860x_vbattery_handler }, | ||
645 | { "vchg", pm860x_vchg_handler }, | ||
646 | }; | ||
647 | |||
648 | static int pm860x_charger_probe(struct platform_device *pdev) | ||
649 | { | ||
650 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
651 | struct pm860x_charger_info *info; | ||
652 | int ret; | ||
653 | int count; | ||
654 | int i; | ||
655 | int j; | ||
656 | |||
657 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | ||
658 | if (!info) | ||
659 | return -ENOMEM; | ||
660 | |||
661 | count = pdev->num_resources; | ||
662 | for (i = 0, j = 0; i < count; i++) { | ||
663 | info->irq[j] = platform_get_irq(pdev, i); | ||
664 | if (info->irq[j] < 0) | ||
665 | continue; | ||
666 | j++; | ||
667 | } | ||
668 | info->irq_nums = j; | ||
669 | |||
670 | info->chip = chip; | ||
671 | info->i2c = | ||
672 | (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | ||
673 | info->i2c_8606 = | ||
674 | (chip->id == CHIP_PM8607) ? chip->companion : chip->client; | ||
675 | if (!info->i2c_8606) { | ||
676 | dev_err(&pdev->dev, "Missed I2C address of 88PM8606!\n"); | ||
677 | ret = -EINVAL; | ||
678 | goto out; | ||
679 | } | ||
680 | info->dev = &pdev->dev; | ||
681 | |||
682 | /* set init value for the case we are not using battery */ | ||
683 | set_vchg_threshold(info, VCHG_NORMAL_LOW, VCHG_OVP_LOW); | ||
684 | |||
685 | mutex_init(&info->lock); | ||
686 | platform_set_drvdata(pdev, info); | ||
687 | |||
688 | info->usb.name = "usb"; | ||
689 | info->usb.type = POWER_SUPPLY_TYPE_USB; | ||
690 | info->usb.supplied_to = pm860x_supplied_to; | ||
691 | info->usb.num_supplicants = ARRAY_SIZE(pm860x_supplied_to); | ||
692 | info->usb.properties = pm860x_usb_props; | ||
693 | info->usb.num_properties = ARRAY_SIZE(pm860x_usb_props); | ||
694 | info->usb.get_property = pm860x_usb_get_prop; | ||
695 | ret = power_supply_register(&pdev->dev, &info->usb); | ||
696 | if (ret) | ||
697 | goto out; | ||
698 | |||
699 | pm860x_init_charger(info); | ||
700 | |||
701 | for (i = 0; i < ARRAY_SIZE(info->irq); i++) { | ||
702 | ret = request_threaded_irq(info->irq[i], NULL, | ||
703 | pm860x_irq_descs[i].handler, | ||
704 | IRQF_ONESHOT, pm860x_irq_descs[i].name, info); | ||
705 | if (ret < 0) { | ||
706 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
707 | info->irq[i], ret); | ||
708 | goto out_irq; | ||
709 | } | ||
710 | } | ||
711 | return 0; | ||
712 | |||
713 | out_irq: | ||
714 | while (--i >= 0) | ||
715 | free_irq(info->irq[i], info); | ||
716 | out: | ||
717 | kfree(info); | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | static int pm860x_charger_remove(struct platform_device *pdev) | ||
722 | { | ||
723 | struct pm860x_charger_info *info = platform_get_drvdata(pdev); | ||
724 | int i; | ||
725 | |||
726 | platform_set_drvdata(pdev, NULL); | ||
727 | power_supply_unregister(&info->usb); | ||
728 | free_irq(info->irq[0], info); | ||
729 | for (i = 0; i < info->irq_nums; i++) | ||
730 | free_irq(info->irq[i], info); | ||
731 | kfree(info); | ||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | static struct platform_driver pm860x_charger_driver = { | ||
736 | .driver = { | ||
737 | .name = "88pm860x-charger", | ||
738 | .owner = THIS_MODULE, | ||
739 | }, | ||
740 | .probe = pm860x_charger_probe, | ||
741 | .remove = pm860x_charger_remove, | ||
742 | }; | ||
743 | module_platform_driver(pm860x_charger_driver); | ||
744 | |||
745 | MODULE_DESCRIPTION("Marvell 88PM860x Charger driver"); | ||
746 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 9f45e2f77d5..cf6d5ec23c4 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | menuconfig POWER_SUPPLY | 1 | menuconfig POWER_SUPPLY |
2 | bool "Power supply class support" | 2 | tristate "Power supply class support" |
3 | help | 3 | help |
4 | Say Y here to enable power supply class support. This allows | 4 | Say Y here to enable power supply class support. This allows |
5 | power supply (batteries, AC, USB) monitoring by userspace | 5 | power supply (batteries, AC, USB) monitoring by userspace |
@@ -29,13 +29,6 @@ config APM_POWER | |||
29 | Say Y here to enable support APM status emulation using | 29 | Say Y here to enable support APM status emulation using |
30 | battery class devices. | 30 | battery class devices. |
31 | 31 | ||
32 | config GENERIC_ADC_BATTERY | ||
33 | tristate "Generic battery support using IIO" | ||
34 | depends on IIO | ||
35 | help | ||
36 | Say Y here to enable support for the generic battery driver | ||
37 | which uses IIO framework to read adc. | ||
38 | |||
39 | config MAX8925_POWER | 32 | config MAX8925_POWER |
40 | tristate "MAX8925 battery charger support" | 33 | tristate "MAX8925 battery charger support" |
41 | depends on MFD_MAX8925 | 34 | depends on MFD_MAX8925 |
@@ -43,6 +36,13 @@ config MAX8925_POWER | |||
43 | Say Y here to enable support for the battery charger in the Maxim | 36 | Say Y here to enable support for the battery charger in the Maxim |
44 | MAX8925 PMIC. | 37 | MAX8925 PMIC. |
45 | 38 | ||
39 | config MAX8907C_CHARGER | ||
40 | tristate "MAX8907c charger support" | ||
41 | depends on MFD_MAX8907C | ||
42 | help | ||
43 | Say Y here to enable support for the charger in the Maxim | ||
44 | MAX8907c PMIC. | ||
45 | |||
46 | config WM831X_BACKUP | 46 | config WM831X_BACKUP |
47 | tristate "WM831X backup battery charger support" | 47 | tristate "WM831X backup battery charger support" |
48 | depends on MFD_WM831X | 48 | depends on MFD_WM831X |
@@ -69,12 +69,6 @@ config TEST_POWER | |||
69 | help | 69 | help |
70 | This driver is used for testing. It's safe to say M here. | 70 | This driver is used for testing. It's safe to say M here. |
71 | 71 | ||
72 | config BATTERY_88PM860X | ||
73 | tristate "Marvell 88PM860x battery driver" | ||
74 | depends on MFD_88PM860X | ||
75 | help | ||
76 | Say Y here to enable battery monitor for Marvell 88PM860x chip. | ||
77 | |||
78 | config BATTERY_DS2760 | 72 | config BATTERY_DS2760 |
79 | tristate "DS2760 battery driver (HP iPAQ & others)" | 73 | tristate "DS2760 battery driver (HP iPAQ & others)" |
80 | depends on W1 && W1_SLAVE_DS2760 | 74 | depends on W1 && W1_SLAVE_DS2760 |
@@ -83,26 +77,11 @@ config BATTERY_DS2760 | |||
83 | 77 | ||
84 | config BATTERY_DS2780 | 78 | config BATTERY_DS2780 |
85 | tristate "DS2780 battery driver" | 79 | tristate "DS2780 battery driver" |
86 | depends on HAS_IOMEM | ||
87 | select W1 | 80 | select W1 |
88 | select W1_SLAVE_DS2780 | 81 | select W1_SLAVE_DS2780 |
89 | help | 82 | help |
90 | Say Y here to enable support for batteries with ds2780 chip. | 83 | Say Y here to enable support for batteries with ds2780 chip. |
91 | 84 | ||
92 | config BATTERY_DS2781 | ||
93 | tristate "DS2781 battery driver" | ||
94 | depends on HAS_IOMEM | ||
95 | select W1 | ||
96 | select W1_SLAVE_DS2781 | ||
97 | help | ||
98 | If you enable this you will have the DS2781 battery driver support. | ||
99 | |||
100 | The battery monitor chip is used in many batteries/devices | ||
101 | as the one who is responsible for charging/discharging/monitoring | ||
102 | Li+ batteries. | ||
103 | |||
104 | If you are unsure, say N. | ||
105 | |||
106 | config BATTERY_DS2782 | 85 | config BATTERY_DS2782 |
107 | tristate "DS2782/DS2786 standalone gas-gauge" | 86 | tristate "DS2782/DS2786 standalone gas-gauge" |
108 | depends on I2C | 87 | depends on I2C |
@@ -143,12 +122,12 @@ config BATTERY_WM97XX | |||
143 | help | 122 | help |
144 | Say Y to enable support for battery measured by WM97xx aux port. | 123 | Say Y to enable support for battery measured by WM97xx aux port. |
145 | 124 | ||
146 | config BATTERY_SBS | 125 | config BATTERY_BQ20Z75 |
147 | tristate "SBS Compliant gas gauge" | 126 | tristate "TI BQ20z75 gas gauge" |
148 | depends on I2C | 127 | depends on I2C |
149 | help | 128 | help |
150 | Say Y to include support for SBS battery driver for SBS-compliant | 129 | Say Y to include support for TI BQ20z75 SBS-compliant |
151 | gas gauges. | 130 | gas gauge and protection IC. |
152 | 131 | ||
153 | config BATTERY_BQ27x00 | 132 | config BATTERY_BQ27x00 |
154 | tristate "BQ27x00 battery driver" | 133 | tristate "BQ27x00 battery driver" |
@@ -170,6 +149,26 @@ config BATTERY_BQ27X00_PLATFORM | |||
170 | help | 149 | help |
171 | Say Y here to enable support for batteries with BQ27000 (HDQ) chips. | 150 | Say Y here to enable support for batteries with BQ27000 (HDQ) chips. |
172 | 151 | ||
152 | config CHARGER_TPS8003X | ||
153 | tristate "TPS8003x battery charger driver" | ||
154 | depends on MFD_TPS80031 | ||
155 | default n | ||
156 | help | ||
157 | Say Y here to enable support for battery charging with TPS80031x chips. | ||
158 | |||
159 | config BATTERY_GAUGE_TPS8003X | ||
160 | tristate "TPS8003x battery gauge driver" | ||
161 | depends on MFD_TPS80031 | ||
162 | default n | ||
163 | help | ||
164 | Say Y here to enable support for battery gauge for TPS80031x chips. | ||
165 | |||
166 | config CHARGER_SMB349 | ||
167 | tristate "SMB349 battery charger driver" | ||
168 | depends on I2C | ||
169 | help | ||
170 | Say Y here to enable support for battery charging with SMB349 chips. | ||
171 | |||
173 | config BATTERY_DA9030 | 172 | config BATTERY_DA9030 |
174 | tristate "DA9030 battery driver" | 173 | tristate "DA9030 battery driver" |
175 | depends on PMIC_DA903X | 174 | depends on PMIC_DA903X |
@@ -177,13 +176,6 @@ config BATTERY_DA9030 | |||
177 | Say Y here to enable support for batteries charger integrated into | 176 | Say Y here to enable support for batteries charger integrated into |
178 | DA9030 PMIC. | 177 | DA9030 PMIC. |
179 | 178 | ||
180 | config BATTERY_DA9052 | ||
181 | tristate "Dialog DA9052 Battery" | ||
182 | depends on PMIC_DA9052 | ||
183 | help | ||
184 | Say Y here to enable support for batteries charger integrated into | ||
185 | DA9052 PMIC. | ||
186 | |||
187 | config BATTERY_MAX17040 | 179 | config BATTERY_MAX17040 |
188 | tristate "Maxim MAX17040 Fuel Gauge" | 180 | tristate "Maxim MAX17040 Fuel Gauge" |
189 | depends on I2C | 181 | depends on I2C |
@@ -193,15 +185,23 @@ config BATTERY_MAX17040 | |||
193 | to operate with a single lithium cell | 185 | to operate with a single lithium cell |
194 | 186 | ||
195 | config BATTERY_MAX17042 | 187 | config BATTERY_MAX17042 |
196 | tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge" | 188 | tristate "Maxim MAX17042/8997/8966 Fuel Gauge" |
197 | depends on I2C | 189 | depends on I2C |
198 | help | 190 | help |
199 | MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries | 191 | MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries |
200 | in handheld and portable equipment. The MAX17042 is configured | 192 | in handheld and portable equipment. The MAX17042 is configured |
201 | to operate with a single lithium cell. MAX8997 and MAX8966 are | 193 | to operate with a single lithium cell. MAX8997 and MAX8966 are |
202 | multi-function devices that include fuel gauages that are compatible | 194 | multi-function devices that include fuel gauages that are compatible |
203 | with MAX17042. This driver also supports max17047/50 chips which are | 195 | with MAX17042. |
204 | improved version of max17042. | 196 | |
197 | config BATTERY_MAX17048 | ||
198 | tristate "Maxim MAX17048/17049 Fuel Gauge" | ||
199 | depends on I2C | ||
200 | help | ||
201 | MAX17048 is fuel-gauge systems for lithium-ion (Li+) batteries | ||
202 | in handheld and portable equipment. The MAX17048 is configured | ||
203 | to operate with a single lithium cell, and MAX17049 for two lithium | ||
204 | cells. | ||
205 | 205 | ||
206 | config BATTERY_Z2 | 206 | config BATTERY_Z2 |
207 | tristate "Z2 battery driver" | 207 | tristate "Z2 battery driver" |
@@ -215,12 +215,6 @@ config BATTERY_S3C_ADC | |||
215 | help | 215 | help |
216 | Say Y here to enable support for iPAQ h1930/h1940/rx1950 battery | 216 | Say Y here to enable support for iPAQ h1930/h1940/rx1950 battery |
217 | 217 | ||
218 | config CHARGER_88PM860X | ||
219 | tristate "Marvell 88PM860x Charger driver" | ||
220 | depends on MFD_88PM860X && BATTERY_88PM860X | ||
221 | help | ||
222 | Say Y here to enable charger for Marvell 88PM860x chip. | ||
223 | |||
224 | config CHARGER_PCF50633 | 218 | config CHARGER_PCF50633 |
225 | tristate "NXP PCF50633 MBC" | 219 | tristate "NXP PCF50633 MBC" |
226 | depends on MFD_PCF50633 | 220 | depends on MFD_PCF50633 |
@@ -245,13 +239,6 @@ config BATTERY_INTEL_MID | |||
245 | Say Y here to enable the battery driver on Intel MID | 239 | Say Y here to enable the battery driver on Intel MID |
246 | platforms. | 240 | platforms. |
247 | 241 | ||
248 | config BATTERY_RX51 | ||
249 | tristate "Nokia RX-51 (N900) battery driver" | ||
250 | depends on TWL4030_MADC | ||
251 | help | ||
252 | Say Y here to enable support for battery information on Nokia | ||
253 | RX-51, also known as N900 tablet. | ||
254 | |||
255 | config CHARGER_ISP1704 | 242 | config CHARGER_ISP1704 |
256 | tristate "ISP1704 USB Charger Detection" | 243 | tristate "ISP1704 USB Charger Detection" |
257 | depends on USB_OTG_UTILS | 244 | depends on USB_OTG_UTILS |
@@ -274,19 +261,6 @@ config CHARGER_TWL4030 | |||
274 | help | 261 | help |
275 | Say Y here to enable support for TWL4030 Battery Charge Interface. | 262 | Say Y here to enable support for TWL4030 Battery Charge Interface. |
276 | 263 | ||
277 | config CHARGER_LP8727 | ||
278 | tristate "TI/National Semiconductor LP8727 charger driver" | ||
279 | depends on I2C | ||
280 | help | ||
281 | Say Y here to enable support for LP8727 Charger Driver. | ||
282 | |||
283 | config CHARGER_LP8788 | ||
284 | tristate "TI LP8788 charger driver" | ||
285 | depends on MFD_LP8788 | ||
286 | depends on LP8788_ADC | ||
287 | help | ||
288 | Say Y to enable support for the LP8788 linear charger. | ||
289 | |||
290 | config CHARGER_GPIO | 264 | config CHARGER_GPIO |
291 | tristate "GPIO charger" | 265 | tristate "GPIO charger" |
292 | depends on GPIOLIB | 266 | depends on GPIOLIB |
@@ -297,17 +271,6 @@ config CHARGER_GPIO | |||
297 | This driver can be build as a module. If so, the module will be | 271 | This driver can be build as a module. If so, the module will be |
298 | called gpio-charger. | 272 | called gpio-charger. |
299 | 273 | ||
300 | config CHARGER_MANAGER | ||
301 | bool "Battery charger manager for multiple chargers" | ||
302 | depends on REGULATOR && RTC_CLASS | ||
303 | select EXTCON | ||
304 | help | ||
305 | Say Y to enable charger-manager support, which allows multiple | ||
306 | chargers attached to a battery and multiple batteries attached to a | ||
307 | system. The charger-manager also can monitor charging status in | ||
308 | runtime and in suspend-to-RAM by waking up the system periodically | ||
309 | with help of suspend_again support. | ||
310 | |||
311 | config CHARGER_MAX8997 | 274 | config CHARGER_MAX8997 |
312 | tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver" | 275 | tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver" |
313 | depends on MFD_MAX8997 && REGULATOR_MAX8997 | 276 | depends on MFD_MAX8997 && REGULATOR_MAX8997 |
@@ -322,32 +285,11 @@ config CHARGER_MAX8998 | |||
322 | Say Y to enable support for the battery charger control sysfs and | 285 | Say Y to enable support for the battery charger control sysfs and |
323 | platform data of MAX8998/LP3974 PMICs. | 286 | platform data of MAX8998/LP3974 PMICs. |
324 | 287 | ||
325 | config CHARGER_BQ2415X | ||
326 | tristate "TI BQ2415x battery charger driver" | ||
327 | depends on I2C | ||
328 | help | ||
329 | Say Y to enable support for the TI BQ2415x battery charger | ||
330 | PMICs. | ||
331 | |||
332 | You'll need this driver to charge batteries on e.g. Nokia | ||
333 | RX-51/N900. | ||
334 | |||
335 | config CHARGER_SMB347 | ||
336 | tristate "Summit Microelectronics SMB347 Battery Charger" | ||
337 | depends on I2C | ||
338 | select REGMAP_I2C | ||
339 | help | ||
340 | Say Y to include support for Summit Microelectronics SMB347 | ||
341 | Battery Charger. | ||
342 | |||
343 | config AB8500_BM | ||
344 | bool "AB8500 Battery Management Driver" | ||
345 | depends on AB8500_CORE && AB8500_GPADC | ||
346 | help | ||
347 | Say Y to include support for AB8500 battery management. | ||
348 | |||
349 | source "drivers/power/reset/Kconfig" | ||
350 | |||
351 | endif # POWER_SUPPLY | 288 | endif # POWER_SUPPLY |
352 | 289 | ||
353 | source "drivers/power/avs/Kconfig" | 290 | config TEGRA_BPC_MGMT |
291 | tristate "battery peak current management" | ||
292 | depends on ARCH_TEGRA | ||
293 | help | ||
294 | This driver reduces cpu frequency/voltage on gpio event from the | ||
295 | battery current monitor device. | ||
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 22c8913382c..b7ceb3f858c 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -5,7 +5,6 @@ power_supply-$(CONFIG_SYSFS) += power_supply_sysfs.o | |||
5 | power_supply-$(CONFIG_LEDS_TRIGGERS) += power_supply_leds.o | 5 | power_supply-$(CONFIG_LEDS_TRIGGERS) += power_supply_leds.o |
6 | 6 | ||
7 | obj-$(CONFIG_POWER_SUPPLY) += power_supply.o | 7 | obj-$(CONFIG_POWER_SUPPLY) += power_supply.o |
8 | obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o | ||
9 | 8 | ||
10 | obj-$(CONFIG_PDA_POWER) += pda_power.o | 9 | obj-$(CONFIG_PDA_POWER) += pda_power.o |
11 | obj-$(CONFIG_APM_POWER) += apm_power.o | 10 | obj-$(CONFIG_APM_POWER) += apm_power.o |
@@ -15,40 +14,33 @@ obj-$(CONFIG_WM831X_POWER) += wm831x_power.o | |||
15 | obj-$(CONFIG_WM8350_POWER) += wm8350_power.o | 14 | obj-$(CONFIG_WM8350_POWER) += wm8350_power.o |
16 | obj-$(CONFIG_TEST_POWER) += test_power.o | 15 | obj-$(CONFIG_TEST_POWER) += test_power.o |
17 | 16 | ||
18 | obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o | ||
19 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o | 17 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o |
20 | obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o | 18 | obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o |
21 | obj-$(CONFIG_BATTERY_DS2781) += ds2781_battery.o | ||
22 | obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o | 19 | obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o |
23 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o | 20 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o |
24 | obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o | 21 | obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o |
25 | obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o | 22 | obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o |
26 | obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o | 23 | obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o |
27 | obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o | 24 | obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o |
28 | obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o | 25 | obj-$(CONFIG_BATTERY_BQ20Z75) += bq20z75.o |
29 | obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o | 26 | obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o |
27 | obj-$(CONFIG_CHARGER_TPS8003X) += tps80031-charger.o | ||
28 | obj-$(CONFIG_BATTERY_GAUGE_TPS8003X) += tps80031_battery_gauge.o | ||
29 | obj-$(CONFIG_CHARGER_SMB349) += smb349-charger.o | ||
30 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o | 30 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o |
31 | obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o | ||
32 | obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o | 31 | obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o |
33 | obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o | 32 | obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o |
33 | obj-$(CONFIG_BATTERY_MAX17048) += max17048_battery.o | ||
34 | obj-$(CONFIG_BATTERY_Z2) += z2_battery.o | 34 | obj-$(CONFIG_BATTERY_Z2) += z2_battery.o |
35 | obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o | 35 | obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o |
36 | obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o | ||
37 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | 36 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o |
38 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o | 37 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o |
39 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o | 38 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o |
40 | obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o | ||
41 | obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o | ||
42 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o | 39 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o |
43 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o | 40 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o |
44 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o | 41 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o |
45 | obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o | ||
46 | obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o | ||
47 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o | 42 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o |
48 | obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o | ||
49 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o | 43 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o |
50 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o | 44 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o |
51 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o | 45 | obj-$(CONFIG_MAX8907C_CHARGER) += max8907c-charger.o |
52 | obj-$(CONFIG_POWER_AVS) += avs/ | 46 | obj-$(CONFIG_TEGRA_BPC_MGMT) += tegra_bpc_mgmt.o |
53 | obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o | ||
54 | obj-$(CONFIG_POWER_RESET) += reset/ | ||
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c deleted file mode 100644 index f034ae43e04..00000000000 --- a/drivers/power/ab8500_bmdata.c +++ /dev/null | |||
@@ -1,519 +0,0 @@ | |||
1 | #include <linux/export.h> | ||
2 | #include <linux/power_supply.h> | ||
3 | #include <linux/of.h> | ||
4 | #include <linux/mfd/abx500.h> | ||
5 | #include <linux/mfd/abx500/ab8500.h> | ||
6 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
7 | |||
8 | /* | ||
9 | * These are the defined batteries that uses a NTC and ID resistor placed | ||
10 | * inside of the battery pack. | ||
11 | * Note that the res_to_temp table must be strictly sorted by falling resistance | ||
12 | * values to work. | ||
13 | */ | ||
14 | static struct abx500_res_to_temp temp_tbl_A_thermistor[] = { | ||
15 | {-5, 53407}, | ||
16 | { 0, 48594}, | ||
17 | { 5, 43804}, | ||
18 | {10, 39188}, | ||
19 | {15, 34870}, | ||
20 | {20, 30933}, | ||
21 | {25, 27422}, | ||
22 | {30, 24347}, | ||
23 | {35, 21694}, | ||
24 | {40, 19431}, | ||
25 | {45, 17517}, | ||
26 | {50, 15908}, | ||
27 | {55, 14561}, | ||
28 | {60, 13437}, | ||
29 | {65, 12500}, | ||
30 | }; | ||
31 | |||
32 | static struct abx500_res_to_temp temp_tbl_B_thermistor[] = { | ||
33 | {-5, 200000}, | ||
34 | { 0, 159024}, | ||
35 | { 5, 151921}, | ||
36 | {10, 144300}, | ||
37 | {15, 136424}, | ||
38 | {20, 128565}, | ||
39 | {25, 120978}, | ||
40 | {30, 113875}, | ||
41 | {35, 107397}, | ||
42 | {40, 101629}, | ||
43 | {45, 96592}, | ||
44 | {50, 92253}, | ||
45 | {55, 88569}, | ||
46 | {60, 85461}, | ||
47 | {65, 82869}, | ||
48 | }; | ||
49 | |||
50 | static struct abx500_v_to_cap cap_tbl_A_thermistor[] = { | ||
51 | {4171, 100}, | ||
52 | {4114, 95}, | ||
53 | {4009, 83}, | ||
54 | {3947, 74}, | ||
55 | {3907, 67}, | ||
56 | {3863, 59}, | ||
57 | {3830, 56}, | ||
58 | {3813, 53}, | ||
59 | {3791, 46}, | ||
60 | {3771, 33}, | ||
61 | {3754, 25}, | ||
62 | {3735, 20}, | ||
63 | {3717, 17}, | ||
64 | {3681, 13}, | ||
65 | {3664, 8}, | ||
66 | {3651, 6}, | ||
67 | {3635, 5}, | ||
68 | {3560, 3}, | ||
69 | {3408, 1}, | ||
70 | {3247, 0}, | ||
71 | }; | ||
72 | |||
73 | static struct abx500_v_to_cap cap_tbl_B_thermistor[] = { | ||
74 | {4161, 100}, | ||
75 | {4124, 98}, | ||
76 | {4044, 90}, | ||
77 | {4003, 85}, | ||
78 | {3966, 80}, | ||
79 | {3933, 75}, | ||
80 | {3888, 67}, | ||
81 | {3849, 60}, | ||
82 | {3813, 55}, | ||
83 | {3787, 47}, | ||
84 | {3772, 30}, | ||
85 | {3751, 25}, | ||
86 | {3718, 20}, | ||
87 | {3681, 16}, | ||
88 | {3660, 14}, | ||
89 | {3589, 10}, | ||
90 | {3546, 7}, | ||
91 | {3495, 4}, | ||
92 | {3404, 2}, | ||
93 | {3250, 0}, | ||
94 | }; | ||
95 | |||
96 | static struct abx500_v_to_cap cap_tbl[] = { | ||
97 | {4186, 100}, | ||
98 | {4163, 99}, | ||
99 | {4114, 95}, | ||
100 | {4068, 90}, | ||
101 | {3990, 80}, | ||
102 | {3926, 70}, | ||
103 | {3898, 65}, | ||
104 | {3866, 60}, | ||
105 | {3833, 55}, | ||
106 | {3812, 50}, | ||
107 | {3787, 40}, | ||
108 | {3768, 30}, | ||
109 | {3747, 25}, | ||
110 | {3730, 20}, | ||
111 | {3705, 15}, | ||
112 | {3699, 14}, | ||
113 | {3684, 12}, | ||
114 | {3672, 9}, | ||
115 | {3657, 7}, | ||
116 | {3638, 6}, | ||
117 | {3556, 4}, | ||
118 | {3424, 2}, | ||
119 | {3317, 1}, | ||
120 | {3094, 0}, | ||
121 | }; | ||
122 | |||
123 | /* | ||
124 | * Note that the res_to_temp table must be strictly sorted by falling | ||
125 | * resistance values to work. | ||
126 | */ | ||
127 | static struct abx500_res_to_temp temp_tbl[] = { | ||
128 | {-5, 214834}, | ||
129 | { 0, 162943}, | ||
130 | { 5, 124820}, | ||
131 | {10, 96520}, | ||
132 | {15, 75306}, | ||
133 | {20, 59254}, | ||
134 | {25, 47000}, | ||
135 | {30, 37566}, | ||
136 | {35, 30245}, | ||
137 | {40, 24520}, | ||
138 | {45, 20010}, | ||
139 | {50, 16432}, | ||
140 | {55, 13576}, | ||
141 | {60, 11280}, | ||
142 | {65, 9425}, | ||
143 | }; | ||
144 | |||
145 | /* | ||
146 | * Note that the batres_vs_temp table must be strictly sorted by falling | ||
147 | * temperature values to work. | ||
148 | */ | ||
149 | static struct batres_vs_temp temp_to_batres_tbl_thermistor[] = { | ||
150 | { 40, 120}, | ||
151 | { 30, 135}, | ||
152 | { 20, 165}, | ||
153 | { 10, 230}, | ||
154 | { 00, 325}, | ||
155 | {-10, 445}, | ||
156 | {-20, 595}, | ||
157 | }; | ||
158 | |||
159 | /* | ||
160 | * Note that the batres_vs_temp table must be strictly sorted by falling | ||
161 | * temperature values to work. | ||
162 | */ | ||
163 | static struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = { | ||
164 | { 60, 300}, | ||
165 | { 30, 300}, | ||
166 | { 20, 300}, | ||
167 | { 10, 300}, | ||
168 | { 00, 300}, | ||
169 | {-10, 300}, | ||
170 | {-20, 300}, | ||
171 | }; | ||
172 | |||
173 | /* battery resistance table for LI ION 9100 battery */ | ||
174 | static struct batres_vs_temp temp_to_batres_tbl_9100[] = { | ||
175 | { 60, 180}, | ||
176 | { 30, 180}, | ||
177 | { 20, 180}, | ||
178 | { 10, 180}, | ||
179 | { 00, 180}, | ||
180 | {-10, 180}, | ||
181 | {-20, 180}, | ||
182 | }; | ||
183 | |||
184 | static struct abx500_battery_type bat_type_thermistor[] = { | ||
185 | [BATTERY_UNKNOWN] = { | ||
186 | /* First element always represent the UNKNOWN battery */ | ||
187 | .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, | ||
188 | .resis_high = 0, | ||
189 | .resis_low = 0, | ||
190 | .battery_resistance = 300, | ||
191 | .charge_full_design = 612, | ||
192 | .nominal_voltage = 3700, | ||
193 | .termination_vol = 4050, | ||
194 | .termination_curr = 200, | ||
195 | .recharge_vol = 3990, | ||
196 | .normal_cur_lvl = 400, | ||
197 | .normal_vol_lvl = 4100, | ||
198 | .maint_a_cur_lvl = 400, | ||
199 | .maint_a_vol_lvl = 4050, | ||
200 | .maint_a_chg_timer_h = 60, | ||
201 | .maint_b_cur_lvl = 400, | ||
202 | .maint_b_vol_lvl = 4000, | ||
203 | .maint_b_chg_timer_h = 200, | ||
204 | .low_high_cur_lvl = 300, | ||
205 | .low_high_vol_lvl = 4000, | ||
206 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
207 | .r_to_t_tbl = temp_tbl, | ||
208 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
209 | .v_to_cap_tbl = cap_tbl, | ||
210 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
211 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
212 | }, | ||
213 | { | ||
214 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, | ||
215 | .resis_high = 53407, | ||
216 | .resis_low = 12500, | ||
217 | .battery_resistance = 300, | ||
218 | .charge_full_design = 900, | ||
219 | .nominal_voltage = 3600, | ||
220 | .termination_vol = 4150, | ||
221 | .termination_curr = 80, | ||
222 | .recharge_vol = 4130, | ||
223 | .normal_cur_lvl = 700, | ||
224 | .normal_vol_lvl = 4200, | ||
225 | .maint_a_cur_lvl = 600, | ||
226 | .maint_a_vol_lvl = 4150, | ||
227 | .maint_a_chg_timer_h = 60, | ||
228 | .maint_b_cur_lvl = 600, | ||
229 | .maint_b_vol_lvl = 4100, | ||
230 | .maint_b_chg_timer_h = 200, | ||
231 | .low_high_cur_lvl = 300, | ||
232 | .low_high_vol_lvl = 4000, | ||
233 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor), | ||
234 | .r_to_t_tbl = temp_tbl_A_thermistor, | ||
235 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor), | ||
236 | .v_to_cap_tbl = cap_tbl_A_thermistor, | ||
237 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
238 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
239 | |||
240 | }, | ||
241 | { | ||
242 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, | ||
243 | .resis_high = 200000, | ||
244 | .resis_low = 82869, | ||
245 | .battery_resistance = 300, | ||
246 | .charge_full_design = 900, | ||
247 | .nominal_voltage = 3600, | ||
248 | .termination_vol = 4150, | ||
249 | .termination_curr = 80, | ||
250 | .recharge_vol = 4130, | ||
251 | .normal_cur_lvl = 700, | ||
252 | .normal_vol_lvl = 4200, | ||
253 | .maint_a_cur_lvl = 600, | ||
254 | .maint_a_vol_lvl = 4150, | ||
255 | .maint_a_chg_timer_h = 60, | ||
256 | .maint_b_cur_lvl = 600, | ||
257 | .maint_b_vol_lvl = 4100, | ||
258 | .maint_b_chg_timer_h = 200, | ||
259 | .low_high_cur_lvl = 300, | ||
260 | .low_high_vol_lvl = 4000, | ||
261 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor), | ||
262 | .r_to_t_tbl = temp_tbl_B_thermistor, | ||
263 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor), | ||
264 | .v_to_cap_tbl = cap_tbl_B_thermistor, | ||
265 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
266 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
267 | }, | ||
268 | }; | ||
269 | |||
270 | static struct abx500_battery_type bat_type_ext_thermistor[] = { | ||
271 | [BATTERY_UNKNOWN] = { | ||
272 | /* First element always represent the UNKNOWN battery */ | ||
273 | .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, | ||
274 | .resis_high = 0, | ||
275 | .resis_low = 0, | ||
276 | .battery_resistance = 300, | ||
277 | .charge_full_design = 612, | ||
278 | .nominal_voltage = 3700, | ||
279 | .termination_vol = 4050, | ||
280 | .termination_curr = 200, | ||
281 | .recharge_vol = 3990, | ||
282 | .normal_cur_lvl = 400, | ||
283 | .normal_vol_lvl = 4100, | ||
284 | .maint_a_cur_lvl = 400, | ||
285 | .maint_a_vol_lvl = 4050, | ||
286 | .maint_a_chg_timer_h = 60, | ||
287 | .maint_b_cur_lvl = 400, | ||
288 | .maint_b_vol_lvl = 4000, | ||
289 | .maint_b_chg_timer_h = 200, | ||
290 | .low_high_cur_lvl = 300, | ||
291 | .low_high_vol_lvl = 4000, | ||
292 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
293 | .r_to_t_tbl = temp_tbl, | ||
294 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
295 | .v_to_cap_tbl = cap_tbl, | ||
296 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
297 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
298 | }, | ||
299 | /* | ||
300 | * These are the batteries that doesn't have an internal NTC resistor to measure | ||
301 | * its temperature. The temperature in this case is measure with a NTC placed | ||
302 | * near the battery but on the PCB. | ||
303 | */ | ||
304 | { | ||
305 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, | ||
306 | .resis_high = 76000, | ||
307 | .resis_low = 53000, | ||
308 | .battery_resistance = 300, | ||
309 | .charge_full_design = 900, | ||
310 | .nominal_voltage = 3700, | ||
311 | .termination_vol = 4150, | ||
312 | .termination_curr = 100, | ||
313 | .recharge_vol = 4130, | ||
314 | .normal_cur_lvl = 700, | ||
315 | .normal_vol_lvl = 4200, | ||
316 | .maint_a_cur_lvl = 600, | ||
317 | .maint_a_vol_lvl = 4150, | ||
318 | .maint_a_chg_timer_h = 60, | ||
319 | .maint_b_cur_lvl = 600, | ||
320 | .maint_b_vol_lvl = 4100, | ||
321 | .maint_b_chg_timer_h = 200, | ||
322 | .low_high_cur_lvl = 300, | ||
323 | .low_high_vol_lvl = 4000, | ||
324 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
325 | .r_to_t_tbl = temp_tbl, | ||
326 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
327 | .v_to_cap_tbl = cap_tbl, | ||
328 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
329 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
330 | }, | ||
331 | { | ||
332 | .name = POWER_SUPPLY_TECHNOLOGY_LION, | ||
333 | .resis_high = 30000, | ||
334 | .resis_low = 10000, | ||
335 | .battery_resistance = 300, | ||
336 | .charge_full_design = 950, | ||
337 | .nominal_voltage = 3700, | ||
338 | .termination_vol = 4150, | ||
339 | .termination_curr = 100, | ||
340 | .recharge_vol = 4130, | ||
341 | .normal_cur_lvl = 700, | ||
342 | .normal_vol_lvl = 4200, | ||
343 | .maint_a_cur_lvl = 600, | ||
344 | .maint_a_vol_lvl = 4150, | ||
345 | .maint_a_chg_timer_h = 60, | ||
346 | .maint_b_cur_lvl = 600, | ||
347 | .maint_b_vol_lvl = 4100, | ||
348 | .maint_b_chg_timer_h = 200, | ||
349 | .low_high_cur_lvl = 300, | ||
350 | .low_high_vol_lvl = 4000, | ||
351 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
352 | .r_to_t_tbl = temp_tbl, | ||
353 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
354 | .v_to_cap_tbl = cap_tbl, | ||
355 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
356 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
357 | }, | ||
358 | { | ||
359 | .name = POWER_SUPPLY_TECHNOLOGY_LION, | ||
360 | .resis_high = 95000, | ||
361 | .resis_low = 76001, | ||
362 | .battery_resistance = 300, | ||
363 | .charge_full_design = 950, | ||
364 | .nominal_voltage = 3700, | ||
365 | .termination_vol = 4150, | ||
366 | .termination_curr = 100, | ||
367 | .recharge_vol = 4130, | ||
368 | .normal_cur_lvl = 700, | ||
369 | .normal_vol_lvl = 4200, | ||
370 | .maint_a_cur_lvl = 600, | ||
371 | .maint_a_vol_lvl = 4150, | ||
372 | .maint_a_chg_timer_h = 60, | ||
373 | .maint_b_cur_lvl = 600, | ||
374 | .maint_b_vol_lvl = 4100, | ||
375 | .maint_b_chg_timer_h = 200, | ||
376 | .low_high_cur_lvl = 300, | ||
377 | .low_high_vol_lvl = 4000, | ||
378 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
379 | .r_to_t_tbl = temp_tbl, | ||
380 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
381 | .v_to_cap_tbl = cap_tbl, | ||
382 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
383 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
384 | }, | ||
385 | }; | ||
386 | |||
387 | static const struct abx500_bm_capacity_levels cap_levels = { | ||
388 | .critical = 2, | ||
389 | .low = 10, | ||
390 | .normal = 70, | ||
391 | .high = 95, | ||
392 | .full = 100, | ||
393 | }; | ||
394 | |||
395 | static const struct abx500_fg_parameters fg = { | ||
396 | .recovery_sleep_timer = 10, | ||
397 | .recovery_total_time = 100, | ||
398 | .init_timer = 1, | ||
399 | .init_discard_time = 5, | ||
400 | .init_total_time = 40, | ||
401 | .high_curr_time = 60, | ||
402 | .accu_charging = 30, | ||
403 | .accu_high_curr = 30, | ||
404 | .high_curr_threshold = 50, | ||
405 | .lowbat_threshold = 3100, | ||
406 | .battok_falling_th_sel0 = 2860, | ||
407 | .battok_raising_th_sel1 = 2860, | ||
408 | .user_cap_limit = 15, | ||
409 | .maint_thres = 97, | ||
410 | }; | ||
411 | |||
412 | static const struct abx500_maxim_parameters maxi_params = { | ||
413 | .ena_maxi = true, | ||
414 | .chg_curr = 910, | ||
415 | .wait_cycles = 10, | ||
416 | .charger_curr_step = 100, | ||
417 | }; | ||
418 | |||
419 | static const struct abx500_bm_charger_parameters chg = { | ||
420 | .usb_volt_max = 5500, | ||
421 | .usb_curr_max = 1500, | ||
422 | .ac_volt_max = 7500, | ||
423 | .ac_curr_max = 1500, | ||
424 | }; | ||
425 | |||
426 | struct abx500_bm_data ab8500_bm_data = { | ||
427 | .temp_under = 3, | ||
428 | .temp_low = 8, | ||
429 | .temp_high = 43, | ||
430 | .temp_over = 48, | ||
431 | .main_safety_tmr_h = 4, | ||
432 | .temp_interval_chg = 20, | ||
433 | .temp_interval_nochg = 120, | ||
434 | .usb_safety_tmr_h = 4, | ||
435 | .bkup_bat_v = BUP_VCH_SEL_2P6V, | ||
436 | .bkup_bat_i = BUP_ICH_SEL_150UA, | ||
437 | .no_maintenance = false, | ||
438 | .adc_therm = ABx500_ADC_THERM_BATCTRL, | ||
439 | .chg_unknown_bat = false, | ||
440 | .enable_overshoot = false, | ||
441 | .fg_res = 100, | ||
442 | .cap_levels = &cap_levels, | ||
443 | .bat_type = bat_type_thermistor, | ||
444 | .n_btypes = 3, | ||
445 | .batt_id = 0, | ||
446 | .interval_charging = 5, | ||
447 | .interval_not_charging = 120, | ||
448 | .temp_hysteresis = 3, | ||
449 | .gnd_lift_resistance = 34, | ||
450 | .maxi = &maxi_params, | ||
451 | .chg_params = &chg, | ||
452 | .fg_params = &fg, | ||
453 | }; | ||
454 | |||
455 | int bmdevs_of_probe(struct device *dev, struct device_node *np, | ||
456 | struct abx500_bm_data **battery) | ||
457 | { | ||
458 | struct abx500_battery_type *btype; | ||
459 | struct device_node *np_bat_supply; | ||
460 | struct abx500_bm_data *bat; | ||
461 | const char *btech; | ||
462 | char bat_tech[8]; | ||
463 | int i, thermistor; | ||
464 | |||
465 | *battery = &ab8500_bm_data; | ||
466 | |||
467 | /* get phandle to 'battery-info' node */ | ||
468 | np_bat_supply = of_parse_phandle(np, "battery", 0); | ||
469 | if (!np_bat_supply) { | ||
470 | dev_err(dev, "missing property battery\n"); | ||
471 | return -EINVAL; | ||
472 | } | ||
473 | if (of_property_read_bool(np_bat_supply, | ||
474 | "thermistor-on-batctrl")) | ||
475 | thermistor = NTC_INTERNAL; | ||
476 | else | ||
477 | thermistor = NTC_EXTERNAL; | ||
478 | |||
479 | bat = *battery; | ||
480 | if (thermistor == NTC_EXTERNAL) { | ||
481 | bat->n_btypes = 4; | ||
482 | bat->bat_type = bat_type_ext_thermistor; | ||
483 | bat->adc_therm = ABx500_ADC_THERM_BATTEMP; | ||
484 | } | ||
485 | btech = of_get_property(np_bat_supply, | ||
486 | "stericsson,battery-type", NULL); | ||
487 | if (!btech) { | ||
488 | dev_warn(dev, "missing property battery-name/type\n"); | ||
489 | strcpy(bat_tech, "UNKNOWN"); | ||
490 | } else { | ||
491 | strcpy(bat_tech, btech); | ||
492 | } | ||
493 | |||
494 | if (strncmp(bat_tech, "LION", 4) == 0) { | ||
495 | bat->no_maintenance = true; | ||
496 | bat->chg_unknown_bat = true; | ||
497 | bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600; | ||
498 | bat->bat_type[BATTERY_UNKNOWN].termination_vol = 4150; | ||
499 | bat->bat_type[BATTERY_UNKNOWN].recharge_vol = 4130; | ||
500 | bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520; | ||
501 | bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200; | ||
502 | } | ||
503 | /* select the battery resolution table */ | ||
504 | for (i = 0; i < bat->n_btypes; ++i) { | ||
505 | btype = (bat->bat_type + i); | ||
506 | if (thermistor == NTC_EXTERNAL) { | ||
507 | btype->batres_tbl = | ||
508 | temp_to_batres_tbl_ext_thermistor; | ||
509 | } else if (strncmp(bat_tech, "LION", 4) == 0) { | ||
510 | btype->batres_tbl = | ||
511 | temp_to_batres_tbl_9100; | ||
512 | } else { | ||
513 | btype->batres_tbl = | ||
514 | temp_to_batres_tbl_thermistor; | ||
515 | } | ||
516 | } | ||
517 | of_node_put(np_bat_supply); | ||
518 | return 0; | ||
519 | } | ||
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c deleted file mode 100644 index 20e2a7d3ef4..00000000000 --- a/drivers/power/ab8500_btemp.c +++ /dev/null | |||
@@ -1,1132 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Battery temperature driver for AB8500 | ||
5 | * | ||
6 | * License Terms: GNU General Public License v2 | ||
7 | * Author: | ||
8 | * Johan Palsson <johan.palsson@stericsson.com> | ||
9 | * Karl Komierowski <karl.komierowski@stericsson.com> | ||
10 | * Arun R Murthy <arun.murthy@stericsson.com> | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/power_supply.h> | ||
21 | #include <linux/completion.h> | ||
22 | #include <linux/workqueue.h> | ||
23 | #include <linux/jiffies.h> | ||
24 | #include <linux/of.h> | ||
25 | #include <linux/mfd/core.h> | ||
26 | #include <linux/mfd/abx500.h> | ||
27 | #include <linux/mfd/abx500/ab8500.h> | ||
28 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
29 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
30 | |||
31 | #define VTVOUT_V 1800 | ||
32 | |||
33 | #define BTEMP_THERMAL_LOW_LIMIT -10 | ||
34 | #define BTEMP_THERMAL_MED_LIMIT 0 | ||
35 | #define BTEMP_THERMAL_HIGH_LIMIT_52 52 | ||
36 | #define BTEMP_THERMAL_HIGH_LIMIT_57 57 | ||
37 | #define BTEMP_THERMAL_HIGH_LIMIT_62 62 | ||
38 | |||
39 | #define BTEMP_BATCTRL_CURR_SRC_7UA 7 | ||
40 | #define BTEMP_BATCTRL_CURR_SRC_20UA 20 | ||
41 | |||
42 | #define to_ab8500_btemp_device_info(x) container_of((x), \ | ||
43 | struct ab8500_btemp, btemp_psy); | ||
44 | |||
45 | /** | ||
46 | * struct ab8500_btemp_interrupts - ab8500 interrupts | ||
47 | * @name: name of the interrupt | ||
48 | * @isr function pointer to the isr | ||
49 | */ | ||
50 | struct ab8500_btemp_interrupts { | ||
51 | char *name; | ||
52 | irqreturn_t (*isr)(int irq, void *data); | ||
53 | }; | ||
54 | |||
55 | struct ab8500_btemp_events { | ||
56 | bool batt_rem; | ||
57 | bool btemp_high; | ||
58 | bool btemp_medhigh; | ||
59 | bool btemp_lowmed; | ||
60 | bool btemp_low; | ||
61 | bool ac_conn; | ||
62 | bool usb_conn; | ||
63 | }; | ||
64 | |||
65 | struct ab8500_btemp_ranges { | ||
66 | int btemp_high_limit; | ||
67 | int btemp_med_limit; | ||
68 | int btemp_low_limit; | ||
69 | }; | ||
70 | |||
71 | /** | ||
72 | * struct ab8500_btemp - ab8500 BTEMP device information | ||
73 | * @dev: Pointer to the structure device | ||
74 | * @node: List of AB8500 BTEMPs, hence prepared for reentrance | ||
75 | * @curr_source: What current source we use, in uA | ||
76 | * @bat_temp: Battery temperature in degree Celcius | ||
77 | * @prev_bat_temp Last dispatched battery temperature | ||
78 | * @parent: Pointer to the struct ab8500 | ||
79 | * @gpadc: Pointer to the struct gpadc | ||
80 | * @fg: Pointer to the struct fg | ||
81 | * @bat: Pointer to the abx500_bm platform data | ||
82 | * @btemp_psy: Structure for BTEMP specific battery properties | ||
83 | * @events: Structure for information about events triggered | ||
84 | * @btemp_ranges: Battery temperature range structure | ||
85 | * @btemp_wq: Work queue for measuring the temperature periodically | ||
86 | * @btemp_periodic_work: Work for measuring the temperature periodically | ||
87 | */ | ||
88 | struct ab8500_btemp { | ||
89 | struct device *dev; | ||
90 | struct list_head node; | ||
91 | int curr_source; | ||
92 | int bat_temp; | ||
93 | int prev_bat_temp; | ||
94 | struct ab8500 *parent; | ||
95 | struct ab8500_gpadc *gpadc; | ||
96 | struct ab8500_fg *fg; | ||
97 | struct abx500_bm_data *bat; | ||
98 | struct power_supply btemp_psy; | ||
99 | struct ab8500_btemp_events events; | ||
100 | struct ab8500_btemp_ranges btemp_ranges; | ||
101 | struct workqueue_struct *btemp_wq; | ||
102 | struct delayed_work btemp_periodic_work; | ||
103 | }; | ||
104 | |||
105 | /* BTEMP power supply properties */ | ||
106 | static enum power_supply_property ab8500_btemp_props[] = { | ||
107 | POWER_SUPPLY_PROP_PRESENT, | ||
108 | POWER_SUPPLY_PROP_ONLINE, | ||
109 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
110 | POWER_SUPPLY_PROP_TEMP, | ||
111 | }; | ||
112 | |||
113 | static LIST_HEAD(ab8500_btemp_list); | ||
114 | |||
115 | /** | ||
116 | * ab8500_btemp_get() - returns a reference to the primary AB8500 BTEMP | ||
117 | * (i.e. the first BTEMP in the instance list) | ||
118 | */ | ||
119 | struct ab8500_btemp *ab8500_btemp_get(void) | ||
120 | { | ||
121 | struct ab8500_btemp *btemp; | ||
122 | btemp = list_first_entry(&ab8500_btemp_list, struct ab8500_btemp, node); | ||
123 | |||
124 | return btemp; | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance | ||
129 | * @di: pointer to the ab8500_btemp structure | ||
130 | * @v_batctrl: measured batctrl voltage | ||
131 | * @inst_curr: measured instant current | ||
132 | * | ||
133 | * This function returns the battery resistance that is | ||
134 | * derived from the BATCTRL voltage. | ||
135 | * Returns value in Ohms. | ||
136 | */ | ||
137 | static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di, | ||
138 | int v_batctrl, int inst_curr) | ||
139 | { | ||
140 | int rbs; | ||
141 | |||
142 | if (is_ab8500_1p1_or_earlier(di->parent)) { | ||
143 | /* | ||
144 | * For ABB cut1.0 and 1.1 BAT_CTRL is internally | ||
145 | * connected to 1.8V through a 450k resistor | ||
146 | */ | ||
147 | return (450000 * (v_batctrl)) / (1800 - v_batctrl); | ||
148 | } | ||
149 | |||
150 | if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL) { | ||
151 | /* | ||
152 | * If the battery has internal NTC, we use the current | ||
153 | * source to calculate the resistance, 7uA or 20uA | ||
154 | */ | ||
155 | rbs = (v_batctrl * 1000 | ||
156 | - di->bat->gnd_lift_resistance * inst_curr) | ||
157 | / di->curr_source; | ||
158 | } else { | ||
159 | /* | ||
160 | * BAT_CTRL is internally | ||
161 | * connected to 1.8V through a 80k resistor | ||
162 | */ | ||
163 | rbs = (80000 * (v_batctrl)) / (1800 - v_batctrl); | ||
164 | } | ||
165 | |||
166 | return rbs; | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * ab8500_btemp_read_batctrl_voltage() - measure batctrl voltage | ||
171 | * @di: pointer to the ab8500_btemp structure | ||
172 | * | ||
173 | * This function returns the voltage on BATCTRL. Returns value in mV. | ||
174 | */ | ||
175 | static int ab8500_btemp_read_batctrl_voltage(struct ab8500_btemp *di) | ||
176 | { | ||
177 | int vbtemp; | ||
178 | static int prev; | ||
179 | |||
180 | vbtemp = ab8500_gpadc_convert(di->gpadc, BAT_CTRL); | ||
181 | if (vbtemp < 0) { | ||
182 | dev_err(di->dev, | ||
183 | "%s gpadc conversion failed, using previous value", | ||
184 | __func__); | ||
185 | return prev; | ||
186 | } | ||
187 | prev = vbtemp; | ||
188 | return vbtemp; | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * ab8500_btemp_curr_source_enable() - enable/disable batctrl current source | ||
193 | * @di: pointer to the ab8500_btemp structure | ||
194 | * @enable: enable or disable the current source | ||
195 | * | ||
196 | * Enable or disable the current sources for the BatCtrl AD channel | ||
197 | */ | ||
198 | static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | ||
199 | bool enable) | ||
200 | { | ||
201 | int curr; | ||
202 | int ret = 0; | ||
203 | |||
204 | /* | ||
205 | * BATCTRL current sources are included on AB8500 cut2.0 | ||
206 | * and future versions | ||
207 | */ | ||
208 | if (is_ab8500_1p1_or_earlier(di->parent)) | ||
209 | return 0; | ||
210 | |||
211 | /* Only do this for batteries with internal NTC */ | ||
212 | if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { | ||
213 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA) | ||
214 | curr = BAT_CTRL_7U_ENA; | ||
215 | else | ||
216 | curr = BAT_CTRL_20U_ENA; | ||
217 | |||
218 | dev_dbg(di->dev, "Set BATCTRL %duA\n", di->curr_source); | ||
219 | |||
220 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
221 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
222 | FORCE_BAT_CTRL_CMP_HIGH, FORCE_BAT_CTRL_CMP_HIGH); | ||
223 | if (ret) { | ||
224 | dev_err(di->dev, "%s failed setting cmp_force\n", | ||
225 | __func__); | ||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * We have to wait one 32kHz cycle before enabling | ||
231 | * the current source, since ForceBatCtrlCmpHigh needs | ||
232 | * to be written in a separate cycle | ||
233 | */ | ||
234 | udelay(32); | ||
235 | |||
236 | ret = abx500_set_register_interruptible(di->dev, | ||
237 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
238 | FORCE_BAT_CTRL_CMP_HIGH | curr); | ||
239 | if (ret) { | ||
240 | dev_err(di->dev, "%s failed enabling current source\n", | ||
241 | __func__); | ||
242 | goto disable_curr_source; | ||
243 | } | ||
244 | } else if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { | ||
245 | dev_dbg(di->dev, "Disable BATCTRL curr source\n"); | ||
246 | |||
247 | /* Write 0 to the curr bits */ | ||
248 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
249 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
250 | BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA, | ||
251 | ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA)); | ||
252 | if (ret) { | ||
253 | dev_err(di->dev, "%s failed disabling current source\n", | ||
254 | __func__); | ||
255 | goto disable_curr_source; | ||
256 | } | ||
257 | |||
258 | /* Enable Pull-Up and comparator */ | ||
259 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
260 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
261 | BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA, | ||
262 | BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA); | ||
263 | if (ret) { | ||
264 | dev_err(di->dev, "%s failed enabling PU and comp\n", | ||
265 | __func__); | ||
266 | goto enable_pu_comp; | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * We have to wait one 32kHz cycle before disabling | ||
271 | * ForceBatCtrlCmpHigh since this needs to be written | ||
272 | * in a separate cycle | ||
273 | */ | ||
274 | udelay(32); | ||
275 | |||
276 | /* Disable 'force comparator' */ | ||
277 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
278 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
279 | FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH); | ||
280 | if (ret) { | ||
281 | dev_err(di->dev, "%s failed disabling force comp\n", | ||
282 | __func__); | ||
283 | goto disable_force_comp; | ||
284 | } | ||
285 | } | ||
286 | return ret; | ||
287 | |||
288 | /* | ||
289 | * We have to try unsetting FORCE_BAT_CTRL_CMP_HIGH one more time | ||
290 | * if we got an error above | ||
291 | */ | ||
292 | disable_curr_source: | ||
293 | /* Write 0 to the curr bits */ | ||
294 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
295 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
296 | BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA, | ||
297 | ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA)); | ||
298 | if (ret) { | ||
299 | dev_err(di->dev, "%s failed disabling current source\n", | ||
300 | __func__); | ||
301 | return ret; | ||
302 | } | ||
303 | enable_pu_comp: | ||
304 | /* Enable Pull-Up and comparator */ | ||
305 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
306 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
307 | BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA, | ||
308 | BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA); | ||
309 | if (ret) { | ||
310 | dev_err(di->dev, "%s failed enabling PU and comp\n", | ||
311 | __func__); | ||
312 | return ret; | ||
313 | } | ||
314 | |||
315 | disable_force_comp: | ||
316 | /* | ||
317 | * We have to wait one 32kHz cycle before disabling | ||
318 | * ForceBatCtrlCmpHigh since this needs to be written | ||
319 | * in a separate cycle | ||
320 | */ | ||
321 | udelay(32); | ||
322 | |||
323 | /* Disable 'force comparator' */ | ||
324 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
325 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
326 | FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH); | ||
327 | if (ret) { | ||
328 | dev_err(di->dev, "%s failed disabling force comp\n", | ||
329 | __func__); | ||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | return ret; | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * ab8500_btemp_get_batctrl_res() - get battery resistance | ||
338 | * @di: pointer to the ab8500_btemp structure | ||
339 | * | ||
340 | * This function returns the battery pack identification resistance. | ||
341 | * Returns value in Ohms. | ||
342 | */ | ||
343 | static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di) | ||
344 | { | ||
345 | int ret; | ||
346 | int batctrl = 0; | ||
347 | int res; | ||
348 | int inst_curr; | ||
349 | int i; | ||
350 | |||
351 | /* | ||
352 | * BATCTRL current sources are included on AB8500 cut2.0 | ||
353 | * and future versions | ||
354 | */ | ||
355 | ret = ab8500_btemp_curr_source_enable(di, true); | ||
356 | if (ret) { | ||
357 | dev_err(di->dev, "%s curr source enabled failed\n", __func__); | ||
358 | return ret; | ||
359 | } | ||
360 | |||
361 | if (!di->fg) | ||
362 | di->fg = ab8500_fg_get(); | ||
363 | if (!di->fg) { | ||
364 | dev_err(di->dev, "No fg found\n"); | ||
365 | return -EINVAL; | ||
366 | } | ||
367 | |||
368 | ret = ab8500_fg_inst_curr_start(di->fg); | ||
369 | |||
370 | if (ret) { | ||
371 | dev_err(di->dev, "Failed to start current measurement\n"); | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * Since there is no interrupt when current measurement is done, | ||
377 | * loop for over 250ms (250ms is one sample conversion time | ||
378 | * with 32.768 Khz RTC clock). Note that a stop time must be set | ||
379 | * since the ab8500_btemp_read_batctrl_voltage call can block and | ||
380 | * take an unknown amount of time to complete. | ||
381 | */ | ||
382 | i = 0; | ||
383 | |||
384 | do { | ||
385 | batctrl += ab8500_btemp_read_batctrl_voltage(di); | ||
386 | i++; | ||
387 | msleep(20); | ||
388 | } while (!ab8500_fg_inst_curr_done(di->fg)); | ||
389 | batctrl /= i; | ||
390 | |||
391 | ret = ab8500_fg_inst_curr_finalize(di->fg, &inst_curr); | ||
392 | if (ret) { | ||
393 | dev_err(di->dev, "Failed to finalize current measurement\n"); | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | res = ab8500_btemp_batctrl_volt_to_res(di, batctrl, inst_curr); | ||
398 | |||
399 | ret = ab8500_btemp_curr_source_enable(di, false); | ||
400 | if (ret) { | ||
401 | dev_err(di->dev, "%s curr source disable failed\n", __func__); | ||
402 | return ret; | ||
403 | } | ||
404 | |||
405 | dev_dbg(di->dev, "%s batctrl: %d res: %d inst_curr: %d samples: %d\n", | ||
406 | __func__, batctrl, res, inst_curr, i); | ||
407 | |||
408 | return res; | ||
409 | } | ||
410 | |||
411 | /** | ||
412 | * ab8500_btemp_res_to_temp() - resistance to temperature | ||
413 | * @di: pointer to the ab8500_btemp structure | ||
414 | * @tbl: pointer to the resiatance to temperature table | ||
415 | * @tbl_size: size of the resistance to temperature table | ||
416 | * @res: resistance to calculate the temperature from | ||
417 | * | ||
418 | * This function returns the battery temperature in degrees Celcius | ||
419 | * based on the NTC resistance. | ||
420 | */ | ||
421 | static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di, | ||
422 | const struct abx500_res_to_temp *tbl, int tbl_size, int res) | ||
423 | { | ||
424 | int i, temp; | ||
425 | /* | ||
426 | * Calculate the formula for the straight line | ||
427 | * Simple interpolation if we are within | ||
428 | * the resistance table limits, extrapolate | ||
429 | * if resistance is outside the limits. | ||
430 | */ | ||
431 | if (res > tbl[0].resist) | ||
432 | i = 0; | ||
433 | else if (res <= tbl[tbl_size - 1].resist) | ||
434 | i = tbl_size - 2; | ||
435 | else { | ||
436 | i = 0; | ||
437 | while (!(res <= tbl[i].resist && | ||
438 | res > tbl[i + 1].resist)) | ||
439 | i++; | ||
440 | } | ||
441 | |||
442 | temp = tbl[i].temp + ((tbl[i + 1].temp - tbl[i].temp) * | ||
443 | (res - tbl[i].resist)) / (tbl[i + 1].resist - tbl[i].resist); | ||
444 | return temp; | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * ab8500_btemp_measure_temp() - measure battery temperature | ||
449 | * @di: pointer to the ab8500_btemp structure | ||
450 | * | ||
451 | * Returns battery temperature (on success) else the previous temperature | ||
452 | */ | ||
453 | static int ab8500_btemp_measure_temp(struct ab8500_btemp *di) | ||
454 | { | ||
455 | int temp; | ||
456 | static int prev; | ||
457 | int rbat, rntc, vntc; | ||
458 | u8 id; | ||
459 | |||
460 | id = di->bat->batt_id; | ||
461 | |||
462 | if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && | ||
463 | id != BATTERY_UNKNOWN) { | ||
464 | |||
465 | rbat = ab8500_btemp_get_batctrl_res(di); | ||
466 | if (rbat < 0) { | ||
467 | dev_err(di->dev, "%s get batctrl res failed\n", | ||
468 | __func__); | ||
469 | /* | ||
470 | * Return out-of-range temperature so that | ||
471 | * charging is stopped | ||
472 | */ | ||
473 | return BTEMP_THERMAL_LOW_LIMIT; | ||
474 | } | ||
475 | |||
476 | temp = ab8500_btemp_res_to_temp(di, | ||
477 | di->bat->bat_type[id].r_to_t_tbl, | ||
478 | di->bat->bat_type[id].n_temp_tbl_elements, rbat); | ||
479 | } else { | ||
480 | vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL); | ||
481 | if (vntc < 0) { | ||
482 | dev_err(di->dev, | ||
483 | "%s gpadc conversion failed," | ||
484 | " using previous value\n", __func__); | ||
485 | return prev; | ||
486 | } | ||
487 | /* | ||
488 | * The PCB NTC is sourced from VTVOUT via a 230kOhm | ||
489 | * resistor. | ||
490 | */ | ||
491 | rntc = 230000 * vntc / (VTVOUT_V - vntc); | ||
492 | |||
493 | temp = ab8500_btemp_res_to_temp(di, | ||
494 | di->bat->bat_type[id].r_to_t_tbl, | ||
495 | di->bat->bat_type[id].n_temp_tbl_elements, rntc); | ||
496 | prev = temp; | ||
497 | } | ||
498 | dev_dbg(di->dev, "Battery temperature is %d\n", temp); | ||
499 | return temp; | ||
500 | } | ||
501 | |||
502 | /** | ||
503 | * ab8500_btemp_id() - Identify the connected battery | ||
504 | * @di: pointer to the ab8500_btemp structure | ||
505 | * | ||
506 | * This function will try to identify the battery by reading the ID | ||
507 | * resistor. Some brands use a combined ID resistor with a NTC resistor to | ||
508 | * both be able to identify and to read the temperature of it. | ||
509 | */ | ||
510 | static int ab8500_btemp_id(struct ab8500_btemp *di) | ||
511 | { | ||
512 | int res; | ||
513 | u8 i; | ||
514 | |||
515 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; | ||
516 | di->bat->batt_id = BATTERY_UNKNOWN; | ||
517 | |||
518 | res = ab8500_btemp_get_batctrl_res(di); | ||
519 | if (res < 0) { | ||
520 | dev_err(di->dev, "%s get batctrl res failed\n", __func__); | ||
521 | return -ENXIO; | ||
522 | } | ||
523 | |||
524 | /* BATTERY_UNKNOWN is defined on position 0, skip it! */ | ||
525 | for (i = BATTERY_UNKNOWN + 1; i < di->bat->n_btypes; i++) { | ||
526 | if ((res <= di->bat->bat_type[i].resis_high) && | ||
527 | (res >= di->bat->bat_type[i].resis_low)) { | ||
528 | dev_dbg(di->dev, "Battery detected on %s" | ||
529 | " low %d < res %d < high: %d" | ||
530 | " index: %d\n", | ||
531 | di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL ? | ||
532 | "BATCTRL" : "BATTEMP", | ||
533 | di->bat->bat_type[i].resis_low, res, | ||
534 | di->bat->bat_type[i].resis_high, i); | ||
535 | |||
536 | di->bat->batt_id = i; | ||
537 | break; | ||
538 | } | ||
539 | } | ||
540 | |||
541 | if (di->bat->batt_id == BATTERY_UNKNOWN) { | ||
542 | dev_warn(di->dev, "Battery identified as unknown" | ||
543 | ", resistance %d Ohm\n", res); | ||
544 | return -ENXIO; | ||
545 | } | ||
546 | |||
547 | /* | ||
548 | * We only have to change current source if the | ||
549 | * detected type is Type 1, else we use the 7uA source | ||
550 | */ | ||
551 | if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && | ||
552 | di->bat->batt_id == 1) { | ||
553 | dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); | ||
554 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA; | ||
555 | } | ||
556 | |||
557 | return di->bat->batt_id; | ||
558 | } | ||
559 | |||
560 | /** | ||
561 | * ab8500_btemp_periodic_work() - Measuring the temperature periodically | ||
562 | * @work: pointer to the work_struct structure | ||
563 | * | ||
564 | * Work function for measuring the temperature periodically | ||
565 | */ | ||
566 | static void ab8500_btemp_periodic_work(struct work_struct *work) | ||
567 | { | ||
568 | int interval; | ||
569 | struct ab8500_btemp *di = container_of(work, | ||
570 | struct ab8500_btemp, btemp_periodic_work.work); | ||
571 | |||
572 | di->bat_temp = ab8500_btemp_measure_temp(di); | ||
573 | |||
574 | if (di->bat_temp != di->prev_bat_temp) { | ||
575 | di->prev_bat_temp = di->bat_temp; | ||
576 | power_supply_changed(&di->btemp_psy); | ||
577 | } | ||
578 | |||
579 | if (di->events.ac_conn || di->events.usb_conn) | ||
580 | interval = di->bat->temp_interval_chg; | ||
581 | else | ||
582 | interval = di->bat->temp_interval_nochg; | ||
583 | |||
584 | /* Schedule a new measurement */ | ||
585 | queue_delayed_work(di->btemp_wq, | ||
586 | &di->btemp_periodic_work, | ||
587 | round_jiffies(interval * HZ)); | ||
588 | } | ||
589 | |||
590 | /** | ||
591 | * ab8500_btemp_batctrlindb_handler() - battery removal detected | ||
592 | * @irq: interrupt number | ||
593 | * @_di: void pointer that has to address of ab8500_btemp | ||
594 | * | ||
595 | * Returns IRQ status(IRQ_HANDLED) | ||
596 | */ | ||
597 | static irqreturn_t ab8500_btemp_batctrlindb_handler(int irq, void *_di) | ||
598 | { | ||
599 | struct ab8500_btemp *di = _di; | ||
600 | dev_err(di->dev, "Battery removal detected!\n"); | ||
601 | |||
602 | di->events.batt_rem = true; | ||
603 | power_supply_changed(&di->btemp_psy); | ||
604 | |||
605 | return IRQ_HANDLED; | ||
606 | } | ||
607 | |||
608 | /** | ||
609 | * ab8500_btemp_templow_handler() - battery temp lower than 10 degrees | ||
610 | * @irq: interrupt number | ||
611 | * @_di: void pointer that has to address of ab8500_btemp | ||
612 | * | ||
613 | * Returns IRQ status(IRQ_HANDLED) | ||
614 | */ | ||
615 | static irqreturn_t ab8500_btemp_templow_handler(int irq, void *_di) | ||
616 | { | ||
617 | struct ab8500_btemp *di = _di; | ||
618 | |||
619 | if (is_ab8500_2p0_or_earlier(di->parent)) { | ||
620 | dev_dbg(di->dev, "Ignore false btemp low irq" | ||
621 | " for ABB cut 1.0, 1.1 and 2.0\n"); | ||
622 | } else { | ||
623 | dev_crit(di->dev, "Battery temperature lower than -10deg c\n"); | ||
624 | |||
625 | di->events.btemp_low = true; | ||
626 | di->events.btemp_high = false; | ||
627 | di->events.btemp_medhigh = false; | ||
628 | di->events.btemp_lowmed = false; | ||
629 | power_supply_changed(&di->btemp_psy); | ||
630 | } | ||
631 | |||
632 | return IRQ_HANDLED; | ||
633 | } | ||
634 | |||
635 | /** | ||
636 | * ab8500_btemp_temphigh_handler() - battery temp higher than max temp | ||
637 | * @irq: interrupt number | ||
638 | * @_di: void pointer that has to address of ab8500_btemp | ||
639 | * | ||
640 | * Returns IRQ status(IRQ_HANDLED) | ||
641 | */ | ||
642 | static irqreturn_t ab8500_btemp_temphigh_handler(int irq, void *_di) | ||
643 | { | ||
644 | struct ab8500_btemp *di = _di; | ||
645 | |||
646 | dev_crit(di->dev, "Battery temperature is higher than MAX temp\n"); | ||
647 | |||
648 | di->events.btemp_high = true; | ||
649 | di->events.btemp_medhigh = false; | ||
650 | di->events.btemp_lowmed = false; | ||
651 | di->events.btemp_low = false; | ||
652 | power_supply_changed(&di->btemp_psy); | ||
653 | |||
654 | return IRQ_HANDLED; | ||
655 | } | ||
656 | |||
657 | /** | ||
658 | * ab8500_btemp_lowmed_handler() - battery temp between low and medium | ||
659 | * @irq: interrupt number | ||
660 | * @_di: void pointer that has to address of ab8500_btemp | ||
661 | * | ||
662 | * Returns IRQ status(IRQ_HANDLED) | ||
663 | */ | ||
664 | static irqreturn_t ab8500_btemp_lowmed_handler(int irq, void *_di) | ||
665 | { | ||
666 | struct ab8500_btemp *di = _di; | ||
667 | |||
668 | dev_dbg(di->dev, "Battery temperature is between low and medium\n"); | ||
669 | |||
670 | di->events.btemp_lowmed = true; | ||
671 | di->events.btemp_medhigh = false; | ||
672 | di->events.btemp_high = false; | ||
673 | di->events.btemp_low = false; | ||
674 | power_supply_changed(&di->btemp_psy); | ||
675 | |||
676 | return IRQ_HANDLED; | ||
677 | } | ||
678 | |||
679 | /** | ||
680 | * ab8500_btemp_medhigh_handler() - battery temp between medium and high | ||
681 | * @irq: interrupt number | ||
682 | * @_di: void pointer that has to address of ab8500_btemp | ||
683 | * | ||
684 | * Returns IRQ status(IRQ_HANDLED) | ||
685 | */ | ||
686 | static irqreturn_t ab8500_btemp_medhigh_handler(int irq, void *_di) | ||
687 | { | ||
688 | struct ab8500_btemp *di = _di; | ||
689 | |||
690 | dev_dbg(di->dev, "Battery temperature is between medium and high\n"); | ||
691 | |||
692 | di->events.btemp_medhigh = true; | ||
693 | di->events.btemp_lowmed = false; | ||
694 | di->events.btemp_high = false; | ||
695 | di->events.btemp_low = false; | ||
696 | power_supply_changed(&di->btemp_psy); | ||
697 | |||
698 | return IRQ_HANDLED; | ||
699 | } | ||
700 | |||
701 | /** | ||
702 | * ab8500_btemp_periodic() - Periodic temperature measurements | ||
703 | * @di: pointer to the ab8500_btemp structure | ||
704 | * @enable: enable or disable periodic temperature measurements | ||
705 | * | ||
706 | * Starts of stops periodic temperature measurements. Periodic measurements | ||
707 | * should only be done when a charger is connected. | ||
708 | */ | ||
709 | static void ab8500_btemp_periodic(struct ab8500_btemp *di, | ||
710 | bool enable) | ||
711 | { | ||
712 | dev_dbg(di->dev, "Enable periodic temperature measurements: %d\n", | ||
713 | enable); | ||
714 | /* | ||
715 | * Make sure a new measurement is done directly by cancelling | ||
716 | * any pending work | ||
717 | */ | ||
718 | cancel_delayed_work_sync(&di->btemp_periodic_work); | ||
719 | |||
720 | if (enable) | ||
721 | queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0); | ||
722 | } | ||
723 | |||
724 | /** | ||
725 | * ab8500_btemp_get_temp() - get battery temperature | ||
726 | * @di: pointer to the ab8500_btemp structure | ||
727 | * | ||
728 | * Returns battery temperature | ||
729 | */ | ||
730 | static int ab8500_btemp_get_temp(struct ab8500_btemp *di) | ||
731 | { | ||
732 | int temp = 0; | ||
733 | |||
734 | /* | ||
735 | * The BTEMP events are not reliabe on AB8500 cut2.0 | ||
736 | * and prior versions | ||
737 | */ | ||
738 | if (is_ab8500_2p0_or_earlier(di->parent)) { | ||
739 | temp = di->bat_temp * 10; | ||
740 | } else { | ||
741 | if (di->events.btemp_low) { | ||
742 | if (temp > di->btemp_ranges.btemp_low_limit) | ||
743 | temp = di->btemp_ranges.btemp_low_limit; | ||
744 | else | ||
745 | temp = di->bat_temp * 10; | ||
746 | } else if (di->events.btemp_high) { | ||
747 | if (temp < di->btemp_ranges.btemp_high_limit) | ||
748 | temp = di->btemp_ranges.btemp_high_limit; | ||
749 | else | ||
750 | temp = di->bat_temp * 10; | ||
751 | } else if (di->events.btemp_lowmed) { | ||
752 | if (temp > di->btemp_ranges.btemp_med_limit) | ||
753 | temp = di->btemp_ranges.btemp_med_limit; | ||
754 | else | ||
755 | temp = di->bat_temp * 10; | ||
756 | } else if (di->events.btemp_medhigh) { | ||
757 | if (temp < di->btemp_ranges.btemp_med_limit) | ||
758 | temp = di->btemp_ranges.btemp_med_limit; | ||
759 | else | ||
760 | temp = di->bat_temp * 10; | ||
761 | } else | ||
762 | temp = di->bat_temp * 10; | ||
763 | } | ||
764 | return temp; | ||
765 | } | ||
766 | |||
767 | /** | ||
768 | * ab8500_btemp_get_batctrl_temp() - get the temperature | ||
769 | * @btemp: pointer to the btemp structure | ||
770 | * | ||
771 | * Returns the batctrl temperature in millidegrees | ||
772 | */ | ||
773 | int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp) | ||
774 | { | ||
775 | return btemp->bat_temp * 1000; | ||
776 | } | ||
777 | |||
778 | /** | ||
779 | * ab8500_btemp_get_property() - get the btemp properties | ||
780 | * @psy: pointer to the power_supply structure | ||
781 | * @psp: pointer to the power_supply_property structure | ||
782 | * @val: pointer to the power_supply_propval union | ||
783 | * | ||
784 | * This function gets called when an application tries to get the btemp | ||
785 | * properties by reading the sysfs files. | ||
786 | * online: presence of the battery | ||
787 | * present: presence of the battery | ||
788 | * technology: battery technology | ||
789 | * temp: battery temperature | ||
790 | * Returns error code in case of failure else 0(on success) | ||
791 | */ | ||
792 | static int ab8500_btemp_get_property(struct power_supply *psy, | ||
793 | enum power_supply_property psp, | ||
794 | union power_supply_propval *val) | ||
795 | { | ||
796 | struct ab8500_btemp *di; | ||
797 | |||
798 | di = to_ab8500_btemp_device_info(psy); | ||
799 | |||
800 | switch (psp) { | ||
801 | case POWER_SUPPLY_PROP_PRESENT: | ||
802 | case POWER_SUPPLY_PROP_ONLINE: | ||
803 | if (di->events.batt_rem) | ||
804 | val->intval = 0; | ||
805 | else | ||
806 | val->intval = 1; | ||
807 | break; | ||
808 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
809 | val->intval = di->bat->bat_type[di->bat->batt_id].name; | ||
810 | break; | ||
811 | case POWER_SUPPLY_PROP_TEMP: | ||
812 | val->intval = ab8500_btemp_get_temp(di); | ||
813 | break; | ||
814 | default: | ||
815 | return -EINVAL; | ||
816 | } | ||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data) | ||
821 | { | ||
822 | struct power_supply *psy; | ||
823 | struct power_supply *ext; | ||
824 | struct ab8500_btemp *di; | ||
825 | union power_supply_propval ret; | ||
826 | int i, j; | ||
827 | bool psy_found = false; | ||
828 | |||
829 | psy = (struct power_supply *)data; | ||
830 | ext = dev_get_drvdata(dev); | ||
831 | di = to_ab8500_btemp_device_info(psy); | ||
832 | |||
833 | /* | ||
834 | * For all psy where the name of your driver | ||
835 | * appears in any supplied_to | ||
836 | */ | ||
837 | for (i = 0; i < ext->num_supplicants; i++) { | ||
838 | if (!strcmp(ext->supplied_to[i], psy->name)) | ||
839 | psy_found = true; | ||
840 | } | ||
841 | |||
842 | if (!psy_found) | ||
843 | return 0; | ||
844 | |||
845 | /* Go through all properties for the psy */ | ||
846 | for (j = 0; j < ext->num_properties; j++) { | ||
847 | enum power_supply_property prop; | ||
848 | prop = ext->properties[j]; | ||
849 | |||
850 | if (ext->get_property(ext, prop, &ret)) | ||
851 | continue; | ||
852 | |||
853 | switch (prop) { | ||
854 | case POWER_SUPPLY_PROP_PRESENT: | ||
855 | switch (ext->type) { | ||
856 | case POWER_SUPPLY_TYPE_MAINS: | ||
857 | /* AC disconnected */ | ||
858 | if (!ret.intval && di->events.ac_conn) { | ||
859 | di->events.ac_conn = false; | ||
860 | } | ||
861 | /* AC connected */ | ||
862 | else if (ret.intval && !di->events.ac_conn) { | ||
863 | di->events.ac_conn = true; | ||
864 | if (!di->events.usb_conn) | ||
865 | ab8500_btemp_periodic(di, true); | ||
866 | } | ||
867 | break; | ||
868 | case POWER_SUPPLY_TYPE_USB: | ||
869 | /* USB disconnected */ | ||
870 | if (!ret.intval && di->events.usb_conn) { | ||
871 | di->events.usb_conn = false; | ||
872 | } | ||
873 | /* USB connected */ | ||
874 | else if (ret.intval && !di->events.usb_conn) { | ||
875 | di->events.usb_conn = true; | ||
876 | if (!di->events.ac_conn) | ||
877 | ab8500_btemp_periodic(di, true); | ||
878 | } | ||
879 | break; | ||
880 | default: | ||
881 | break; | ||
882 | } | ||
883 | break; | ||
884 | default: | ||
885 | break; | ||
886 | } | ||
887 | } | ||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | /** | ||
892 | * ab8500_btemp_external_power_changed() - callback for power supply changes | ||
893 | * @psy: pointer to the structure power_supply | ||
894 | * | ||
895 | * This function is pointing to the function pointer external_power_changed | ||
896 | * of the structure power_supply. | ||
897 | * This function gets executed when there is a change in the external power | ||
898 | * supply to the btemp. | ||
899 | */ | ||
900 | static void ab8500_btemp_external_power_changed(struct power_supply *psy) | ||
901 | { | ||
902 | struct ab8500_btemp *di = to_ab8500_btemp_device_info(psy); | ||
903 | |||
904 | class_for_each_device(power_supply_class, NULL, | ||
905 | &di->btemp_psy, ab8500_btemp_get_ext_psy_data); | ||
906 | } | ||
907 | |||
908 | /* ab8500 btemp driver interrupts and their respective isr */ | ||
909 | static struct ab8500_btemp_interrupts ab8500_btemp_irq[] = { | ||
910 | {"BAT_CTRL_INDB", ab8500_btemp_batctrlindb_handler}, | ||
911 | {"BTEMP_LOW", ab8500_btemp_templow_handler}, | ||
912 | {"BTEMP_HIGH", ab8500_btemp_temphigh_handler}, | ||
913 | {"BTEMP_LOW_MEDIUM", ab8500_btemp_lowmed_handler}, | ||
914 | {"BTEMP_MEDIUM_HIGH", ab8500_btemp_medhigh_handler}, | ||
915 | }; | ||
916 | |||
917 | #if defined(CONFIG_PM) | ||
918 | static int ab8500_btemp_resume(struct platform_device *pdev) | ||
919 | { | ||
920 | struct ab8500_btemp *di = platform_get_drvdata(pdev); | ||
921 | |||
922 | ab8500_btemp_periodic(di, true); | ||
923 | |||
924 | return 0; | ||
925 | } | ||
926 | |||
927 | static int ab8500_btemp_suspend(struct platform_device *pdev, | ||
928 | pm_message_t state) | ||
929 | { | ||
930 | struct ab8500_btemp *di = platform_get_drvdata(pdev); | ||
931 | |||
932 | ab8500_btemp_periodic(di, false); | ||
933 | |||
934 | return 0; | ||
935 | } | ||
936 | #else | ||
937 | #define ab8500_btemp_suspend NULL | ||
938 | #define ab8500_btemp_resume NULL | ||
939 | #endif | ||
940 | |||
941 | static int ab8500_btemp_remove(struct platform_device *pdev) | ||
942 | { | ||
943 | struct ab8500_btemp *di = platform_get_drvdata(pdev); | ||
944 | int i, irq; | ||
945 | |||
946 | /* Disable interrupts */ | ||
947 | for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { | ||
948 | irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); | ||
949 | free_irq(irq, di); | ||
950 | } | ||
951 | |||
952 | /* Delete the work queue */ | ||
953 | destroy_workqueue(di->btemp_wq); | ||
954 | |||
955 | flush_scheduled_work(); | ||
956 | power_supply_unregister(&di->btemp_psy); | ||
957 | platform_set_drvdata(pdev, NULL); | ||
958 | |||
959 | return 0; | ||
960 | } | ||
961 | |||
962 | static char *supply_interface[] = { | ||
963 | "ab8500_chargalg", | ||
964 | "ab8500_fg", | ||
965 | }; | ||
966 | |||
967 | static int ab8500_btemp_probe(struct platform_device *pdev) | ||
968 | { | ||
969 | struct device_node *np = pdev->dev.of_node; | ||
970 | struct ab8500_btemp *di; | ||
971 | int irq, i, ret = 0; | ||
972 | u8 val; | ||
973 | |||
974 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); | ||
975 | if (!di) { | ||
976 | dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__); | ||
977 | return -ENOMEM; | ||
978 | } | ||
979 | di->bat = pdev->mfd_cell->platform_data; | ||
980 | if (!di->bat) { | ||
981 | if (np) { | ||
982 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | ||
983 | if (ret) { | ||
984 | dev_err(&pdev->dev, | ||
985 | "failed to get battery information\n"); | ||
986 | return ret; | ||
987 | } | ||
988 | } else { | ||
989 | dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n"); | ||
990 | return -EINVAL; | ||
991 | } | ||
992 | } else { | ||
993 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
994 | } | ||
995 | |||
996 | /* get parent data */ | ||
997 | di->dev = &pdev->dev; | ||
998 | di->parent = dev_get_drvdata(pdev->dev.parent); | ||
999 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
1000 | |||
1001 | /* BTEMP supply */ | ||
1002 | di->btemp_psy.name = "ab8500_btemp"; | ||
1003 | di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; | ||
1004 | di->btemp_psy.properties = ab8500_btemp_props; | ||
1005 | di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props); | ||
1006 | di->btemp_psy.get_property = ab8500_btemp_get_property; | ||
1007 | di->btemp_psy.supplied_to = supply_interface; | ||
1008 | di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface); | ||
1009 | di->btemp_psy.external_power_changed = | ||
1010 | ab8500_btemp_external_power_changed; | ||
1011 | |||
1012 | |||
1013 | /* Create a work queue for the btemp */ | ||
1014 | di->btemp_wq = | ||
1015 | create_singlethread_workqueue("ab8500_btemp_wq"); | ||
1016 | if (di->btemp_wq == NULL) { | ||
1017 | dev_err(di->dev, "failed to create work queue\n"); | ||
1018 | return -ENOMEM; | ||
1019 | } | ||
1020 | |||
1021 | /* Init work for measuring temperature periodically */ | ||
1022 | INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, | ||
1023 | ab8500_btemp_periodic_work); | ||
1024 | |||
1025 | /* Identify the battery */ | ||
1026 | if (ab8500_btemp_id(di) < 0) | ||
1027 | dev_warn(di->dev, "failed to identify the battery\n"); | ||
1028 | |||
1029 | /* Set BTEMP thermal limits. Low and Med are fixed */ | ||
1030 | di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT; | ||
1031 | di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT; | ||
1032 | |||
1033 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
1034 | AB8500_BTEMP_HIGH_TH, &val); | ||
1035 | if (ret < 0) { | ||
1036 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
1037 | goto free_btemp_wq; | ||
1038 | } | ||
1039 | switch (val) { | ||
1040 | case BTEMP_HIGH_TH_57_0: | ||
1041 | case BTEMP_HIGH_TH_57_1: | ||
1042 | di->btemp_ranges.btemp_high_limit = | ||
1043 | BTEMP_THERMAL_HIGH_LIMIT_57; | ||
1044 | break; | ||
1045 | case BTEMP_HIGH_TH_52: | ||
1046 | di->btemp_ranges.btemp_high_limit = | ||
1047 | BTEMP_THERMAL_HIGH_LIMIT_52; | ||
1048 | break; | ||
1049 | case BTEMP_HIGH_TH_62: | ||
1050 | di->btemp_ranges.btemp_high_limit = | ||
1051 | BTEMP_THERMAL_HIGH_LIMIT_62; | ||
1052 | break; | ||
1053 | } | ||
1054 | |||
1055 | /* Register BTEMP power supply class */ | ||
1056 | ret = power_supply_register(di->dev, &di->btemp_psy); | ||
1057 | if (ret) { | ||
1058 | dev_err(di->dev, "failed to register BTEMP psy\n"); | ||
1059 | goto free_btemp_wq; | ||
1060 | } | ||
1061 | |||
1062 | /* Register interrupts */ | ||
1063 | for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { | ||
1064 | irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); | ||
1065 | ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr, | ||
1066 | IRQF_SHARED | IRQF_NO_SUSPEND, | ||
1067 | ab8500_btemp_irq[i].name, di); | ||
1068 | |||
1069 | if (ret) { | ||
1070 | dev_err(di->dev, "failed to request %s IRQ %d: %d\n" | ||
1071 | , ab8500_btemp_irq[i].name, irq, ret); | ||
1072 | goto free_irq; | ||
1073 | } | ||
1074 | dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", | ||
1075 | ab8500_btemp_irq[i].name, irq, ret); | ||
1076 | } | ||
1077 | |||
1078 | platform_set_drvdata(pdev, di); | ||
1079 | |||
1080 | /* Kick off periodic temperature measurements */ | ||
1081 | ab8500_btemp_periodic(di, true); | ||
1082 | list_add_tail(&di->node, &ab8500_btemp_list); | ||
1083 | |||
1084 | return ret; | ||
1085 | |||
1086 | free_irq: | ||
1087 | power_supply_unregister(&di->btemp_psy); | ||
1088 | |||
1089 | /* We also have to free all successfully registered irqs */ | ||
1090 | for (i = i - 1; i >= 0; i--) { | ||
1091 | irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); | ||
1092 | free_irq(irq, di); | ||
1093 | } | ||
1094 | free_btemp_wq: | ||
1095 | destroy_workqueue(di->btemp_wq); | ||
1096 | return ret; | ||
1097 | } | ||
1098 | |||
1099 | static const struct of_device_id ab8500_btemp_match[] = { | ||
1100 | { .compatible = "stericsson,ab8500-btemp", }, | ||
1101 | { }, | ||
1102 | }; | ||
1103 | |||
1104 | static struct platform_driver ab8500_btemp_driver = { | ||
1105 | .probe = ab8500_btemp_probe, | ||
1106 | .remove = ab8500_btemp_remove, | ||
1107 | .suspend = ab8500_btemp_suspend, | ||
1108 | .resume = ab8500_btemp_resume, | ||
1109 | .driver = { | ||
1110 | .name = "ab8500-btemp", | ||
1111 | .owner = THIS_MODULE, | ||
1112 | .of_match_table = ab8500_btemp_match, | ||
1113 | }, | ||
1114 | }; | ||
1115 | |||
1116 | static int __init ab8500_btemp_init(void) | ||
1117 | { | ||
1118 | return platform_driver_register(&ab8500_btemp_driver); | ||
1119 | } | ||
1120 | |||
1121 | static void __exit ab8500_btemp_exit(void) | ||
1122 | { | ||
1123 | platform_driver_unregister(&ab8500_btemp_driver); | ||
1124 | } | ||
1125 | |||
1126 | subsys_initcall_sync(ab8500_btemp_init); | ||
1127 | module_exit(ab8500_btemp_exit); | ||
1128 | |||
1129 | MODULE_LICENSE("GPL v2"); | ||
1130 | MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); | ||
1131 | MODULE_ALIAS("platform:ab8500-btemp"); | ||
1132 | MODULE_DESCRIPTION("AB8500 battery temperature driver"); | ||
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c deleted file mode 100644 index 3be9c0ee3fc..00000000000 --- a/drivers/power/ab8500_charger.c +++ /dev/null | |||
@@ -1,2801 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Charger driver for AB8500 | ||
5 | * | ||
6 | * License Terms: GNU General Public License v2 | ||
7 | * Author: | ||
8 | * Johan Palsson <johan.palsson@stericsson.com> | ||
9 | * Karl Komierowski <karl.komierowski@stericsson.com> | ||
10 | * Arun R Murthy <arun.murthy@stericsson.com> | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/power_supply.h> | ||
21 | #include <linux/completion.h> | ||
22 | #include <linux/regulator/consumer.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | #include <linux/kobject.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/mfd/core.h> | ||
28 | #include <linux/mfd/abx500/ab8500.h> | ||
29 | #include <linux/mfd/abx500.h> | ||
30 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
31 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
32 | #include <linux/mfd/abx500/ux500_chargalg.h> | ||
33 | #include <linux/usb/otg.h> | ||
34 | |||
35 | /* Charger constants */ | ||
36 | #define NO_PW_CONN 0 | ||
37 | #define AC_PW_CONN 1 | ||
38 | #define USB_PW_CONN 2 | ||
39 | |||
40 | #define MAIN_WDOG_ENA 0x01 | ||
41 | #define MAIN_WDOG_KICK 0x02 | ||
42 | #define MAIN_WDOG_DIS 0x00 | ||
43 | #define CHARG_WD_KICK 0x01 | ||
44 | #define MAIN_CH_ENA 0x01 | ||
45 | #define MAIN_CH_NO_OVERSHOOT_ENA_N 0x02 | ||
46 | #define USB_CH_ENA 0x01 | ||
47 | #define USB_CHG_NO_OVERSHOOT_ENA_N 0x02 | ||
48 | #define MAIN_CH_DET 0x01 | ||
49 | #define MAIN_CH_CV_ON 0x04 | ||
50 | #define USB_CH_CV_ON 0x08 | ||
51 | #define VBUS_DET_DBNC100 0x02 | ||
52 | #define VBUS_DET_DBNC1 0x01 | ||
53 | #define OTP_ENABLE_WD 0x01 | ||
54 | |||
55 | #define MAIN_CH_INPUT_CURR_SHIFT 4 | ||
56 | #define VBUS_IN_CURR_LIM_SHIFT 4 | ||
57 | |||
58 | #define LED_INDICATOR_PWM_ENA 0x01 | ||
59 | #define LED_INDICATOR_PWM_DIS 0x00 | ||
60 | #define LED_IND_CUR_5MA 0x04 | ||
61 | #define LED_INDICATOR_PWM_DUTY_252_256 0xBF | ||
62 | |||
63 | /* HW failure constants */ | ||
64 | #define MAIN_CH_TH_PROT 0x02 | ||
65 | #define VBUS_CH_NOK 0x08 | ||
66 | #define USB_CH_TH_PROT 0x02 | ||
67 | #define VBUS_OVV_TH 0x01 | ||
68 | #define MAIN_CH_NOK 0x01 | ||
69 | #define VBUS_DET 0x80 | ||
70 | |||
71 | /* UsbLineStatus register bit masks */ | ||
72 | #define AB8500_USB_LINK_STATUS 0x78 | ||
73 | #define AB8500_STD_HOST_SUSP 0x18 | ||
74 | |||
75 | /* Watchdog timeout constant */ | ||
76 | #define WD_TIMER 0x30 /* 4min */ | ||
77 | #define WD_KICK_INTERVAL (60 * HZ) | ||
78 | |||
79 | /* Lowest charger voltage is 3.39V -> 0x4E */ | ||
80 | #define LOW_VOLT_REG 0x4E | ||
81 | |||
82 | /* UsbLineStatus register - usb types */ | ||
83 | enum ab8500_charger_link_status { | ||
84 | USB_STAT_NOT_CONFIGURED, | ||
85 | USB_STAT_STD_HOST_NC, | ||
86 | USB_STAT_STD_HOST_C_NS, | ||
87 | USB_STAT_STD_HOST_C_S, | ||
88 | USB_STAT_HOST_CHG_NM, | ||
89 | USB_STAT_HOST_CHG_HS, | ||
90 | USB_STAT_HOST_CHG_HS_CHIRP, | ||
91 | USB_STAT_DEDICATED_CHG, | ||
92 | USB_STAT_ACA_RID_A, | ||
93 | USB_STAT_ACA_RID_B, | ||
94 | USB_STAT_ACA_RID_C_NM, | ||
95 | USB_STAT_ACA_RID_C_HS, | ||
96 | USB_STAT_ACA_RID_C_HS_CHIRP, | ||
97 | USB_STAT_HM_IDGND, | ||
98 | USB_STAT_RESERVED, | ||
99 | USB_STAT_NOT_VALID_LINK, | ||
100 | }; | ||
101 | |||
102 | enum ab8500_usb_state { | ||
103 | AB8500_BM_USB_STATE_RESET_HS, /* HighSpeed Reset */ | ||
104 | AB8500_BM_USB_STATE_RESET_FS, /* FullSpeed/LowSpeed Reset */ | ||
105 | AB8500_BM_USB_STATE_CONFIGURED, | ||
106 | AB8500_BM_USB_STATE_SUSPEND, | ||
107 | AB8500_BM_USB_STATE_RESUME, | ||
108 | AB8500_BM_USB_STATE_MAX, | ||
109 | }; | ||
110 | |||
111 | /* VBUS input current limits supported in AB8500 in mA */ | ||
112 | #define USB_CH_IP_CUR_LVL_0P05 50 | ||
113 | #define USB_CH_IP_CUR_LVL_0P09 98 | ||
114 | #define USB_CH_IP_CUR_LVL_0P19 193 | ||
115 | #define USB_CH_IP_CUR_LVL_0P29 290 | ||
116 | #define USB_CH_IP_CUR_LVL_0P38 380 | ||
117 | #define USB_CH_IP_CUR_LVL_0P45 450 | ||
118 | #define USB_CH_IP_CUR_LVL_0P5 500 | ||
119 | #define USB_CH_IP_CUR_LVL_0P6 600 | ||
120 | #define USB_CH_IP_CUR_LVL_0P7 700 | ||
121 | #define USB_CH_IP_CUR_LVL_0P8 800 | ||
122 | #define USB_CH_IP_CUR_LVL_0P9 900 | ||
123 | #define USB_CH_IP_CUR_LVL_1P0 1000 | ||
124 | #define USB_CH_IP_CUR_LVL_1P1 1100 | ||
125 | #define USB_CH_IP_CUR_LVL_1P3 1300 | ||
126 | #define USB_CH_IP_CUR_LVL_1P4 1400 | ||
127 | #define USB_CH_IP_CUR_LVL_1P5 1500 | ||
128 | |||
129 | #define VBAT_TRESH_IP_CUR_RED 3800 | ||
130 | |||
131 | #define to_ab8500_charger_usb_device_info(x) container_of((x), \ | ||
132 | struct ab8500_charger, usb_chg) | ||
133 | #define to_ab8500_charger_ac_device_info(x) container_of((x), \ | ||
134 | struct ab8500_charger, ac_chg) | ||
135 | |||
136 | /** | ||
137 | * struct ab8500_charger_interrupts - ab8500 interupts | ||
138 | * @name: name of the interrupt | ||
139 | * @isr function pointer to the isr | ||
140 | */ | ||
141 | struct ab8500_charger_interrupts { | ||
142 | char *name; | ||
143 | irqreturn_t (*isr)(int irq, void *data); | ||
144 | }; | ||
145 | |||
146 | struct ab8500_charger_info { | ||
147 | int charger_connected; | ||
148 | int charger_online; | ||
149 | int charger_voltage; | ||
150 | int cv_active; | ||
151 | bool wd_expired; | ||
152 | }; | ||
153 | |||
154 | struct ab8500_charger_event_flags { | ||
155 | bool mainextchnotok; | ||
156 | bool main_thermal_prot; | ||
157 | bool usb_thermal_prot; | ||
158 | bool vbus_ovv; | ||
159 | bool usbchargernotok; | ||
160 | bool chgwdexp; | ||
161 | bool vbus_collapse; | ||
162 | }; | ||
163 | |||
164 | struct ab8500_charger_usb_state { | ||
165 | bool usb_changed; | ||
166 | int usb_current; | ||
167 | enum ab8500_usb_state state; | ||
168 | spinlock_t usb_lock; | ||
169 | }; | ||
170 | |||
171 | /** | ||
172 | * struct ab8500_charger - ab8500 Charger device information | ||
173 | * @dev: Pointer to the structure device | ||
174 | * @max_usb_in_curr: Max USB charger input current | ||
175 | * @vbus_detected: VBUS detected | ||
176 | * @vbus_detected_start: | ||
177 | * VBUS detected during startup | ||
178 | * @ac_conn: This will be true when the AC charger has been plugged | ||
179 | * @vddadc_en_ac: Indicate if VDD ADC supply is enabled because AC | ||
180 | * charger is enabled | ||
181 | * @vddadc_en_usb: Indicate if VDD ADC supply is enabled because USB | ||
182 | * charger is enabled | ||
183 | * @vbat Battery voltage | ||
184 | * @old_vbat Previously measured battery voltage | ||
185 | * @autopower Indicate if we should have automatic pwron after pwrloss | ||
186 | * @autopower_cfg platform specific power config support for "pwron after pwrloss" | ||
187 | * @parent: Pointer to the struct ab8500 | ||
188 | * @gpadc: Pointer to the struct gpadc | ||
189 | * @bat: Pointer to the abx500_bm platform data | ||
190 | * @flags: Structure for information about events triggered | ||
191 | * @usb_state: Structure for usb stack information | ||
192 | * @ac_chg: AC charger power supply | ||
193 | * @usb_chg: USB charger power supply | ||
194 | * @ac: Structure that holds the AC charger properties | ||
195 | * @usb: Structure that holds the USB charger properties | ||
196 | * @regu: Pointer to the struct regulator | ||
197 | * @charger_wq: Work queue for the IRQs and checking HW state | ||
198 | * @check_vbat_work Work for checking vbat threshold to adjust vbus current | ||
199 | * @check_hw_failure_work: Work for checking HW state | ||
200 | * @check_usbchgnotok_work: Work for checking USB charger not ok status | ||
201 | * @kick_wd_work: Work for kicking the charger watchdog in case | ||
202 | * of ABB rev 1.* due to the watchog logic bug | ||
203 | * @ac_work: Work for checking AC charger connection | ||
204 | * @detect_usb_type_work: Work for detecting the USB type connected | ||
205 | * @usb_link_status_work: Work for checking the new USB link status | ||
206 | * @usb_state_changed_work: Work for checking USB state | ||
207 | * @check_main_thermal_prot_work: | ||
208 | * Work for checking Main thermal status | ||
209 | * @check_usb_thermal_prot_work: | ||
210 | * Work for checking USB thermal status | ||
211 | */ | ||
212 | struct ab8500_charger { | ||
213 | struct device *dev; | ||
214 | int max_usb_in_curr; | ||
215 | bool vbus_detected; | ||
216 | bool vbus_detected_start; | ||
217 | bool ac_conn; | ||
218 | bool vddadc_en_ac; | ||
219 | bool vddadc_en_usb; | ||
220 | int vbat; | ||
221 | int old_vbat; | ||
222 | bool autopower; | ||
223 | bool autopower_cfg; | ||
224 | struct ab8500 *parent; | ||
225 | struct ab8500_gpadc *gpadc; | ||
226 | struct abx500_bm_data *bat; | ||
227 | struct ab8500_charger_event_flags flags; | ||
228 | struct ab8500_charger_usb_state usb_state; | ||
229 | struct ux500_charger ac_chg; | ||
230 | struct ux500_charger usb_chg; | ||
231 | struct ab8500_charger_info ac; | ||
232 | struct ab8500_charger_info usb; | ||
233 | struct regulator *regu; | ||
234 | struct workqueue_struct *charger_wq; | ||
235 | struct delayed_work check_vbat_work; | ||
236 | struct delayed_work check_hw_failure_work; | ||
237 | struct delayed_work check_usbchgnotok_work; | ||
238 | struct delayed_work kick_wd_work; | ||
239 | struct work_struct ac_work; | ||
240 | struct work_struct detect_usb_type_work; | ||
241 | struct work_struct usb_link_status_work; | ||
242 | struct work_struct usb_state_changed_work; | ||
243 | struct work_struct check_main_thermal_prot_work; | ||
244 | struct work_struct check_usb_thermal_prot_work; | ||
245 | struct usb_phy *usb_phy; | ||
246 | struct notifier_block nb; | ||
247 | }; | ||
248 | |||
249 | /* AC properties */ | ||
250 | static enum power_supply_property ab8500_charger_ac_props[] = { | ||
251 | POWER_SUPPLY_PROP_HEALTH, | ||
252 | POWER_SUPPLY_PROP_PRESENT, | ||
253 | POWER_SUPPLY_PROP_ONLINE, | ||
254 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
255 | POWER_SUPPLY_PROP_VOLTAGE_AVG, | ||
256 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
257 | }; | ||
258 | |||
259 | /* USB properties */ | ||
260 | static enum power_supply_property ab8500_charger_usb_props[] = { | ||
261 | POWER_SUPPLY_PROP_HEALTH, | ||
262 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
263 | POWER_SUPPLY_PROP_PRESENT, | ||
264 | POWER_SUPPLY_PROP_ONLINE, | ||
265 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
266 | POWER_SUPPLY_PROP_VOLTAGE_AVG, | ||
267 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
268 | }; | ||
269 | |||
270 | /** | ||
271 | * ab8500_power_loss_handling - set how we handle powerloss. | ||
272 | * @di: pointer to the ab8500_charger structure | ||
273 | * | ||
274 | * Magic nummbers are from STE HW department. | ||
275 | */ | ||
276 | static void ab8500_power_loss_handling(struct ab8500_charger *di) | ||
277 | { | ||
278 | u8 reg; | ||
279 | int ret; | ||
280 | |||
281 | dev_dbg(di->dev, "Autopower : %d\n", di->autopower); | ||
282 | |||
283 | /* read the autopower register */ | ||
284 | ret = abx500_get_register_interruptible(di->dev, 0x15, 0x00, ®); | ||
285 | if (ret) { | ||
286 | dev_err(di->dev, "%d write failed\n", __LINE__); | ||
287 | return; | ||
288 | } | ||
289 | |||
290 | /* enable the OPT emulation registers */ | ||
291 | ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x2); | ||
292 | if (ret) { | ||
293 | dev_err(di->dev, "%d write failed\n", __LINE__); | ||
294 | return; | ||
295 | } | ||
296 | |||
297 | if (di->autopower) | ||
298 | reg |= 0x8; | ||
299 | else | ||
300 | reg &= ~0x8; | ||
301 | |||
302 | /* write back the changed value to autopower reg */ | ||
303 | ret = abx500_set_register_interruptible(di->dev, 0x15, 0x00, reg); | ||
304 | if (ret) { | ||
305 | dev_err(di->dev, "%d write failed\n", __LINE__); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | /* disable the set OTP registers again */ | ||
310 | ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x0); | ||
311 | if (ret) { | ||
312 | dev_err(di->dev, "%d write failed\n", __LINE__); | ||
313 | return; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * ab8500_power_supply_changed - a wrapper with local extentions for | ||
319 | * power_supply_changed | ||
320 | * @di: pointer to the ab8500_charger structure | ||
321 | * @psy: pointer to power_supply_that have changed. | ||
322 | * | ||
323 | */ | ||
324 | static void ab8500_power_supply_changed(struct ab8500_charger *di, | ||
325 | struct power_supply *psy) | ||
326 | { | ||
327 | if (di->autopower_cfg) { | ||
328 | if (!di->usb.charger_connected && | ||
329 | !di->ac.charger_connected && | ||
330 | di->autopower) { | ||
331 | di->autopower = false; | ||
332 | ab8500_power_loss_handling(di); | ||
333 | } else if (!di->autopower && | ||
334 | (di->ac.charger_connected || | ||
335 | di->usb.charger_connected)) { | ||
336 | di->autopower = true; | ||
337 | ab8500_power_loss_handling(di); | ||
338 | } | ||
339 | } | ||
340 | power_supply_changed(psy); | ||
341 | } | ||
342 | |||
343 | static void ab8500_charger_set_usb_connected(struct ab8500_charger *di, | ||
344 | bool connected) | ||
345 | { | ||
346 | if (connected != di->usb.charger_connected) { | ||
347 | dev_dbg(di->dev, "USB connected:%i\n", connected); | ||
348 | di->usb.charger_connected = connected; | ||
349 | sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present"); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * ab8500_charger_get_ac_voltage() - get ac charger voltage | ||
355 | * @di: pointer to the ab8500_charger structure | ||
356 | * | ||
357 | * Returns ac charger voltage (on success) | ||
358 | */ | ||
359 | static int ab8500_charger_get_ac_voltage(struct ab8500_charger *di) | ||
360 | { | ||
361 | int vch; | ||
362 | |||
363 | /* Only measure voltage if the charger is connected */ | ||
364 | if (di->ac.charger_connected) { | ||
365 | vch = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_V); | ||
366 | if (vch < 0) | ||
367 | dev_err(di->dev, "%s gpadc conv failed,\n", __func__); | ||
368 | } else { | ||
369 | vch = 0; | ||
370 | } | ||
371 | return vch; | ||
372 | } | ||
373 | |||
374 | /** | ||
375 | * ab8500_charger_ac_cv() - check if the main charger is in CV mode | ||
376 | * @di: pointer to the ab8500_charger structure | ||
377 | * | ||
378 | * Returns ac charger CV mode (on success) else error code | ||
379 | */ | ||
380 | static int ab8500_charger_ac_cv(struct ab8500_charger *di) | ||
381 | { | ||
382 | u8 val; | ||
383 | int ret = 0; | ||
384 | |||
385 | /* Only check CV mode if the charger is online */ | ||
386 | if (di->ac.charger_online) { | ||
387 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
388 | AB8500_CH_STATUS1_REG, &val); | ||
389 | if (ret < 0) { | ||
390 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | if (val & MAIN_CH_CV_ON) | ||
395 | ret = 1; | ||
396 | else | ||
397 | ret = 0; | ||
398 | } | ||
399 | |||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | /** | ||
404 | * ab8500_charger_get_vbus_voltage() - get vbus voltage | ||
405 | * @di: pointer to the ab8500_charger structure | ||
406 | * | ||
407 | * This function returns the vbus voltage. | ||
408 | * Returns vbus voltage (on success) | ||
409 | */ | ||
410 | static int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di) | ||
411 | { | ||
412 | int vch; | ||
413 | |||
414 | /* Only measure voltage if the charger is connected */ | ||
415 | if (di->usb.charger_connected) { | ||
416 | vch = ab8500_gpadc_convert(di->gpadc, VBUS_V); | ||
417 | if (vch < 0) | ||
418 | dev_err(di->dev, "%s gpadc conv failed\n", __func__); | ||
419 | } else { | ||
420 | vch = 0; | ||
421 | } | ||
422 | return vch; | ||
423 | } | ||
424 | |||
425 | /** | ||
426 | * ab8500_charger_get_usb_current() - get usb charger current | ||
427 | * @di: pointer to the ab8500_charger structure | ||
428 | * | ||
429 | * This function returns the usb charger current. | ||
430 | * Returns usb current (on success) and error code on failure | ||
431 | */ | ||
432 | static int ab8500_charger_get_usb_current(struct ab8500_charger *di) | ||
433 | { | ||
434 | int ich; | ||
435 | |||
436 | /* Only measure current if the charger is online */ | ||
437 | if (di->usb.charger_online) { | ||
438 | ich = ab8500_gpadc_convert(di->gpadc, USB_CHARGER_C); | ||
439 | if (ich < 0) | ||
440 | dev_err(di->dev, "%s gpadc conv failed\n", __func__); | ||
441 | } else { | ||
442 | ich = 0; | ||
443 | } | ||
444 | return ich; | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * ab8500_charger_get_ac_current() - get ac charger current | ||
449 | * @di: pointer to the ab8500_charger structure | ||
450 | * | ||
451 | * This function returns the ac charger current. | ||
452 | * Returns ac current (on success) and error code on failure. | ||
453 | */ | ||
454 | static int ab8500_charger_get_ac_current(struct ab8500_charger *di) | ||
455 | { | ||
456 | int ich; | ||
457 | |||
458 | /* Only measure current if the charger is online */ | ||
459 | if (di->ac.charger_online) { | ||
460 | ich = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_C); | ||
461 | if (ich < 0) | ||
462 | dev_err(di->dev, "%s gpadc conv failed\n", __func__); | ||
463 | } else { | ||
464 | ich = 0; | ||
465 | } | ||
466 | return ich; | ||
467 | } | ||
468 | |||
469 | /** | ||
470 | * ab8500_charger_usb_cv() - check if the usb charger is in CV mode | ||
471 | * @di: pointer to the ab8500_charger structure | ||
472 | * | ||
473 | * Returns ac charger CV mode (on success) else error code | ||
474 | */ | ||
475 | static int ab8500_charger_usb_cv(struct ab8500_charger *di) | ||
476 | { | ||
477 | int ret; | ||
478 | u8 val; | ||
479 | |||
480 | /* Only check CV mode if the charger is online */ | ||
481 | if (di->usb.charger_online) { | ||
482 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
483 | AB8500_CH_USBCH_STAT1_REG, &val); | ||
484 | if (ret < 0) { | ||
485 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | if (val & USB_CH_CV_ON) | ||
490 | ret = 1; | ||
491 | else | ||
492 | ret = 0; | ||
493 | } else { | ||
494 | ret = 0; | ||
495 | } | ||
496 | |||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * ab8500_charger_detect_chargers() - Detect the connected chargers | ||
502 | * @di: pointer to the ab8500_charger structure | ||
503 | * | ||
504 | * Returns the type of charger connected. | ||
505 | * For USB it will not mean we can actually charge from it | ||
506 | * but that there is a USB cable connected that we have to | ||
507 | * identify. This is used during startup when we don't get | ||
508 | * interrupts of the charger detection | ||
509 | * | ||
510 | * Returns an integer value, that means, | ||
511 | * NO_PW_CONN no power supply is connected | ||
512 | * AC_PW_CONN if the AC power supply is connected | ||
513 | * USB_PW_CONN if the USB power supply is connected | ||
514 | * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected | ||
515 | */ | ||
516 | static int ab8500_charger_detect_chargers(struct ab8500_charger *di) | ||
517 | { | ||
518 | int result = NO_PW_CONN; | ||
519 | int ret; | ||
520 | u8 val; | ||
521 | |||
522 | /* Check for AC charger */ | ||
523 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
524 | AB8500_CH_STATUS1_REG, &val); | ||
525 | if (ret < 0) { | ||
526 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
527 | return ret; | ||
528 | } | ||
529 | |||
530 | if (val & MAIN_CH_DET) | ||
531 | result = AC_PW_CONN; | ||
532 | |||
533 | /* Check for USB charger */ | ||
534 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
535 | AB8500_CH_USBCH_STAT1_REG, &val); | ||
536 | if (ret < 0) { | ||
537 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
538 | return ret; | ||
539 | } | ||
540 | |||
541 | if ((val & VBUS_DET_DBNC1) && (val & VBUS_DET_DBNC100)) | ||
542 | result |= USB_PW_CONN; | ||
543 | |||
544 | return result; | ||
545 | } | ||
546 | |||
547 | /** | ||
548 | * ab8500_charger_max_usb_curr() - get the max curr for the USB type | ||
549 | * @di: pointer to the ab8500_charger structure | ||
550 | * @link_status: the identified USB type | ||
551 | * | ||
552 | * Get the maximum current that is allowed to be drawn from the host | ||
553 | * based on the USB type. | ||
554 | * Returns error code in case of failure else 0 on success | ||
555 | */ | ||
556 | static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | ||
557 | enum ab8500_charger_link_status link_status) | ||
558 | { | ||
559 | int ret = 0; | ||
560 | |||
561 | switch (link_status) { | ||
562 | case USB_STAT_STD_HOST_NC: | ||
563 | case USB_STAT_STD_HOST_C_NS: | ||
564 | case USB_STAT_STD_HOST_C_S: | ||
565 | dev_dbg(di->dev, "USB Type - Standard host is " | ||
566 | "detected through USB driver\n"); | ||
567 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; | ||
568 | break; | ||
569 | case USB_STAT_HOST_CHG_HS_CHIRP: | ||
570 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | ||
571 | break; | ||
572 | case USB_STAT_HOST_CHG_HS: | ||
573 | case USB_STAT_ACA_RID_C_HS: | ||
574 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9; | ||
575 | break; | ||
576 | case USB_STAT_ACA_RID_A: | ||
577 | /* | ||
578 | * Dedicated charger level minus maximum current accessory | ||
579 | * can consume (300mA). Closest level is 1100mA | ||
580 | */ | ||
581 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P1; | ||
582 | break; | ||
583 | case USB_STAT_ACA_RID_B: | ||
584 | /* | ||
585 | * Dedicated charger level minus 120mA (20mA for ACA and | ||
586 | * 100mA for potential accessory). Closest level is 1300mA | ||
587 | */ | ||
588 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3; | ||
589 | break; | ||
590 | case USB_STAT_DEDICATED_CHG: | ||
591 | case USB_STAT_HOST_CHG_NM: | ||
592 | case USB_STAT_ACA_RID_C_HS_CHIRP: | ||
593 | case USB_STAT_ACA_RID_C_NM: | ||
594 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; | ||
595 | break; | ||
596 | case USB_STAT_RESERVED: | ||
597 | /* | ||
598 | * This state is used to indicate that VBUS has dropped below | ||
599 | * the detection level 4 times in a row. This is due to the | ||
600 | * charger output current is set to high making the charger | ||
601 | * voltage collapse. This have to be propagated through to | ||
602 | * chargalg. This is done using the property | ||
603 | * POWER_SUPPLY_PROP_CURRENT_AVG = 1 | ||
604 | */ | ||
605 | di->flags.vbus_collapse = true; | ||
606 | dev_dbg(di->dev, "USB Type - USB_STAT_RESERVED " | ||
607 | "VBUS has collapsed\n"); | ||
608 | ret = -1; | ||
609 | break; | ||
610 | case USB_STAT_HM_IDGND: | ||
611 | case USB_STAT_NOT_CONFIGURED: | ||
612 | case USB_STAT_NOT_VALID_LINK: | ||
613 | dev_err(di->dev, "USB Type - Charging not allowed\n"); | ||
614 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | ||
615 | ret = -ENXIO; | ||
616 | break; | ||
617 | default: | ||
618 | dev_err(di->dev, "USB Type - Unknown\n"); | ||
619 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | ||
620 | ret = -ENXIO; | ||
621 | break; | ||
622 | }; | ||
623 | |||
624 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", | ||
625 | link_status, di->max_usb_in_curr); | ||
626 | |||
627 | return ret; | ||
628 | } | ||
629 | |||
630 | /** | ||
631 | * ab8500_charger_read_usb_type() - read the type of usb connected | ||
632 | * @di: pointer to the ab8500_charger structure | ||
633 | * | ||
634 | * Detect the type of the plugged USB | ||
635 | * Returns error code in case of failure else 0 on success | ||
636 | */ | ||
637 | static int ab8500_charger_read_usb_type(struct ab8500_charger *di) | ||
638 | { | ||
639 | int ret; | ||
640 | u8 val; | ||
641 | |||
642 | ret = abx500_get_register_interruptible(di->dev, | ||
643 | AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, &val); | ||
644 | if (ret < 0) { | ||
645 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
646 | return ret; | ||
647 | } | ||
648 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | ||
649 | AB8500_USB_LINE_STAT_REG, &val); | ||
650 | if (ret < 0) { | ||
651 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
652 | return ret; | ||
653 | } | ||
654 | |||
655 | /* get the USB type */ | ||
656 | val = (val & AB8500_USB_LINK_STATUS) >> 3; | ||
657 | ret = ab8500_charger_max_usb_curr(di, | ||
658 | (enum ab8500_charger_link_status) val); | ||
659 | |||
660 | return ret; | ||
661 | } | ||
662 | |||
663 | /** | ||
664 | * ab8500_charger_detect_usb_type() - get the type of usb connected | ||
665 | * @di: pointer to the ab8500_charger structure | ||
666 | * | ||
667 | * Detect the type of the plugged USB | ||
668 | * Returns error code in case of failure else 0 on success | ||
669 | */ | ||
670 | static int ab8500_charger_detect_usb_type(struct ab8500_charger *di) | ||
671 | { | ||
672 | int i, ret; | ||
673 | u8 val; | ||
674 | |||
675 | /* | ||
676 | * On getting the VBUS rising edge detect interrupt there | ||
677 | * is a 250ms delay after which the register UsbLineStatus | ||
678 | * is filled with valid data. | ||
679 | */ | ||
680 | for (i = 0; i < 10; i++) { | ||
681 | msleep(250); | ||
682 | ret = abx500_get_register_interruptible(di->dev, | ||
683 | AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, | ||
684 | &val); | ||
685 | if (ret < 0) { | ||
686 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
687 | return ret; | ||
688 | } | ||
689 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | ||
690 | AB8500_USB_LINE_STAT_REG, &val); | ||
691 | if (ret < 0) { | ||
692 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
693 | return ret; | ||
694 | } | ||
695 | /* | ||
696 | * Until the IT source register is read the UsbLineStatus | ||
697 | * register is not updated, hence doing the same | ||
698 | * Revisit this: | ||
699 | */ | ||
700 | |||
701 | /* get the USB type */ | ||
702 | val = (val & AB8500_USB_LINK_STATUS) >> 3; | ||
703 | if (val) | ||
704 | break; | ||
705 | } | ||
706 | ret = ab8500_charger_max_usb_curr(di, | ||
707 | (enum ab8500_charger_link_status) val); | ||
708 | |||
709 | return ret; | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | * This array maps the raw hex value to charger voltage used by the AB8500 | ||
714 | * Values taken from the UM0836 | ||
715 | */ | ||
716 | static int ab8500_charger_voltage_map[] = { | ||
717 | 3500 , | ||
718 | 3525 , | ||
719 | 3550 , | ||
720 | 3575 , | ||
721 | 3600 , | ||
722 | 3625 , | ||
723 | 3650 , | ||
724 | 3675 , | ||
725 | 3700 , | ||
726 | 3725 , | ||
727 | 3750 , | ||
728 | 3775 , | ||
729 | 3800 , | ||
730 | 3825 , | ||
731 | 3850 , | ||
732 | 3875 , | ||
733 | 3900 , | ||
734 | 3925 , | ||
735 | 3950 , | ||
736 | 3975 , | ||
737 | 4000 , | ||
738 | 4025 , | ||
739 | 4050 , | ||
740 | 4060 , | ||
741 | 4070 , | ||
742 | 4080 , | ||
743 | 4090 , | ||
744 | 4100 , | ||
745 | 4110 , | ||
746 | 4120 , | ||
747 | 4130 , | ||
748 | 4140 , | ||
749 | 4150 , | ||
750 | 4160 , | ||
751 | 4170 , | ||
752 | 4180 , | ||
753 | 4190 , | ||
754 | 4200 , | ||
755 | 4210 , | ||
756 | 4220 , | ||
757 | 4230 , | ||
758 | 4240 , | ||
759 | 4250 , | ||
760 | 4260 , | ||
761 | 4270 , | ||
762 | 4280 , | ||
763 | 4290 , | ||
764 | 4300 , | ||
765 | 4310 , | ||
766 | 4320 , | ||
767 | 4330 , | ||
768 | 4340 , | ||
769 | 4350 , | ||
770 | 4360 , | ||
771 | 4370 , | ||
772 | 4380 , | ||
773 | 4390 , | ||
774 | 4400 , | ||
775 | 4410 , | ||
776 | 4420 , | ||
777 | 4430 , | ||
778 | 4440 , | ||
779 | 4450 , | ||
780 | 4460 , | ||
781 | 4470 , | ||
782 | 4480 , | ||
783 | 4490 , | ||
784 | 4500 , | ||
785 | 4510 , | ||
786 | 4520 , | ||
787 | 4530 , | ||
788 | 4540 , | ||
789 | 4550 , | ||
790 | 4560 , | ||
791 | 4570 , | ||
792 | 4580 , | ||
793 | 4590 , | ||
794 | 4600 , | ||
795 | }; | ||
796 | |||
797 | /* | ||
798 | * This array maps the raw hex value to charger current used by the AB8500 | ||
799 | * Values taken from the UM0836 | ||
800 | */ | ||
801 | static int ab8500_charger_current_map[] = { | ||
802 | 100 , | ||
803 | 200 , | ||
804 | 300 , | ||
805 | 400 , | ||
806 | 500 , | ||
807 | 600 , | ||
808 | 700 , | ||
809 | 800 , | ||
810 | 900 , | ||
811 | 1000 , | ||
812 | 1100 , | ||
813 | 1200 , | ||
814 | 1300 , | ||
815 | 1400 , | ||
816 | 1500 , | ||
817 | }; | ||
818 | |||
819 | /* | ||
820 | * This array maps the raw hex value to VBUS input current used by the AB8500 | ||
821 | * Values taken from the UM0836 | ||
822 | */ | ||
823 | static int ab8500_charger_vbus_in_curr_map[] = { | ||
824 | USB_CH_IP_CUR_LVL_0P05, | ||
825 | USB_CH_IP_CUR_LVL_0P09, | ||
826 | USB_CH_IP_CUR_LVL_0P19, | ||
827 | USB_CH_IP_CUR_LVL_0P29, | ||
828 | USB_CH_IP_CUR_LVL_0P38, | ||
829 | USB_CH_IP_CUR_LVL_0P45, | ||
830 | USB_CH_IP_CUR_LVL_0P5, | ||
831 | USB_CH_IP_CUR_LVL_0P6, | ||
832 | USB_CH_IP_CUR_LVL_0P7, | ||
833 | USB_CH_IP_CUR_LVL_0P8, | ||
834 | USB_CH_IP_CUR_LVL_0P9, | ||
835 | USB_CH_IP_CUR_LVL_1P0, | ||
836 | USB_CH_IP_CUR_LVL_1P1, | ||
837 | USB_CH_IP_CUR_LVL_1P3, | ||
838 | USB_CH_IP_CUR_LVL_1P4, | ||
839 | USB_CH_IP_CUR_LVL_1P5, | ||
840 | }; | ||
841 | |||
842 | static int ab8500_voltage_to_regval(int voltage) | ||
843 | { | ||
844 | int i; | ||
845 | |||
846 | /* Special case for voltage below 3.5V */ | ||
847 | if (voltage < ab8500_charger_voltage_map[0]) | ||
848 | return LOW_VOLT_REG; | ||
849 | |||
850 | for (i = 1; i < ARRAY_SIZE(ab8500_charger_voltage_map); i++) { | ||
851 | if (voltage < ab8500_charger_voltage_map[i]) | ||
852 | return i - 1; | ||
853 | } | ||
854 | |||
855 | /* If not last element, return error */ | ||
856 | i = ARRAY_SIZE(ab8500_charger_voltage_map) - 1; | ||
857 | if (voltage == ab8500_charger_voltage_map[i]) | ||
858 | return i; | ||
859 | else | ||
860 | return -1; | ||
861 | } | ||
862 | |||
863 | static int ab8500_current_to_regval(int curr) | ||
864 | { | ||
865 | int i; | ||
866 | |||
867 | if (curr < ab8500_charger_current_map[0]) | ||
868 | return 0; | ||
869 | |||
870 | for (i = 0; i < ARRAY_SIZE(ab8500_charger_current_map); i++) { | ||
871 | if (curr < ab8500_charger_current_map[i]) | ||
872 | return i - 1; | ||
873 | } | ||
874 | |||
875 | /* If not last element, return error */ | ||
876 | i = ARRAY_SIZE(ab8500_charger_current_map) - 1; | ||
877 | if (curr == ab8500_charger_current_map[i]) | ||
878 | return i; | ||
879 | else | ||
880 | return -1; | ||
881 | } | ||
882 | |||
883 | static int ab8500_vbus_in_curr_to_regval(int curr) | ||
884 | { | ||
885 | int i; | ||
886 | |||
887 | if (curr < ab8500_charger_vbus_in_curr_map[0]) | ||
888 | return 0; | ||
889 | |||
890 | for (i = 0; i < ARRAY_SIZE(ab8500_charger_vbus_in_curr_map); i++) { | ||
891 | if (curr < ab8500_charger_vbus_in_curr_map[i]) | ||
892 | return i - 1; | ||
893 | } | ||
894 | |||
895 | /* If not last element, return error */ | ||
896 | i = ARRAY_SIZE(ab8500_charger_vbus_in_curr_map) - 1; | ||
897 | if (curr == ab8500_charger_vbus_in_curr_map[i]) | ||
898 | return i; | ||
899 | else | ||
900 | return -1; | ||
901 | } | ||
902 | |||
903 | /** | ||
904 | * ab8500_charger_get_usb_cur() - get usb current | ||
905 | * @di: pointer to the ab8500_charger structre | ||
906 | * | ||
907 | * The usb stack provides the maximum current that can be drawn from | ||
908 | * the standard usb host. This will be in mA. | ||
909 | * This function converts current in mA to a value that can be written | ||
910 | * to the register. Returns -1 if charging is not allowed | ||
911 | */ | ||
912 | static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) | ||
913 | { | ||
914 | switch (di->usb_state.usb_current) { | ||
915 | case 100: | ||
916 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; | ||
917 | break; | ||
918 | case 200: | ||
919 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P19; | ||
920 | break; | ||
921 | case 300: | ||
922 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P29; | ||
923 | break; | ||
924 | case 400: | ||
925 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P38; | ||
926 | break; | ||
927 | case 500: | ||
928 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | ||
929 | break; | ||
930 | default: | ||
931 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | ||
932 | return -1; | ||
933 | break; | ||
934 | }; | ||
935 | return 0; | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit | ||
940 | * @di: pointer to the ab8500_charger structure | ||
941 | * @ich_in: charger input current limit | ||
942 | * | ||
943 | * Sets the current that can be drawn from the USB host | ||
944 | * Returns error code in case of failure else 0(on success) | ||
945 | */ | ||
946 | static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, | ||
947 | int ich_in) | ||
948 | { | ||
949 | int ret; | ||
950 | int input_curr_index; | ||
951 | int min_value; | ||
952 | |||
953 | /* We should always use to lowest current limit */ | ||
954 | min_value = min(di->bat->chg_params->usb_curr_max, ich_in); | ||
955 | |||
956 | switch (min_value) { | ||
957 | case 100: | ||
958 | if (di->vbat < VBAT_TRESH_IP_CUR_RED) | ||
959 | min_value = USB_CH_IP_CUR_LVL_0P05; | ||
960 | break; | ||
961 | case 500: | ||
962 | if (di->vbat < VBAT_TRESH_IP_CUR_RED) | ||
963 | min_value = USB_CH_IP_CUR_LVL_0P45; | ||
964 | break; | ||
965 | default: | ||
966 | break; | ||
967 | } | ||
968 | |||
969 | input_curr_index = ab8500_vbus_in_curr_to_regval(min_value); | ||
970 | if (input_curr_index < 0) { | ||
971 | dev_err(di->dev, "VBUS input current limit too high\n"); | ||
972 | return -ENXIO; | ||
973 | } | ||
974 | |||
975 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
976 | AB8500_USBCH_IPT_CRNTLVL_REG, | ||
977 | input_curr_index << VBUS_IN_CURR_LIM_SHIFT); | ||
978 | if (ret) | ||
979 | dev_err(di->dev, "%s write failed\n", __func__); | ||
980 | |||
981 | return ret; | ||
982 | } | ||
983 | |||
984 | /** | ||
985 | * ab8500_charger_led_en() - turn on/off chargign led | ||
986 | * @di: pointer to the ab8500_charger structure | ||
987 | * @on: flag to turn on/off the chargign led | ||
988 | * | ||
989 | * Power ON/OFF charging LED indication | ||
990 | * Returns error code in case of failure else 0(on success) | ||
991 | */ | ||
992 | static int ab8500_charger_led_en(struct ab8500_charger *di, int on) | ||
993 | { | ||
994 | int ret; | ||
995 | |||
996 | if (on) { | ||
997 | /* Power ON charging LED indicator, set LED current to 5mA */ | ||
998 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
999 | AB8500_LED_INDICATOR_PWM_CTRL, | ||
1000 | (LED_IND_CUR_5MA | LED_INDICATOR_PWM_ENA)); | ||
1001 | if (ret) { | ||
1002 | dev_err(di->dev, "Power ON LED failed\n"); | ||
1003 | return ret; | ||
1004 | } | ||
1005 | /* LED indicator PWM duty cycle 252/256 */ | ||
1006 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1007 | AB8500_LED_INDICATOR_PWM_DUTY, | ||
1008 | LED_INDICATOR_PWM_DUTY_252_256); | ||
1009 | if (ret) { | ||
1010 | dev_err(di->dev, "Set LED PWM duty cycle failed\n"); | ||
1011 | return ret; | ||
1012 | } | ||
1013 | } else { | ||
1014 | /* Power off charging LED indicator */ | ||
1015 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1016 | AB8500_LED_INDICATOR_PWM_CTRL, | ||
1017 | LED_INDICATOR_PWM_DIS); | ||
1018 | if (ret) { | ||
1019 | dev_err(di->dev, "Power-off LED failed\n"); | ||
1020 | return ret; | ||
1021 | } | ||
1022 | } | ||
1023 | |||
1024 | return ret; | ||
1025 | } | ||
1026 | |||
1027 | /** | ||
1028 | * ab8500_charger_ac_en() - enable or disable ac charging | ||
1029 | * @di: pointer to the ab8500_charger structure | ||
1030 | * @enable: enable/disable flag | ||
1031 | * @vset: charging voltage | ||
1032 | * @iset: charging current | ||
1033 | * | ||
1034 | * Enable/Disable AC/Mains charging and turns on/off the charging led | ||
1035 | * respectively. | ||
1036 | **/ | ||
1037 | static int ab8500_charger_ac_en(struct ux500_charger *charger, | ||
1038 | int enable, int vset, int iset) | ||
1039 | { | ||
1040 | int ret; | ||
1041 | int volt_index; | ||
1042 | int curr_index; | ||
1043 | int input_curr_index; | ||
1044 | u8 overshoot = 0; | ||
1045 | |||
1046 | struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger); | ||
1047 | |||
1048 | if (enable) { | ||
1049 | /* Check if AC is connected */ | ||
1050 | if (!di->ac.charger_connected) { | ||
1051 | dev_err(di->dev, "AC charger not connected\n"); | ||
1052 | return -ENXIO; | ||
1053 | } | ||
1054 | |||
1055 | /* Enable AC charging */ | ||
1056 | dev_dbg(di->dev, "Enable AC: %dmV %dmA\n", vset, iset); | ||
1057 | |||
1058 | /* | ||
1059 | * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts | ||
1060 | * will be triggered everytime we enable the VDD ADC supply. | ||
1061 | * This will turn off charging for a short while. | ||
1062 | * It can be avoided by having the supply on when | ||
1063 | * there is a charger enabled. Normally the VDD ADC supply | ||
1064 | * is enabled everytime a GPADC conversion is triggered. We will | ||
1065 | * force it to be enabled from this driver to have | ||
1066 | * the GPADC module independant of the AB8500 chargers | ||
1067 | */ | ||
1068 | if (!di->vddadc_en_ac) { | ||
1069 | regulator_enable(di->regu); | ||
1070 | di->vddadc_en_ac = true; | ||
1071 | } | ||
1072 | |||
1073 | /* Check if the requested voltage or current is valid */ | ||
1074 | volt_index = ab8500_voltage_to_regval(vset); | ||
1075 | curr_index = ab8500_current_to_regval(iset); | ||
1076 | input_curr_index = ab8500_current_to_regval( | ||
1077 | di->bat->chg_params->ac_curr_max); | ||
1078 | if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) { | ||
1079 | dev_err(di->dev, | ||
1080 | "Charger voltage or current too high, " | ||
1081 | "charging not started\n"); | ||
1082 | return -ENXIO; | ||
1083 | } | ||
1084 | |||
1085 | /* ChVoltLevel: maximum battery charging voltage */ | ||
1086 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1087 | AB8500_CH_VOLT_LVL_REG, (u8) volt_index); | ||
1088 | if (ret) { | ||
1089 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1090 | return ret; | ||
1091 | } | ||
1092 | /* MainChInputCurr: current that can be drawn from the charger*/ | ||
1093 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1094 | AB8500_MCH_IPT_CURLVL_REG, | ||
1095 | input_curr_index << MAIN_CH_INPUT_CURR_SHIFT); | ||
1096 | if (ret) { | ||
1097 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1098 | return ret; | ||
1099 | } | ||
1100 | /* ChOutputCurentLevel: protected output current */ | ||
1101 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1102 | AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); | ||
1103 | if (ret) { | ||
1104 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1105 | return ret; | ||
1106 | } | ||
1107 | |||
1108 | /* Check if VBAT overshoot control should be enabled */ | ||
1109 | if (!di->bat->enable_overshoot) | ||
1110 | overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N; | ||
1111 | |||
1112 | /* Enable Main Charger */ | ||
1113 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1114 | AB8500_MCH_CTRL1, MAIN_CH_ENA | overshoot); | ||
1115 | if (ret) { | ||
1116 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1117 | return ret; | ||
1118 | } | ||
1119 | |||
1120 | /* Power on charging LED indication */ | ||
1121 | ret = ab8500_charger_led_en(di, true); | ||
1122 | if (ret < 0) | ||
1123 | dev_err(di->dev, "failed to enable LED\n"); | ||
1124 | |||
1125 | di->ac.charger_online = 1; | ||
1126 | } else { | ||
1127 | /* Disable AC charging */ | ||
1128 | if (is_ab8500_1p1_or_earlier(di->parent)) { | ||
1129 | /* | ||
1130 | * For ABB revision 1.0 and 1.1 there is a bug in the | ||
1131 | * watchdog logic. That means we have to continously | ||
1132 | * kick the charger watchdog even when no charger is | ||
1133 | * connected. This is only valid once the AC charger | ||
1134 | * has been enabled. This is a bug that is not handled | ||
1135 | * by the algorithm and the watchdog have to be kicked | ||
1136 | * by the charger driver when the AC charger | ||
1137 | * is disabled | ||
1138 | */ | ||
1139 | if (di->ac_conn) { | ||
1140 | queue_delayed_work(di->charger_wq, | ||
1141 | &di->kick_wd_work, | ||
1142 | round_jiffies(WD_KICK_INTERVAL)); | ||
1143 | } | ||
1144 | |||
1145 | /* | ||
1146 | * We can't turn off charging completely | ||
1147 | * due to a bug in AB8500 cut1. | ||
1148 | * If we do, charging will not start again. | ||
1149 | * That is why we set the lowest voltage | ||
1150 | * and current possible | ||
1151 | */ | ||
1152 | ret = abx500_set_register_interruptible(di->dev, | ||
1153 | AB8500_CHARGER, | ||
1154 | AB8500_CH_VOLT_LVL_REG, CH_VOL_LVL_3P5); | ||
1155 | if (ret) { | ||
1156 | dev_err(di->dev, | ||
1157 | "%s write failed\n", __func__); | ||
1158 | return ret; | ||
1159 | } | ||
1160 | |||
1161 | ret = abx500_set_register_interruptible(di->dev, | ||
1162 | AB8500_CHARGER, | ||
1163 | AB8500_CH_OPT_CRNTLVL_REG, CH_OP_CUR_LVL_0P1); | ||
1164 | if (ret) { | ||
1165 | dev_err(di->dev, | ||
1166 | "%s write failed\n", __func__); | ||
1167 | return ret; | ||
1168 | } | ||
1169 | } else { | ||
1170 | ret = abx500_set_register_interruptible(di->dev, | ||
1171 | AB8500_CHARGER, | ||
1172 | AB8500_MCH_CTRL1, 0); | ||
1173 | if (ret) { | ||
1174 | dev_err(di->dev, | ||
1175 | "%s write failed\n", __func__); | ||
1176 | return ret; | ||
1177 | } | ||
1178 | } | ||
1179 | |||
1180 | ret = ab8500_charger_led_en(di, false); | ||
1181 | if (ret < 0) | ||
1182 | dev_err(di->dev, "failed to disable LED\n"); | ||
1183 | |||
1184 | di->ac.charger_online = 0; | ||
1185 | di->ac.wd_expired = false; | ||
1186 | |||
1187 | /* Disable regulator if enabled */ | ||
1188 | if (di->vddadc_en_ac) { | ||
1189 | regulator_disable(di->regu); | ||
1190 | di->vddadc_en_ac = false; | ||
1191 | } | ||
1192 | |||
1193 | dev_dbg(di->dev, "%s Disabled AC charging\n", __func__); | ||
1194 | } | ||
1195 | ab8500_power_supply_changed(di, &di->ac_chg.psy); | ||
1196 | |||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1200 | /** | ||
1201 | * ab8500_charger_usb_en() - enable usb charging | ||
1202 | * @di: pointer to the ab8500_charger structure | ||
1203 | * @enable: enable/disable flag | ||
1204 | * @vset: charging voltage | ||
1205 | * @ich_out: charger output current | ||
1206 | * | ||
1207 | * Enable/Disable USB charging and turns on/off the charging led respectively. | ||
1208 | * Returns error code in case of failure else 0(on success) | ||
1209 | */ | ||
1210 | static int ab8500_charger_usb_en(struct ux500_charger *charger, | ||
1211 | int enable, int vset, int ich_out) | ||
1212 | { | ||
1213 | int ret; | ||
1214 | int volt_index; | ||
1215 | int curr_index; | ||
1216 | u8 overshoot = 0; | ||
1217 | |||
1218 | struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger); | ||
1219 | |||
1220 | if (enable) { | ||
1221 | /* Check if USB is connected */ | ||
1222 | if (!di->usb.charger_connected) { | ||
1223 | dev_err(di->dev, "USB charger not connected\n"); | ||
1224 | return -ENXIO; | ||
1225 | } | ||
1226 | |||
1227 | /* | ||
1228 | * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts | ||
1229 | * will be triggered everytime we enable the VDD ADC supply. | ||
1230 | * This will turn off charging for a short while. | ||
1231 | * It can be avoided by having the supply on when | ||
1232 | * there is a charger enabled. Normally the VDD ADC supply | ||
1233 | * is enabled everytime a GPADC conversion is triggered. We will | ||
1234 | * force it to be enabled from this driver to have | ||
1235 | * the GPADC module independant of the AB8500 chargers | ||
1236 | */ | ||
1237 | if (!di->vddadc_en_usb) { | ||
1238 | regulator_enable(di->regu); | ||
1239 | di->vddadc_en_usb = true; | ||
1240 | } | ||
1241 | |||
1242 | /* Enable USB charging */ | ||
1243 | dev_dbg(di->dev, "Enable USB: %dmV %dmA\n", vset, ich_out); | ||
1244 | |||
1245 | /* Check if the requested voltage or current is valid */ | ||
1246 | volt_index = ab8500_voltage_to_regval(vset); | ||
1247 | curr_index = ab8500_current_to_regval(ich_out); | ||
1248 | if (volt_index < 0 || curr_index < 0) { | ||
1249 | dev_err(di->dev, | ||
1250 | "Charger voltage or current too high, " | ||
1251 | "charging not started\n"); | ||
1252 | return -ENXIO; | ||
1253 | } | ||
1254 | |||
1255 | /* ChVoltLevel: max voltage upto which battery can be charged */ | ||
1256 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1257 | AB8500_CH_VOLT_LVL_REG, (u8) volt_index); | ||
1258 | if (ret) { | ||
1259 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1260 | return ret; | ||
1261 | } | ||
1262 | /* USBChInputCurr: current that can be drawn from the usb */ | ||
1263 | ret = ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | ||
1264 | if (ret) { | ||
1265 | dev_err(di->dev, "setting USBChInputCurr failed\n"); | ||
1266 | return ret; | ||
1267 | } | ||
1268 | /* ChOutputCurentLevel: protected output current */ | ||
1269 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1270 | AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); | ||
1271 | if (ret) { | ||
1272 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1273 | return ret; | ||
1274 | } | ||
1275 | /* Check if VBAT overshoot control should be enabled */ | ||
1276 | if (!di->bat->enable_overshoot) | ||
1277 | overshoot = USB_CHG_NO_OVERSHOOT_ENA_N; | ||
1278 | |||
1279 | /* Enable USB Charger */ | ||
1280 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1281 | AB8500_USBCH_CTRL1_REG, USB_CH_ENA | overshoot); | ||
1282 | if (ret) { | ||
1283 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1284 | return ret; | ||
1285 | } | ||
1286 | |||
1287 | /* If success power on charging LED indication */ | ||
1288 | ret = ab8500_charger_led_en(di, true); | ||
1289 | if (ret < 0) | ||
1290 | dev_err(di->dev, "failed to enable LED\n"); | ||
1291 | |||
1292 | queue_delayed_work(di->charger_wq, &di->check_vbat_work, HZ); | ||
1293 | |||
1294 | di->usb.charger_online = 1; | ||
1295 | } else { | ||
1296 | /* Disable USB charging */ | ||
1297 | ret = abx500_set_register_interruptible(di->dev, | ||
1298 | AB8500_CHARGER, | ||
1299 | AB8500_USBCH_CTRL1_REG, 0); | ||
1300 | if (ret) { | ||
1301 | dev_err(di->dev, | ||
1302 | "%s write failed\n", __func__); | ||
1303 | return ret; | ||
1304 | } | ||
1305 | |||
1306 | ret = ab8500_charger_led_en(di, false); | ||
1307 | if (ret < 0) | ||
1308 | dev_err(di->dev, "failed to disable LED\n"); | ||
1309 | |||
1310 | di->usb.charger_online = 0; | ||
1311 | di->usb.wd_expired = false; | ||
1312 | |||
1313 | /* Disable regulator if enabled */ | ||
1314 | if (di->vddadc_en_usb) { | ||
1315 | regulator_disable(di->regu); | ||
1316 | di->vddadc_en_usb = false; | ||
1317 | } | ||
1318 | |||
1319 | dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); | ||
1320 | |||
1321 | /* Cancel any pending Vbat check work */ | ||
1322 | if (delayed_work_pending(&di->check_vbat_work)) | ||
1323 | cancel_delayed_work(&di->check_vbat_work); | ||
1324 | |||
1325 | } | ||
1326 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1327 | |||
1328 | return ret; | ||
1329 | } | ||
1330 | |||
1331 | /** | ||
1332 | * ab8500_charger_watchdog_kick() - kick charger watchdog | ||
1333 | * @di: pointer to the ab8500_charger structure | ||
1334 | * | ||
1335 | * Kick charger watchdog | ||
1336 | * Returns error code in case of failure else 0(on success) | ||
1337 | */ | ||
1338 | static int ab8500_charger_watchdog_kick(struct ux500_charger *charger) | ||
1339 | { | ||
1340 | int ret; | ||
1341 | struct ab8500_charger *di; | ||
1342 | |||
1343 | if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) | ||
1344 | di = to_ab8500_charger_ac_device_info(charger); | ||
1345 | else if (charger->psy.type == POWER_SUPPLY_TYPE_USB) | ||
1346 | di = to_ab8500_charger_usb_device_info(charger); | ||
1347 | else | ||
1348 | return -ENXIO; | ||
1349 | |||
1350 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1351 | AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); | ||
1352 | if (ret) | ||
1353 | dev_err(di->dev, "Failed to kick WD!\n"); | ||
1354 | |||
1355 | return ret; | ||
1356 | } | ||
1357 | |||
1358 | /** | ||
1359 | * ab8500_charger_update_charger_current() - update charger current | ||
1360 | * @di: pointer to the ab8500_charger structure | ||
1361 | * | ||
1362 | * Update the charger output current for the specified charger | ||
1363 | * Returns error code in case of failure else 0(on success) | ||
1364 | */ | ||
1365 | static int ab8500_charger_update_charger_current(struct ux500_charger *charger, | ||
1366 | int ich_out) | ||
1367 | { | ||
1368 | int ret; | ||
1369 | int curr_index; | ||
1370 | struct ab8500_charger *di; | ||
1371 | |||
1372 | if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) | ||
1373 | di = to_ab8500_charger_ac_device_info(charger); | ||
1374 | else if (charger->psy.type == POWER_SUPPLY_TYPE_USB) | ||
1375 | di = to_ab8500_charger_usb_device_info(charger); | ||
1376 | else | ||
1377 | return -ENXIO; | ||
1378 | |||
1379 | curr_index = ab8500_current_to_regval(ich_out); | ||
1380 | if (curr_index < 0) { | ||
1381 | dev_err(di->dev, | ||
1382 | "Charger current too high, " | ||
1383 | "charging not started\n"); | ||
1384 | return -ENXIO; | ||
1385 | } | ||
1386 | |||
1387 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1388 | AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); | ||
1389 | if (ret) { | ||
1390 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1391 | return ret; | ||
1392 | } | ||
1393 | |||
1394 | /* Reset the main and usb drop input current measurement counter */ | ||
1395 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1396 | AB8500_CHARGER_CTRL, | ||
1397 | 0x1); | ||
1398 | if (ret) { | ||
1399 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1400 | return ret; | ||
1401 | } | ||
1402 | |||
1403 | return ret; | ||
1404 | } | ||
1405 | |||
1406 | static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data) | ||
1407 | { | ||
1408 | struct power_supply *psy; | ||
1409 | struct power_supply *ext; | ||
1410 | struct ab8500_charger *di; | ||
1411 | union power_supply_propval ret; | ||
1412 | int i, j; | ||
1413 | bool psy_found = false; | ||
1414 | struct ux500_charger *usb_chg; | ||
1415 | |||
1416 | usb_chg = (struct ux500_charger *)data; | ||
1417 | psy = &usb_chg->psy; | ||
1418 | |||
1419 | di = to_ab8500_charger_usb_device_info(usb_chg); | ||
1420 | |||
1421 | ext = dev_get_drvdata(dev); | ||
1422 | |||
1423 | /* For all psy where the driver name appears in any supplied_to */ | ||
1424 | for (i = 0; i < ext->num_supplicants; i++) { | ||
1425 | if (!strcmp(ext->supplied_to[i], psy->name)) | ||
1426 | psy_found = true; | ||
1427 | } | ||
1428 | |||
1429 | if (!psy_found) | ||
1430 | return 0; | ||
1431 | |||
1432 | /* Go through all properties for the psy */ | ||
1433 | for (j = 0; j < ext->num_properties; j++) { | ||
1434 | enum power_supply_property prop; | ||
1435 | prop = ext->properties[j]; | ||
1436 | |||
1437 | if (ext->get_property(ext, prop, &ret)) | ||
1438 | continue; | ||
1439 | |||
1440 | switch (prop) { | ||
1441 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
1442 | switch (ext->type) { | ||
1443 | case POWER_SUPPLY_TYPE_BATTERY: | ||
1444 | di->vbat = ret.intval / 1000; | ||
1445 | break; | ||
1446 | default: | ||
1447 | break; | ||
1448 | } | ||
1449 | break; | ||
1450 | default: | ||
1451 | break; | ||
1452 | } | ||
1453 | } | ||
1454 | return 0; | ||
1455 | } | ||
1456 | |||
1457 | /** | ||
1458 | * ab8500_charger_check_vbat_work() - keep vbus current within spec | ||
1459 | * @work pointer to the work_struct structure | ||
1460 | * | ||
1461 | * Due to a asic bug it is necessary to lower the input current to the vbus | ||
1462 | * charger when charging with at some specific levels. This issue is only valid | ||
1463 | * for below a certain battery voltage. This function makes sure that the | ||
1464 | * the allowed current limit isn't exceeded. | ||
1465 | */ | ||
1466 | static void ab8500_charger_check_vbat_work(struct work_struct *work) | ||
1467 | { | ||
1468 | int t = 10; | ||
1469 | struct ab8500_charger *di = container_of(work, | ||
1470 | struct ab8500_charger, check_vbat_work.work); | ||
1471 | |||
1472 | class_for_each_device(power_supply_class, NULL, | ||
1473 | &di->usb_chg.psy, ab8500_charger_get_ext_psy_data); | ||
1474 | |||
1475 | /* First run old_vbat is 0. */ | ||
1476 | if (di->old_vbat == 0) | ||
1477 | di->old_vbat = di->vbat; | ||
1478 | |||
1479 | if (!((di->old_vbat <= VBAT_TRESH_IP_CUR_RED && | ||
1480 | di->vbat <= VBAT_TRESH_IP_CUR_RED) || | ||
1481 | (di->old_vbat > VBAT_TRESH_IP_CUR_RED && | ||
1482 | di->vbat > VBAT_TRESH_IP_CUR_RED))) { | ||
1483 | |||
1484 | dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d," | ||
1485 | " old: %d\n", di->max_usb_in_curr, di->vbat, | ||
1486 | di->old_vbat); | ||
1487 | ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | ||
1488 | power_supply_changed(&di->usb_chg.psy); | ||
1489 | } | ||
1490 | |||
1491 | di->old_vbat = di->vbat; | ||
1492 | |||
1493 | /* | ||
1494 | * No need to check the battery voltage every second when not close to | ||
1495 | * the threshold. | ||
1496 | */ | ||
1497 | if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100) && | ||
1498 | (di->vbat > (VBAT_TRESH_IP_CUR_RED - 100))) | ||
1499 | t = 1; | ||
1500 | |||
1501 | queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ); | ||
1502 | } | ||
1503 | |||
1504 | /** | ||
1505 | * ab8500_charger_check_hw_failure_work() - check main charger failure | ||
1506 | * @work: pointer to the work_struct structure | ||
1507 | * | ||
1508 | * Work queue function for checking the main charger status | ||
1509 | */ | ||
1510 | static void ab8500_charger_check_hw_failure_work(struct work_struct *work) | ||
1511 | { | ||
1512 | int ret; | ||
1513 | u8 reg_value; | ||
1514 | |||
1515 | struct ab8500_charger *di = container_of(work, | ||
1516 | struct ab8500_charger, check_hw_failure_work.work); | ||
1517 | |||
1518 | /* Check if the status bits for HW failure is still active */ | ||
1519 | if (di->flags.mainextchnotok) { | ||
1520 | ret = abx500_get_register_interruptible(di->dev, | ||
1521 | AB8500_CHARGER, AB8500_CH_STATUS2_REG, ®_value); | ||
1522 | if (ret < 0) { | ||
1523 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
1524 | return; | ||
1525 | } | ||
1526 | if (!(reg_value & MAIN_CH_NOK)) { | ||
1527 | di->flags.mainextchnotok = false; | ||
1528 | ab8500_power_supply_changed(di, &di->ac_chg.psy); | ||
1529 | } | ||
1530 | } | ||
1531 | if (di->flags.vbus_ovv) { | ||
1532 | ret = abx500_get_register_interruptible(di->dev, | ||
1533 | AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, | ||
1534 | ®_value); | ||
1535 | if (ret < 0) { | ||
1536 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
1537 | return; | ||
1538 | } | ||
1539 | if (!(reg_value & VBUS_OVV_TH)) { | ||
1540 | di->flags.vbus_ovv = false; | ||
1541 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1542 | } | ||
1543 | } | ||
1544 | /* If we still have a failure, schedule a new check */ | ||
1545 | if (di->flags.mainextchnotok || di->flags.vbus_ovv) { | ||
1546 | queue_delayed_work(di->charger_wq, | ||
1547 | &di->check_hw_failure_work, round_jiffies(HZ)); | ||
1548 | } | ||
1549 | } | ||
1550 | |||
1551 | /** | ||
1552 | * ab8500_charger_kick_watchdog_work() - kick the watchdog | ||
1553 | * @work: pointer to the work_struct structure | ||
1554 | * | ||
1555 | * Work queue function for kicking the charger watchdog. | ||
1556 | * | ||
1557 | * For ABB revision 1.0 and 1.1 there is a bug in the watchdog | ||
1558 | * logic. That means we have to continously kick the charger | ||
1559 | * watchdog even when no charger is connected. This is only | ||
1560 | * valid once the AC charger has been enabled. This is | ||
1561 | * a bug that is not handled by the algorithm and the | ||
1562 | * watchdog have to be kicked by the charger driver | ||
1563 | * when the AC charger is disabled | ||
1564 | */ | ||
1565 | static void ab8500_charger_kick_watchdog_work(struct work_struct *work) | ||
1566 | { | ||
1567 | int ret; | ||
1568 | |||
1569 | struct ab8500_charger *di = container_of(work, | ||
1570 | struct ab8500_charger, kick_wd_work.work); | ||
1571 | |||
1572 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1573 | AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); | ||
1574 | if (ret) | ||
1575 | dev_err(di->dev, "Failed to kick WD!\n"); | ||
1576 | |||
1577 | /* Schedule a new watchdog kick */ | ||
1578 | queue_delayed_work(di->charger_wq, | ||
1579 | &di->kick_wd_work, round_jiffies(WD_KICK_INTERVAL)); | ||
1580 | } | ||
1581 | |||
1582 | /** | ||
1583 | * ab8500_charger_ac_work() - work to get and set main charger status | ||
1584 | * @work: pointer to the work_struct structure | ||
1585 | * | ||
1586 | * Work queue function for checking the main charger status | ||
1587 | */ | ||
1588 | static void ab8500_charger_ac_work(struct work_struct *work) | ||
1589 | { | ||
1590 | int ret; | ||
1591 | |||
1592 | struct ab8500_charger *di = container_of(work, | ||
1593 | struct ab8500_charger, ac_work); | ||
1594 | |||
1595 | /* | ||
1596 | * Since we can't be sure that the events are received | ||
1597 | * synchronously, we have the check if the main charger is | ||
1598 | * connected by reading the status register | ||
1599 | */ | ||
1600 | ret = ab8500_charger_detect_chargers(di); | ||
1601 | if (ret < 0) | ||
1602 | return; | ||
1603 | |||
1604 | if (ret & AC_PW_CONN) { | ||
1605 | di->ac.charger_connected = 1; | ||
1606 | di->ac_conn = true; | ||
1607 | } else { | ||
1608 | di->ac.charger_connected = 0; | ||
1609 | } | ||
1610 | |||
1611 | ab8500_power_supply_changed(di, &di->ac_chg.psy); | ||
1612 | sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present"); | ||
1613 | } | ||
1614 | |||
1615 | /** | ||
1616 | * ab8500_charger_detect_usb_type_work() - work to detect USB type | ||
1617 | * @work: Pointer to the work_struct structure | ||
1618 | * | ||
1619 | * Detect the type of USB plugged | ||
1620 | */ | ||
1621 | static void ab8500_charger_detect_usb_type_work(struct work_struct *work) | ||
1622 | { | ||
1623 | int ret; | ||
1624 | |||
1625 | struct ab8500_charger *di = container_of(work, | ||
1626 | struct ab8500_charger, detect_usb_type_work); | ||
1627 | |||
1628 | /* | ||
1629 | * Since we can't be sure that the events are received | ||
1630 | * synchronously, we have the check if is | ||
1631 | * connected by reading the status register | ||
1632 | */ | ||
1633 | ret = ab8500_charger_detect_chargers(di); | ||
1634 | if (ret < 0) | ||
1635 | return; | ||
1636 | |||
1637 | if (!(ret & USB_PW_CONN)) { | ||
1638 | di->vbus_detected = 0; | ||
1639 | ab8500_charger_set_usb_connected(di, false); | ||
1640 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1641 | } else { | ||
1642 | di->vbus_detected = 1; | ||
1643 | |||
1644 | if (is_ab8500_1p1_or_earlier(di->parent)) { | ||
1645 | ret = ab8500_charger_detect_usb_type(di); | ||
1646 | if (!ret) { | ||
1647 | ab8500_charger_set_usb_connected(di, true); | ||
1648 | ab8500_power_supply_changed(di, | ||
1649 | &di->usb_chg.psy); | ||
1650 | } | ||
1651 | } else { | ||
1652 | /* For ABB cut2.0 and onwards we have an IRQ, | ||
1653 | * USB_LINK_STATUS that will be triggered when the USB | ||
1654 | * link status changes. The exception is USB connected | ||
1655 | * during startup. Then we don't get a | ||
1656 | * USB_LINK_STATUS IRQ | ||
1657 | */ | ||
1658 | if (di->vbus_detected_start) { | ||
1659 | di->vbus_detected_start = false; | ||
1660 | ret = ab8500_charger_detect_usb_type(di); | ||
1661 | if (!ret) { | ||
1662 | ab8500_charger_set_usb_connected(di, | ||
1663 | true); | ||
1664 | ab8500_power_supply_changed(di, | ||
1665 | &di->usb_chg.psy); | ||
1666 | } | ||
1667 | } | ||
1668 | } | ||
1669 | } | ||
1670 | } | ||
1671 | |||
1672 | /** | ||
1673 | * ab8500_charger_usb_link_status_work() - work to detect USB type | ||
1674 | * @work: pointer to the work_struct structure | ||
1675 | * | ||
1676 | * Detect the type of USB plugged | ||
1677 | */ | ||
1678 | static void ab8500_charger_usb_link_status_work(struct work_struct *work) | ||
1679 | { | ||
1680 | int ret; | ||
1681 | |||
1682 | struct ab8500_charger *di = container_of(work, | ||
1683 | struct ab8500_charger, usb_link_status_work); | ||
1684 | |||
1685 | /* | ||
1686 | * Since we can't be sure that the events are received | ||
1687 | * synchronously, we have the check if is | ||
1688 | * connected by reading the status register | ||
1689 | */ | ||
1690 | ret = ab8500_charger_detect_chargers(di); | ||
1691 | if (ret < 0) | ||
1692 | return; | ||
1693 | |||
1694 | if (!(ret & USB_PW_CONN)) { | ||
1695 | di->vbus_detected = 0; | ||
1696 | ab8500_charger_set_usb_connected(di, false); | ||
1697 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1698 | } else { | ||
1699 | di->vbus_detected = 1; | ||
1700 | ret = ab8500_charger_read_usb_type(di); | ||
1701 | if (!ret) { | ||
1702 | /* Update maximum input current */ | ||
1703 | ret = ab8500_charger_set_vbus_in_curr(di, | ||
1704 | di->max_usb_in_curr); | ||
1705 | if (ret) | ||
1706 | return; | ||
1707 | |||
1708 | ab8500_charger_set_usb_connected(di, true); | ||
1709 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1710 | } else if (ret == -ENXIO) { | ||
1711 | /* No valid charger type detected */ | ||
1712 | ab8500_charger_set_usb_connected(di, false); | ||
1713 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1714 | } | ||
1715 | } | ||
1716 | } | ||
1717 | |||
1718 | static void ab8500_charger_usb_state_changed_work(struct work_struct *work) | ||
1719 | { | ||
1720 | int ret; | ||
1721 | unsigned long flags; | ||
1722 | |||
1723 | struct ab8500_charger *di = container_of(work, | ||
1724 | struct ab8500_charger, usb_state_changed_work); | ||
1725 | |||
1726 | if (!di->vbus_detected) | ||
1727 | return; | ||
1728 | |||
1729 | spin_lock_irqsave(&di->usb_state.usb_lock, flags); | ||
1730 | di->usb_state.usb_changed = false; | ||
1731 | spin_unlock_irqrestore(&di->usb_state.usb_lock, flags); | ||
1732 | |||
1733 | /* | ||
1734 | * wait for some time until you get updates from the usb stack | ||
1735 | * and negotiations are completed | ||
1736 | */ | ||
1737 | msleep(250); | ||
1738 | |||
1739 | if (di->usb_state.usb_changed) | ||
1740 | return; | ||
1741 | |||
1742 | dev_dbg(di->dev, "%s USB state: 0x%02x mA: %d\n", | ||
1743 | __func__, di->usb_state.state, di->usb_state.usb_current); | ||
1744 | |||
1745 | switch (di->usb_state.state) { | ||
1746 | case AB8500_BM_USB_STATE_RESET_HS: | ||
1747 | case AB8500_BM_USB_STATE_RESET_FS: | ||
1748 | case AB8500_BM_USB_STATE_SUSPEND: | ||
1749 | case AB8500_BM_USB_STATE_MAX: | ||
1750 | ab8500_charger_set_usb_connected(di, false); | ||
1751 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1752 | break; | ||
1753 | |||
1754 | case AB8500_BM_USB_STATE_RESUME: | ||
1755 | /* | ||
1756 | * when suspend->resume there should be delay | ||
1757 | * of 1sec for enabling charging | ||
1758 | */ | ||
1759 | msleep(1000); | ||
1760 | /* Intentional fall through */ | ||
1761 | case AB8500_BM_USB_STATE_CONFIGURED: | ||
1762 | /* | ||
1763 | * USB is configured, enable charging with the charging | ||
1764 | * input current obtained from USB driver | ||
1765 | */ | ||
1766 | if (!ab8500_charger_get_usb_cur(di)) { | ||
1767 | /* Update maximum input current */ | ||
1768 | ret = ab8500_charger_set_vbus_in_curr(di, | ||
1769 | di->max_usb_in_curr); | ||
1770 | if (ret) | ||
1771 | return; | ||
1772 | |||
1773 | ab8500_charger_set_usb_connected(di, true); | ||
1774 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1775 | } | ||
1776 | break; | ||
1777 | |||
1778 | default: | ||
1779 | break; | ||
1780 | }; | ||
1781 | } | ||
1782 | |||
1783 | /** | ||
1784 | * ab8500_charger_check_usbchargernotok_work() - check USB chg not ok status | ||
1785 | * @work: pointer to the work_struct structure | ||
1786 | * | ||
1787 | * Work queue function for checking the USB charger Not OK status | ||
1788 | */ | ||
1789 | static void ab8500_charger_check_usbchargernotok_work(struct work_struct *work) | ||
1790 | { | ||
1791 | int ret; | ||
1792 | u8 reg_value; | ||
1793 | bool prev_status; | ||
1794 | |||
1795 | struct ab8500_charger *di = container_of(work, | ||
1796 | struct ab8500_charger, check_usbchgnotok_work.work); | ||
1797 | |||
1798 | /* Check if the status bit for usbchargernotok is still active */ | ||
1799 | ret = abx500_get_register_interruptible(di->dev, | ||
1800 | AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, ®_value); | ||
1801 | if (ret < 0) { | ||
1802 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
1803 | return; | ||
1804 | } | ||
1805 | prev_status = di->flags.usbchargernotok; | ||
1806 | |||
1807 | if (reg_value & VBUS_CH_NOK) { | ||
1808 | di->flags.usbchargernotok = true; | ||
1809 | /* Check again in 1sec */ | ||
1810 | queue_delayed_work(di->charger_wq, | ||
1811 | &di->check_usbchgnotok_work, HZ); | ||
1812 | } else { | ||
1813 | di->flags.usbchargernotok = false; | ||
1814 | di->flags.vbus_collapse = false; | ||
1815 | } | ||
1816 | |||
1817 | if (prev_status != di->flags.usbchargernotok) | ||
1818 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1819 | } | ||
1820 | |||
1821 | /** | ||
1822 | * ab8500_charger_check_main_thermal_prot_work() - check main thermal status | ||
1823 | * @work: pointer to the work_struct structure | ||
1824 | * | ||
1825 | * Work queue function for checking the Main thermal prot status | ||
1826 | */ | ||
1827 | static void ab8500_charger_check_main_thermal_prot_work( | ||
1828 | struct work_struct *work) | ||
1829 | { | ||
1830 | int ret; | ||
1831 | u8 reg_value; | ||
1832 | |||
1833 | struct ab8500_charger *di = container_of(work, | ||
1834 | struct ab8500_charger, check_main_thermal_prot_work); | ||
1835 | |||
1836 | /* Check if the status bit for main_thermal_prot is still active */ | ||
1837 | ret = abx500_get_register_interruptible(di->dev, | ||
1838 | AB8500_CHARGER, AB8500_CH_STATUS2_REG, ®_value); | ||
1839 | if (ret < 0) { | ||
1840 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
1841 | return; | ||
1842 | } | ||
1843 | if (reg_value & MAIN_CH_TH_PROT) | ||
1844 | di->flags.main_thermal_prot = true; | ||
1845 | else | ||
1846 | di->flags.main_thermal_prot = false; | ||
1847 | |||
1848 | ab8500_power_supply_changed(di, &di->ac_chg.psy); | ||
1849 | } | ||
1850 | |||
1851 | /** | ||
1852 | * ab8500_charger_check_usb_thermal_prot_work() - check usb thermal status | ||
1853 | * @work: pointer to the work_struct structure | ||
1854 | * | ||
1855 | * Work queue function for checking the USB thermal prot status | ||
1856 | */ | ||
1857 | static void ab8500_charger_check_usb_thermal_prot_work( | ||
1858 | struct work_struct *work) | ||
1859 | { | ||
1860 | int ret; | ||
1861 | u8 reg_value; | ||
1862 | |||
1863 | struct ab8500_charger *di = container_of(work, | ||
1864 | struct ab8500_charger, check_usb_thermal_prot_work); | ||
1865 | |||
1866 | /* Check if the status bit for usb_thermal_prot is still active */ | ||
1867 | ret = abx500_get_register_interruptible(di->dev, | ||
1868 | AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, ®_value); | ||
1869 | if (ret < 0) { | ||
1870 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
1871 | return; | ||
1872 | } | ||
1873 | if (reg_value & USB_CH_TH_PROT) | ||
1874 | di->flags.usb_thermal_prot = true; | ||
1875 | else | ||
1876 | di->flags.usb_thermal_prot = false; | ||
1877 | |||
1878 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
1879 | } | ||
1880 | |||
1881 | /** | ||
1882 | * ab8500_charger_mainchunplugdet_handler() - main charger unplugged | ||
1883 | * @irq: interrupt number | ||
1884 | * @_di: pointer to the ab8500_charger structure | ||
1885 | * | ||
1886 | * Returns IRQ status(IRQ_HANDLED) | ||
1887 | */ | ||
1888 | static irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di) | ||
1889 | { | ||
1890 | struct ab8500_charger *di = _di; | ||
1891 | |||
1892 | dev_dbg(di->dev, "Main charger unplugged\n"); | ||
1893 | queue_work(di->charger_wq, &di->ac_work); | ||
1894 | |||
1895 | return IRQ_HANDLED; | ||
1896 | } | ||
1897 | |||
1898 | /** | ||
1899 | * ab8500_charger_mainchplugdet_handler() - main charger plugged | ||
1900 | * @irq: interrupt number | ||
1901 | * @_di: pointer to the ab8500_charger structure | ||
1902 | * | ||
1903 | * Returns IRQ status(IRQ_HANDLED) | ||
1904 | */ | ||
1905 | static irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di) | ||
1906 | { | ||
1907 | struct ab8500_charger *di = _di; | ||
1908 | |||
1909 | dev_dbg(di->dev, "Main charger plugged\n"); | ||
1910 | queue_work(di->charger_wq, &di->ac_work); | ||
1911 | |||
1912 | return IRQ_HANDLED; | ||
1913 | } | ||
1914 | |||
1915 | /** | ||
1916 | * ab8500_charger_mainextchnotok_handler() - main charger not ok | ||
1917 | * @irq: interrupt number | ||
1918 | * @_di: pointer to the ab8500_charger structure | ||
1919 | * | ||
1920 | * Returns IRQ status(IRQ_HANDLED) | ||
1921 | */ | ||
1922 | static irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di) | ||
1923 | { | ||
1924 | struct ab8500_charger *di = _di; | ||
1925 | |||
1926 | dev_dbg(di->dev, "Main charger not ok\n"); | ||
1927 | di->flags.mainextchnotok = true; | ||
1928 | ab8500_power_supply_changed(di, &di->ac_chg.psy); | ||
1929 | |||
1930 | /* Schedule a new HW failure check */ | ||
1931 | queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); | ||
1932 | |||
1933 | return IRQ_HANDLED; | ||
1934 | } | ||
1935 | |||
1936 | /** | ||
1937 | * ab8500_charger_mainchthprotr_handler() - Die temp is above main charger | ||
1938 | * thermal protection threshold | ||
1939 | * @irq: interrupt number | ||
1940 | * @_di: pointer to the ab8500_charger structure | ||
1941 | * | ||
1942 | * Returns IRQ status(IRQ_HANDLED) | ||
1943 | */ | ||
1944 | static irqreturn_t ab8500_charger_mainchthprotr_handler(int irq, void *_di) | ||
1945 | { | ||
1946 | struct ab8500_charger *di = _di; | ||
1947 | |||
1948 | dev_dbg(di->dev, | ||
1949 | "Die temp above Main charger thermal protection threshold\n"); | ||
1950 | queue_work(di->charger_wq, &di->check_main_thermal_prot_work); | ||
1951 | |||
1952 | return IRQ_HANDLED; | ||
1953 | } | ||
1954 | |||
1955 | /** | ||
1956 | * ab8500_charger_mainchthprotf_handler() - Die temp is below main charger | ||
1957 | * thermal protection threshold | ||
1958 | * @irq: interrupt number | ||
1959 | * @_di: pointer to the ab8500_charger structure | ||
1960 | * | ||
1961 | * Returns IRQ status(IRQ_HANDLED) | ||
1962 | */ | ||
1963 | static irqreturn_t ab8500_charger_mainchthprotf_handler(int irq, void *_di) | ||
1964 | { | ||
1965 | struct ab8500_charger *di = _di; | ||
1966 | |||
1967 | dev_dbg(di->dev, | ||
1968 | "Die temp ok for Main charger thermal protection threshold\n"); | ||
1969 | queue_work(di->charger_wq, &di->check_main_thermal_prot_work); | ||
1970 | |||
1971 | return IRQ_HANDLED; | ||
1972 | } | ||
1973 | |||
1974 | /** | ||
1975 | * ab8500_charger_vbusdetf_handler() - VBUS falling detected | ||
1976 | * @irq: interrupt number | ||
1977 | * @_di: pointer to the ab8500_charger structure | ||
1978 | * | ||
1979 | * Returns IRQ status(IRQ_HANDLED) | ||
1980 | */ | ||
1981 | static irqreturn_t ab8500_charger_vbusdetf_handler(int irq, void *_di) | ||
1982 | { | ||
1983 | struct ab8500_charger *di = _di; | ||
1984 | |||
1985 | dev_dbg(di->dev, "VBUS falling detected\n"); | ||
1986 | queue_work(di->charger_wq, &di->detect_usb_type_work); | ||
1987 | |||
1988 | return IRQ_HANDLED; | ||
1989 | } | ||
1990 | |||
1991 | /** | ||
1992 | * ab8500_charger_vbusdetr_handler() - VBUS rising detected | ||
1993 | * @irq: interrupt number | ||
1994 | * @_di: pointer to the ab8500_charger structure | ||
1995 | * | ||
1996 | * Returns IRQ status(IRQ_HANDLED) | ||
1997 | */ | ||
1998 | static irqreturn_t ab8500_charger_vbusdetr_handler(int irq, void *_di) | ||
1999 | { | ||
2000 | struct ab8500_charger *di = _di; | ||
2001 | |||
2002 | di->vbus_detected = true; | ||
2003 | dev_dbg(di->dev, "VBUS rising detected\n"); | ||
2004 | queue_work(di->charger_wq, &di->detect_usb_type_work); | ||
2005 | |||
2006 | return IRQ_HANDLED; | ||
2007 | } | ||
2008 | |||
2009 | /** | ||
2010 | * ab8500_charger_usblinkstatus_handler() - USB link status has changed | ||
2011 | * @irq: interrupt number | ||
2012 | * @_di: pointer to the ab8500_charger structure | ||
2013 | * | ||
2014 | * Returns IRQ status(IRQ_HANDLED) | ||
2015 | */ | ||
2016 | static irqreturn_t ab8500_charger_usblinkstatus_handler(int irq, void *_di) | ||
2017 | { | ||
2018 | struct ab8500_charger *di = _di; | ||
2019 | |||
2020 | dev_dbg(di->dev, "USB link status changed\n"); | ||
2021 | |||
2022 | queue_work(di->charger_wq, &di->usb_link_status_work); | ||
2023 | |||
2024 | return IRQ_HANDLED; | ||
2025 | } | ||
2026 | |||
2027 | /** | ||
2028 | * ab8500_charger_usbchthprotr_handler() - Die temp is above usb charger | ||
2029 | * thermal protection threshold | ||
2030 | * @irq: interrupt number | ||
2031 | * @_di: pointer to the ab8500_charger structure | ||
2032 | * | ||
2033 | * Returns IRQ status(IRQ_HANDLED) | ||
2034 | */ | ||
2035 | static irqreturn_t ab8500_charger_usbchthprotr_handler(int irq, void *_di) | ||
2036 | { | ||
2037 | struct ab8500_charger *di = _di; | ||
2038 | |||
2039 | dev_dbg(di->dev, | ||
2040 | "Die temp above USB charger thermal protection threshold\n"); | ||
2041 | queue_work(di->charger_wq, &di->check_usb_thermal_prot_work); | ||
2042 | |||
2043 | return IRQ_HANDLED; | ||
2044 | } | ||
2045 | |||
2046 | /** | ||
2047 | * ab8500_charger_usbchthprotf_handler() - Die temp is below usb charger | ||
2048 | * thermal protection threshold | ||
2049 | * @irq: interrupt number | ||
2050 | * @_di: pointer to the ab8500_charger structure | ||
2051 | * | ||
2052 | * Returns IRQ status(IRQ_HANDLED) | ||
2053 | */ | ||
2054 | static irqreturn_t ab8500_charger_usbchthprotf_handler(int irq, void *_di) | ||
2055 | { | ||
2056 | struct ab8500_charger *di = _di; | ||
2057 | |||
2058 | dev_dbg(di->dev, | ||
2059 | "Die temp ok for USB charger thermal protection threshold\n"); | ||
2060 | queue_work(di->charger_wq, &di->check_usb_thermal_prot_work); | ||
2061 | |||
2062 | return IRQ_HANDLED; | ||
2063 | } | ||
2064 | |||
2065 | /** | ||
2066 | * ab8500_charger_usbchargernotokr_handler() - USB charger not ok detected | ||
2067 | * @irq: interrupt number | ||
2068 | * @_di: pointer to the ab8500_charger structure | ||
2069 | * | ||
2070 | * Returns IRQ status(IRQ_HANDLED) | ||
2071 | */ | ||
2072 | static irqreturn_t ab8500_charger_usbchargernotokr_handler(int irq, void *_di) | ||
2073 | { | ||
2074 | struct ab8500_charger *di = _di; | ||
2075 | |||
2076 | dev_dbg(di->dev, "Not allowed USB charger detected\n"); | ||
2077 | queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0); | ||
2078 | |||
2079 | return IRQ_HANDLED; | ||
2080 | } | ||
2081 | |||
2082 | /** | ||
2083 | * ab8500_charger_chwdexp_handler() - Charger watchdog expired | ||
2084 | * @irq: interrupt number | ||
2085 | * @_di: pointer to the ab8500_charger structure | ||
2086 | * | ||
2087 | * Returns IRQ status(IRQ_HANDLED) | ||
2088 | */ | ||
2089 | static irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di) | ||
2090 | { | ||
2091 | struct ab8500_charger *di = _di; | ||
2092 | |||
2093 | dev_dbg(di->dev, "Charger watchdog expired\n"); | ||
2094 | |||
2095 | /* | ||
2096 | * The charger that was online when the watchdog expired | ||
2097 | * needs to be restarted for charging to start again | ||
2098 | */ | ||
2099 | if (di->ac.charger_online) { | ||
2100 | di->ac.wd_expired = true; | ||
2101 | ab8500_power_supply_changed(di, &di->ac_chg.psy); | ||
2102 | } | ||
2103 | if (di->usb.charger_online) { | ||
2104 | di->usb.wd_expired = true; | ||
2105 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
2106 | } | ||
2107 | |||
2108 | return IRQ_HANDLED; | ||
2109 | } | ||
2110 | |||
2111 | /** | ||
2112 | * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected | ||
2113 | * @irq: interrupt number | ||
2114 | * @_di: pointer to the ab8500_charger structure | ||
2115 | * | ||
2116 | * Returns IRQ status(IRQ_HANDLED) | ||
2117 | */ | ||
2118 | static irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di) | ||
2119 | { | ||
2120 | struct ab8500_charger *di = _di; | ||
2121 | |||
2122 | dev_dbg(di->dev, "VBUS overvoltage detected\n"); | ||
2123 | di->flags.vbus_ovv = true; | ||
2124 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
2125 | |||
2126 | /* Schedule a new HW failure check */ | ||
2127 | queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); | ||
2128 | |||
2129 | return IRQ_HANDLED; | ||
2130 | } | ||
2131 | |||
2132 | /** | ||
2133 | * ab8500_charger_ac_get_property() - get the ac/mains properties | ||
2134 | * @psy: pointer to the power_supply structure | ||
2135 | * @psp: pointer to the power_supply_property structure | ||
2136 | * @val: pointer to the power_supply_propval union | ||
2137 | * | ||
2138 | * This function gets called when an application tries to get the ac/mains | ||
2139 | * properties by reading the sysfs files. | ||
2140 | * AC/Mains properties are online, present and voltage. | ||
2141 | * online: ac/mains charging is in progress or not | ||
2142 | * present: presence of the ac/mains | ||
2143 | * voltage: AC/Mains voltage | ||
2144 | * Returns error code in case of failure else 0(on success) | ||
2145 | */ | ||
2146 | static int ab8500_charger_ac_get_property(struct power_supply *psy, | ||
2147 | enum power_supply_property psp, | ||
2148 | union power_supply_propval *val) | ||
2149 | { | ||
2150 | struct ab8500_charger *di; | ||
2151 | |||
2152 | di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy)); | ||
2153 | |||
2154 | switch (psp) { | ||
2155 | case POWER_SUPPLY_PROP_HEALTH: | ||
2156 | if (di->flags.mainextchnotok) | ||
2157 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
2158 | else if (di->ac.wd_expired || di->usb.wd_expired) | ||
2159 | val->intval = POWER_SUPPLY_HEALTH_DEAD; | ||
2160 | else if (di->flags.main_thermal_prot) | ||
2161 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
2162 | else | ||
2163 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
2164 | break; | ||
2165 | case POWER_SUPPLY_PROP_ONLINE: | ||
2166 | val->intval = di->ac.charger_online; | ||
2167 | break; | ||
2168 | case POWER_SUPPLY_PROP_PRESENT: | ||
2169 | val->intval = di->ac.charger_connected; | ||
2170 | break; | ||
2171 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
2172 | di->ac.charger_voltage = ab8500_charger_get_ac_voltage(di); | ||
2173 | val->intval = di->ac.charger_voltage * 1000; | ||
2174 | break; | ||
2175 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | ||
2176 | /* | ||
2177 | * This property is used to indicate when CV mode is entered | ||
2178 | * for the AC charger | ||
2179 | */ | ||
2180 | di->ac.cv_active = ab8500_charger_ac_cv(di); | ||
2181 | val->intval = di->ac.cv_active; | ||
2182 | break; | ||
2183 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
2184 | val->intval = ab8500_charger_get_ac_current(di) * 1000; | ||
2185 | break; | ||
2186 | default: | ||
2187 | return -EINVAL; | ||
2188 | } | ||
2189 | return 0; | ||
2190 | } | ||
2191 | |||
2192 | /** | ||
2193 | * ab8500_charger_usb_get_property() - get the usb properties | ||
2194 | * @psy: pointer to the power_supply structure | ||
2195 | * @psp: pointer to the power_supply_property structure | ||
2196 | * @val: pointer to the power_supply_propval union | ||
2197 | * | ||
2198 | * This function gets called when an application tries to get the usb | ||
2199 | * properties by reading the sysfs files. | ||
2200 | * USB properties are online, present and voltage. | ||
2201 | * online: usb charging is in progress or not | ||
2202 | * present: presence of the usb | ||
2203 | * voltage: vbus voltage | ||
2204 | * Returns error code in case of failure else 0(on success) | ||
2205 | */ | ||
2206 | static int ab8500_charger_usb_get_property(struct power_supply *psy, | ||
2207 | enum power_supply_property psp, | ||
2208 | union power_supply_propval *val) | ||
2209 | { | ||
2210 | struct ab8500_charger *di; | ||
2211 | |||
2212 | di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy)); | ||
2213 | |||
2214 | switch (psp) { | ||
2215 | case POWER_SUPPLY_PROP_HEALTH: | ||
2216 | if (di->flags.usbchargernotok) | ||
2217 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
2218 | else if (di->ac.wd_expired || di->usb.wd_expired) | ||
2219 | val->intval = POWER_SUPPLY_HEALTH_DEAD; | ||
2220 | else if (di->flags.usb_thermal_prot) | ||
2221 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
2222 | else if (di->flags.vbus_ovv) | ||
2223 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
2224 | else | ||
2225 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
2226 | break; | ||
2227 | case POWER_SUPPLY_PROP_ONLINE: | ||
2228 | val->intval = di->usb.charger_online; | ||
2229 | break; | ||
2230 | case POWER_SUPPLY_PROP_PRESENT: | ||
2231 | val->intval = di->usb.charger_connected; | ||
2232 | break; | ||
2233 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
2234 | di->usb.charger_voltage = ab8500_charger_get_vbus_voltage(di); | ||
2235 | val->intval = di->usb.charger_voltage * 1000; | ||
2236 | break; | ||
2237 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | ||
2238 | /* | ||
2239 | * This property is used to indicate when CV mode is entered | ||
2240 | * for the USB charger | ||
2241 | */ | ||
2242 | di->usb.cv_active = ab8500_charger_usb_cv(di); | ||
2243 | val->intval = di->usb.cv_active; | ||
2244 | break; | ||
2245 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
2246 | val->intval = ab8500_charger_get_usb_current(di) * 1000; | ||
2247 | break; | ||
2248 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
2249 | /* | ||
2250 | * This property is used to indicate when VBUS has collapsed | ||
2251 | * due to too high output current from the USB charger | ||
2252 | */ | ||
2253 | if (di->flags.vbus_collapse) | ||
2254 | val->intval = 1; | ||
2255 | else | ||
2256 | val->intval = 0; | ||
2257 | break; | ||
2258 | default: | ||
2259 | return -EINVAL; | ||
2260 | } | ||
2261 | return 0; | ||
2262 | } | ||
2263 | |||
2264 | /** | ||
2265 | * ab8500_charger_init_hw_registers() - Set up charger related registers | ||
2266 | * @di: pointer to the ab8500_charger structure | ||
2267 | * | ||
2268 | * Set up charger OVV, watchdog and maximum voltage registers as well as | ||
2269 | * charging of the backup battery | ||
2270 | */ | ||
2271 | static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) | ||
2272 | { | ||
2273 | int ret = 0; | ||
2274 | |||
2275 | /* Setup maximum charger current and voltage for ABB cut2.0 */ | ||
2276 | if (!is_ab8500_1p1_or_earlier(di->parent)) { | ||
2277 | ret = abx500_set_register_interruptible(di->dev, | ||
2278 | AB8500_CHARGER, | ||
2279 | AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6); | ||
2280 | if (ret) { | ||
2281 | dev_err(di->dev, | ||
2282 | "failed to set CH_VOLT_LVL_MAX_REG\n"); | ||
2283 | goto out; | ||
2284 | } | ||
2285 | |||
2286 | ret = abx500_set_register_interruptible(di->dev, | ||
2287 | AB8500_CHARGER, | ||
2288 | AB8500_CH_OPT_CRNTLVL_MAX_REG, CH_OP_CUR_LVL_1P6); | ||
2289 | if (ret) { | ||
2290 | dev_err(di->dev, | ||
2291 | "failed to set CH_OPT_CRNTLVL_MAX_REG\n"); | ||
2292 | goto out; | ||
2293 | } | ||
2294 | } | ||
2295 | |||
2296 | /* VBUS OVV set to 6.3V and enable automatic current limitiation */ | ||
2297 | ret = abx500_set_register_interruptible(di->dev, | ||
2298 | AB8500_CHARGER, | ||
2299 | AB8500_USBCH_CTRL2_REG, | ||
2300 | VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA); | ||
2301 | if (ret) { | ||
2302 | dev_err(di->dev, "failed to set VBUS OVV\n"); | ||
2303 | goto out; | ||
2304 | } | ||
2305 | |||
2306 | /* Enable main watchdog in OTP */ | ||
2307 | ret = abx500_set_register_interruptible(di->dev, | ||
2308 | AB8500_OTP_EMUL, AB8500_OTP_CONF_15, OTP_ENABLE_WD); | ||
2309 | if (ret) { | ||
2310 | dev_err(di->dev, "failed to enable main WD in OTP\n"); | ||
2311 | goto out; | ||
2312 | } | ||
2313 | |||
2314 | /* Enable main watchdog */ | ||
2315 | ret = abx500_set_register_interruptible(di->dev, | ||
2316 | AB8500_SYS_CTRL2_BLOCK, | ||
2317 | AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_ENA); | ||
2318 | if (ret) { | ||
2319 | dev_err(di->dev, "faile to enable main watchdog\n"); | ||
2320 | goto out; | ||
2321 | } | ||
2322 | |||
2323 | /* | ||
2324 | * Due to internal synchronisation, Enable and Kick watchdog bits | ||
2325 | * cannot be enabled in a single write. | ||
2326 | * A minimum delay of 2*32 kHz period (62.5µs) must be inserted | ||
2327 | * between writing Enable then Kick bits. | ||
2328 | */ | ||
2329 | udelay(63); | ||
2330 | |||
2331 | /* Kick main watchdog */ | ||
2332 | ret = abx500_set_register_interruptible(di->dev, | ||
2333 | AB8500_SYS_CTRL2_BLOCK, | ||
2334 | AB8500_MAIN_WDOG_CTRL_REG, | ||
2335 | (MAIN_WDOG_ENA | MAIN_WDOG_KICK)); | ||
2336 | if (ret) { | ||
2337 | dev_err(di->dev, "failed to kick main watchdog\n"); | ||
2338 | goto out; | ||
2339 | } | ||
2340 | |||
2341 | /* Disable main watchdog */ | ||
2342 | ret = abx500_set_register_interruptible(di->dev, | ||
2343 | AB8500_SYS_CTRL2_BLOCK, | ||
2344 | AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_DIS); | ||
2345 | if (ret) { | ||
2346 | dev_err(di->dev, "failed to disable main watchdog\n"); | ||
2347 | goto out; | ||
2348 | } | ||
2349 | |||
2350 | /* Set watchdog timeout */ | ||
2351 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
2352 | AB8500_CH_WD_TIMER_REG, WD_TIMER); | ||
2353 | if (ret) { | ||
2354 | dev_err(di->dev, "failed to set charger watchdog timeout\n"); | ||
2355 | goto out; | ||
2356 | } | ||
2357 | |||
2358 | /* Backup battery voltage and current */ | ||
2359 | ret = abx500_set_register_interruptible(di->dev, | ||
2360 | AB8500_RTC, | ||
2361 | AB8500_RTC_BACKUP_CHG_REG, | ||
2362 | di->bat->bkup_bat_v | | ||
2363 | di->bat->bkup_bat_i); | ||
2364 | if (ret) { | ||
2365 | dev_err(di->dev, "failed to setup backup battery charging\n"); | ||
2366 | goto out; | ||
2367 | } | ||
2368 | |||
2369 | /* Enable backup battery charging */ | ||
2370 | abx500_mask_and_set_register_interruptible(di->dev, | ||
2371 | AB8500_RTC, AB8500_RTC_CTRL_REG, | ||
2372 | RTC_BUP_CH_ENA, RTC_BUP_CH_ENA); | ||
2373 | if (ret < 0) | ||
2374 | dev_err(di->dev, "%s mask and set failed\n", __func__); | ||
2375 | |||
2376 | out: | ||
2377 | return ret; | ||
2378 | } | ||
2379 | |||
2380 | /* | ||
2381 | * ab8500 charger driver interrupts and their respective isr | ||
2382 | */ | ||
2383 | static struct ab8500_charger_interrupts ab8500_charger_irq[] = { | ||
2384 | {"MAIN_CH_UNPLUG_DET", ab8500_charger_mainchunplugdet_handler}, | ||
2385 | {"MAIN_CHARGE_PLUG_DET", ab8500_charger_mainchplugdet_handler}, | ||
2386 | {"MAIN_EXT_CH_NOT_OK", ab8500_charger_mainextchnotok_handler}, | ||
2387 | {"MAIN_CH_TH_PROT_R", ab8500_charger_mainchthprotr_handler}, | ||
2388 | {"MAIN_CH_TH_PROT_F", ab8500_charger_mainchthprotf_handler}, | ||
2389 | {"VBUS_DET_F", ab8500_charger_vbusdetf_handler}, | ||
2390 | {"VBUS_DET_R", ab8500_charger_vbusdetr_handler}, | ||
2391 | {"USB_LINK_STATUS", ab8500_charger_usblinkstatus_handler}, | ||
2392 | {"USB_CH_TH_PROT_R", ab8500_charger_usbchthprotr_handler}, | ||
2393 | {"USB_CH_TH_PROT_F", ab8500_charger_usbchthprotf_handler}, | ||
2394 | {"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler}, | ||
2395 | {"VBUS_OVV", ab8500_charger_vbusovv_handler}, | ||
2396 | {"CH_WD_EXP", ab8500_charger_chwdexp_handler}, | ||
2397 | }; | ||
2398 | |||
2399 | static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, | ||
2400 | unsigned long event, void *power) | ||
2401 | { | ||
2402 | struct ab8500_charger *di = | ||
2403 | container_of(nb, struct ab8500_charger, nb); | ||
2404 | enum ab8500_usb_state bm_usb_state; | ||
2405 | unsigned mA = *((unsigned *)power); | ||
2406 | |||
2407 | if (event != USB_EVENT_VBUS) { | ||
2408 | dev_dbg(di->dev, "not a standard host, returning\n"); | ||
2409 | return NOTIFY_DONE; | ||
2410 | } | ||
2411 | |||
2412 | /* TODO: State is fabricate here. See if charger really needs USB | ||
2413 | * state or if mA is enough | ||
2414 | */ | ||
2415 | if ((di->usb_state.usb_current == 2) && (mA > 2)) | ||
2416 | bm_usb_state = AB8500_BM_USB_STATE_RESUME; | ||
2417 | else if (mA == 0) | ||
2418 | bm_usb_state = AB8500_BM_USB_STATE_RESET_HS; | ||
2419 | else if (mA == 2) | ||
2420 | bm_usb_state = AB8500_BM_USB_STATE_SUSPEND; | ||
2421 | else if (mA >= 8) /* 8, 100, 500 */ | ||
2422 | bm_usb_state = AB8500_BM_USB_STATE_CONFIGURED; | ||
2423 | else /* Should never occur */ | ||
2424 | bm_usb_state = AB8500_BM_USB_STATE_RESET_FS; | ||
2425 | |||
2426 | dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n", | ||
2427 | __func__, bm_usb_state, mA); | ||
2428 | |||
2429 | spin_lock(&di->usb_state.usb_lock); | ||
2430 | di->usb_state.usb_changed = true; | ||
2431 | spin_unlock(&di->usb_state.usb_lock); | ||
2432 | |||
2433 | di->usb_state.state = bm_usb_state; | ||
2434 | di->usb_state.usb_current = mA; | ||
2435 | |||
2436 | queue_work(di->charger_wq, &di->usb_state_changed_work); | ||
2437 | |||
2438 | return NOTIFY_OK; | ||
2439 | } | ||
2440 | |||
2441 | #if defined(CONFIG_PM) | ||
2442 | static int ab8500_charger_resume(struct platform_device *pdev) | ||
2443 | { | ||
2444 | int ret; | ||
2445 | struct ab8500_charger *di = platform_get_drvdata(pdev); | ||
2446 | |||
2447 | /* | ||
2448 | * For ABB revision 1.0 and 1.1 there is a bug in the watchdog | ||
2449 | * logic. That means we have to continously kick the charger | ||
2450 | * watchdog even when no charger is connected. This is only | ||
2451 | * valid once the AC charger has been enabled. This is | ||
2452 | * a bug that is not handled by the algorithm and the | ||
2453 | * watchdog have to be kicked by the charger driver | ||
2454 | * when the AC charger is disabled | ||
2455 | */ | ||
2456 | if (di->ac_conn && is_ab8500_1p1_or_earlier(di->parent)) { | ||
2457 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
2458 | AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); | ||
2459 | if (ret) | ||
2460 | dev_err(di->dev, "Failed to kick WD!\n"); | ||
2461 | |||
2462 | /* If not already pending start a new timer */ | ||
2463 | if (!delayed_work_pending( | ||
2464 | &di->kick_wd_work)) { | ||
2465 | queue_delayed_work(di->charger_wq, &di->kick_wd_work, | ||
2466 | round_jiffies(WD_KICK_INTERVAL)); | ||
2467 | } | ||
2468 | } | ||
2469 | |||
2470 | /* If we still have a HW failure, schedule a new check */ | ||
2471 | if (di->flags.mainextchnotok || di->flags.vbus_ovv) { | ||
2472 | queue_delayed_work(di->charger_wq, | ||
2473 | &di->check_hw_failure_work, 0); | ||
2474 | } | ||
2475 | |||
2476 | return 0; | ||
2477 | } | ||
2478 | |||
2479 | static int ab8500_charger_suspend(struct platform_device *pdev, | ||
2480 | pm_message_t state) | ||
2481 | { | ||
2482 | struct ab8500_charger *di = platform_get_drvdata(pdev); | ||
2483 | |||
2484 | /* Cancel any pending HW failure check */ | ||
2485 | if (delayed_work_pending(&di->check_hw_failure_work)) | ||
2486 | cancel_delayed_work(&di->check_hw_failure_work); | ||
2487 | |||
2488 | return 0; | ||
2489 | } | ||
2490 | #else | ||
2491 | #define ab8500_charger_suspend NULL | ||
2492 | #define ab8500_charger_resume NULL | ||
2493 | #endif | ||
2494 | |||
2495 | static int ab8500_charger_remove(struct platform_device *pdev) | ||
2496 | { | ||
2497 | struct ab8500_charger *di = platform_get_drvdata(pdev); | ||
2498 | int i, irq, ret; | ||
2499 | |||
2500 | /* Disable AC charging */ | ||
2501 | ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); | ||
2502 | |||
2503 | /* Disable USB charging */ | ||
2504 | ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); | ||
2505 | |||
2506 | /* Disable interrupts */ | ||
2507 | for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { | ||
2508 | irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); | ||
2509 | free_irq(irq, di); | ||
2510 | } | ||
2511 | |||
2512 | /* disable the regulator */ | ||
2513 | regulator_put(di->regu); | ||
2514 | |||
2515 | /* Backup battery voltage and current disable */ | ||
2516 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
2517 | AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); | ||
2518 | if (ret < 0) | ||
2519 | dev_err(di->dev, "%s mask and set failed\n", __func__); | ||
2520 | |||
2521 | usb_unregister_notifier(di->usb_phy, &di->nb); | ||
2522 | usb_put_phy(di->usb_phy); | ||
2523 | |||
2524 | /* Delete the work queue */ | ||
2525 | destroy_workqueue(di->charger_wq); | ||
2526 | |||
2527 | flush_scheduled_work(); | ||
2528 | power_supply_unregister(&di->usb_chg.psy); | ||
2529 | power_supply_unregister(&di->ac_chg.psy); | ||
2530 | platform_set_drvdata(pdev, NULL); | ||
2531 | |||
2532 | return 0; | ||
2533 | } | ||
2534 | |||
2535 | static char *supply_interface[] = { | ||
2536 | "ab8500_chargalg", | ||
2537 | "ab8500_fg", | ||
2538 | "ab8500_btemp", | ||
2539 | }; | ||
2540 | |||
2541 | static int ab8500_charger_probe(struct platform_device *pdev) | ||
2542 | { | ||
2543 | struct device_node *np = pdev->dev.of_node; | ||
2544 | struct ab8500_charger *di; | ||
2545 | int irq, i, charger_status, ret = 0; | ||
2546 | |||
2547 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); | ||
2548 | if (!di) { | ||
2549 | dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); | ||
2550 | return -ENOMEM; | ||
2551 | } | ||
2552 | di->bat = pdev->mfd_cell->platform_data; | ||
2553 | if (!di->bat) { | ||
2554 | if (np) { | ||
2555 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | ||
2556 | if (ret) { | ||
2557 | dev_err(&pdev->dev, | ||
2558 | "failed to get battery information\n"); | ||
2559 | return ret; | ||
2560 | } | ||
2561 | di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); | ||
2562 | } else { | ||
2563 | dev_err(&pdev->dev, "missing dt node for ab8500_charger\n"); | ||
2564 | return -EINVAL; | ||
2565 | } | ||
2566 | } else { | ||
2567 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
2568 | di->autopower_cfg = false; | ||
2569 | } | ||
2570 | |||
2571 | /* get parent data */ | ||
2572 | di->dev = &pdev->dev; | ||
2573 | di->parent = dev_get_drvdata(pdev->dev.parent); | ||
2574 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2575 | |||
2576 | /* initialize lock */ | ||
2577 | spin_lock_init(&di->usb_state.usb_lock); | ||
2578 | |||
2579 | di->autopower = false; | ||
2580 | |||
2581 | /* AC supply */ | ||
2582 | /* power_supply base class */ | ||
2583 | di->ac_chg.psy.name = "ab8500_ac"; | ||
2584 | di->ac_chg.psy.type = POWER_SUPPLY_TYPE_MAINS; | ||
2585 | di->ac_chg.psy.properties = ab8500_charger_ac_props; | ||
2586 | di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props); | ||
2587 | di->ac_chg.psy.get_property = ab8500_charger_ac_get_property; | ||
2588 | di->ac_chg.psy.supplied_to = supply_interface; | ||
2589 | di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), | ||
2590 | /* ux500_charger sub-class */ | ||
2591 | di->ac_chg.ops.enable = &ab8500_charger_ac_en; | ||
2592 | di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; | ||
2593 | di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current; | ||
2594 | di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ | ||
2595 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; | ||
2596 | di->ac_chg.max_out_curr = ab8500_charger_current_map[ | ||
2597 | ARRAY_SIZE(ab8500_charger_current_map) - 1]; | ||
2598 | |||
2599 | /* USB supply */ | ||
2600 | /* power_supply base class */ | ||
2601 | di->usb_chg.psy.name = "ab8500_usb"; | ||
2602 | di->usb_chg.psy.type = POWER_SUPPLY_TYPE_USB; | ||
2603 | di->usb_chg.psy.properties = ab8500_charger_usb_props; | ||
2604 | di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props); | ||
2605 | di->usb_chg.psy.get_property = ab8500_charger_usb_get_property; | ||
2606 | di->usb_chg.psy.supplied_to = supply_interface; | ||
2607 | di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), | ||
2608 | /* ux500_charger sub-class */ | ||
2609 | di->usb_chg.ops.enable = &ab8500_charger_usb_en; | ||
2610 | di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; | ||
2611 | di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; | ||
2612 | di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ | ||
2613 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; | ||
2614 | di->usb_chg.max_out_curr = ab8500_charger_current_map[ | ||
2615 | ARRAY_SIZE(ab8500_charger_current_map) - 1]; | ||
2616 | |||
2617 | |||
2618 | /* Create a work queue for the charger */ | ||
2619 | di->charger_wq = | ||
2620 | create_singlethread_workqueue("ab8500_charger_wq"); | ||
2621 | if (di->charger_wq == NULL) { | ||
2622 | dev_err(di->dev, "failed to create work queue\n"); | ||
2623 | return -ENOMEM; | ||
2624 | } | ||
2625 | |||
2626 | /* Init work for HW failure check */ | ||
2627 | INIT_DEFERRABLE_WORK(&di->check_hw_failure_work, | ||
2628 | ab8500_charger_check_hw_failure_work); | ||
2629 | INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work, | ||
2630 | ab8500_charger_check_usbchargernotok_work); | ||
2631 | |||
2632 | /* | ||
2633 | * For ABB revision 1.0 and 1.1 there is a bug in the watchdog | ||
2634 | * logic. That means we have to continously kick the charger | ||
2635 | * watchdog even when no charger is connected. This is only | ||
2636 | * valid once the AC charger has been enabled. This is | ||
2637 | * a bug that is not handled by the algorithm and the | ||
2638 | * watchdog have to be kicked by the charger driver | ||
2639 | * when the AC charger is disabled | ||
2640 | */ | ||
2641 | INIT_DEFERRABLE_WORK(&di->kick_wd_work, | ||
2642 | ab8500_charger_kick_watchdog_work); | ||
2643 | |||
2644 | INIT_DEFERRABLE_WORK(&di->check_vbat_work, | ||
2645 | ab8500_charger_check_vbat_work); | ||
2646 | |||
2647 | /* Init work for charger detection */ | ||
2648 | INIT_WORK(&di->usb_link_status_work, | ||
2649 | ab8500_charger_usb_link_status_work); | ||
2650 | INIT_WORK(&di->ac_work, ab8500_charger_ac_work); | ||
2651 | INIT_WORK(&di->detect_usb_type_work, | ||
2652 | ab8500_charger_detect_usb_type_work); | ||
2653 | |||
2654 | INIT_WORK(&di->usb_state_changed_work, | ||
2655 | ab8500_charger_usb_state_changed_work); | ||
2656 | |||
2657 | /* Init work for checking HW status */ | ||
2658 | INIT_WORK(&di->check_main_thermal_prot_work, | ||
2659 | ab8500_charger_check_main_thermal_prot_work); | ||
2660 | INIT_WORK(&di->check_usb_thermal_prot_work, | ||
2661 | ab8500_charger_check_usb_thermal_prot_work); | ||
2662 | |||
2663 | /* | ||
2664 | * VDD ADC supply needs to be enabled from this driver when there | ||
2665 | * is a charger connected to avoid erroneous BTEMP_HIGH/LOW | ||
2666 | * interrupts during charging | ||
2667 | */ | ||
2668 | di->regu = regulator_get(di->dev, "vddadc"); | ||
2669 | if (IS_ERR(di->regu)) { | ||
2670 | ret = PTR_ERR(di->regu); | ||
2671 | dev_err(di->dev, "failed to get vddadc regulator\n"); | ||
2672 | goto free_charger_wq; | ||
2673 | } | ||
2674 | |||
2675 | |||
2676 | /* Initialize OVV, and other registers */ | ||
2677 | ret = ab8500_charger_init_hw_registers(di); | ||
2678 | if (ret) { | ||
2679 | dev_err(di->dev, "failed to initialize ABB registers\n"); | ||
2680 | goto free_regulator; | ||
2681 | } | ||
2682 | |||
2683 | /* Register AC charger class */ | ||
2684 | ret = power_supply_register(di->dev, &di->ac_chg.psy); | ||
2685 | if (ret) { | ||
2686 | dev_err(di->dev, "failed to register AC charger\n"); | ||
2687 | goto free_regulator; | ||
2688 | } | ||
2689 | |||
2690 | /* Register USB charger class */ | ||
2691 | ret = power_supply_register(di->dev, &di->usb_chg.psy); | ||
2692 | if (ret) { | ||
2693 | dev_err(di->dev, "failed to register USB charger\n"); | ||
2694 | goto free_ac; | ||
2695 | } | ||
2696 | |||
2697 | di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); | ||
2698 | if (IS_ERR_OR_NULL(di->usb_phy)) { | ||
2699 | dev_err(di->dev, "failed to get usb transceiver\n"); | ||
2700 | ret = -EINVAL; | ||
2701 | goto free_usb; | ||
2702 | } | ||
2703 | di->nb.notifier_call = ab8500_charger_usb_notifier_call; | ||
2704 | ret = usb_register_notifier(di->usb_phy, &di->nb); | ||
2705 | if (ret) { | ||
2706 | dev_err(di->dev, "failed to register usb notifier\n"); | ||
2707 | goto put_usb_phy; | ||
2708 | } | ||
2709 | |||
2710 | /* Identify the connected charger types during startup */ | ||
2711 | charger_status = ab8500_charger_detect_chargers(di); | ||
2712 | if (charger_status & AC_PW_CONN) { | ||
2713 | di->ac.charger_connected = 1; | ||
2714 | di->ac_conn = true; | ||
2715 | ab8500_power_supply_changed(di, &di->ac_chg.psy); | ||
2716 | sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present"); | ||
2717 | } | ||
2718 | |||
2719 | if (charger_status & USB_PW_CONN) { | ||
2720 | dev_dbg(di->dev, "VBUS Detect during startup\n"); | ||
2721 | di->vbus_detected = true; | ||
2722 | di->vbus_detected_start = true; | ||
2723 | queue_work(di->charger_wq, | ||
2724 | &di->detect_usb_type_work); | ||
2725 | } | ||
2726 | |||
2727 | /* Register interrupts */ | ||
2728 | for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { | ||
2729 | irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); | ||
2730 | ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, | ||
2731 | IRQF_SHARED | IRQF_NO_SUSPEND, | ||
2732 | ab8500_charger_irq[i].name, di); | ||
2733 | |||
2734 | if (ret != 0) { | ||
2735 | dev_err(di->dev, "failed to request %s IRQ %d: %d\n" | ||
2736 | , ab8500_charger_irq[i].name, irq, ret); | ||
2737 | goto free_irq; | ||
2738 | } | ||
2739 | dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", | ||
2740 | ab8500_charger_irq[i].name, irq, ret); | ||
2741 | } | ||
2742 | |||
2743 | platform_set_drvdata(pdev, di); | ||
2744 | |||
2745 | return ret; | ||
2746 | |||
2747 | free_irq: | ||
2748 | usb_unregister_notifier(di->usb_phy, &di->nb); | ||
2749 | |||
2750 | /* We also have to free all successfully registered irqs */ | ||
2751 | for (i = i - 1; i >= 0; i--) { | ||
2752 | irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); | ||
2753 | free_irq(irq, di); | ||
2754 | } | ||
2755 | put_usb_phy: | ||
2756 | usb_put_phy(di->usb_phy); | ||
2757 | free_usb: | ||
2758 | power_supply_unregister(&di->usb_chg.psy); | ||
2759 | free_ac: | ||
2760 | power_supply_unregister(&di->ac_chg.psy); | ||
2761 | free_regulator: | ||
2762 | regulator_put(di->regu); | ||
2763 | free_charger_wq: | ||
2764 | destroy_workqueue(di->charger_wq); | ||
2765 | return ret; | ||
2766 | } | ||
2767 | |||
2768 | static const struct of_device_id ab8500_charger_match[] = { | ||
2769 | { .compatible = "stericsson,ab8500-charger", }, | ||
2770 | { }, | ||
2771 | }; | ||
2772 | |||
2773 | static struct platform_driver ab8500_charger_driver = { | ||
2774 | .probe = ab8500_charger_probe, | ||
2775 | .remove = ab8500_charger_remove, | ||
2776 | .suspend = ab8500_charger_suspend, | ||
2777 | .resume = ab8500_charger_resume, | ||
2778 | .driver = { | ||
2779 | .name = "ab8500-charger", | ||
2780 | .owner = THIS_MODULE, | ||
2781 | .of_match_table = ab8500_charger_match, | ||
2782 | }, | ||
2783 | }; | ||
2784 | |||
2785 | static int __init ab8500_charger_init(void) | ||
2786 | { | ||
2787 | return platform_driver_register(&ab8500_charger_driver); | ||
2788 | } | ||
2789 | |||
2790 | static void __exit ab8500_charger_exit(void) | ||
2791 | { | ||
2792 | platform_driver_unregister(&ab8500_charger_driver); | ||
2793 | } | ||
2794 | |||
2795 | subsys_initcall_sync(ab8500_charger_init); | ||
2796 | module_exit(ab8500_charger_exit); | ||
2797 | |||
2798 | MODULE_LICENSE("GPL v2"); | ||
2799 | MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); | ||
2800 | MODULE_ALIAS("platform:ab8500-charger"); | ||
2801 | MODULE_DESCRIPTION("AB8500 charger management driver"); | ||
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c deleted file mode 100644 index b3bf178c346..00000000000 --- a/drivers/power/ab8500_fg.c +++ /dev/null | |||
@@ -1,2644 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2012 | ||
3 | * | ||
4 | * Main and Back-up battery management driver. | ||
5 | * | ||
6 | * Note: Backup battery management is required in case of Li-Ion battery and not | ||
7 | * for capacitive battery. HREF boards have capacitive battery and hence backup | ||
8 | * battery management is not used and the supported code is available in this | ||
9 | * driver. | ||
10 | * | ||
11 | * License Terms: GNU General Public License v2 | ||
12 | * Author: | ||
13 | * Johan Palsson <johan.palsson@stericsson.com> | ||
14 | * Karl Komierowski <karl.komierowski@stericsson.com> | ||
15 | * Arun R Murthy <arun.murthy@stericsson.com> | ||
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/platform_device.h> | ||
23 | #include <linux/power_supply.h> | ||
24 | #include <linux/kobject.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/time.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/completion.h> | ||
30 | #include <linux/mfd/core.h> | ||
31 | #include <linux/mfd/abx500.h> | ||
32 | #include <linux/mfd/abx500/ab8500.h> | ||
33 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
34 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
35 | |||
36 | #define MILLI_TO_MICRO 1000 | ||
37 | #define FG_LSB_IN_MA 1627 | ||
38 | #define QLSB_NANO_AMP_HOURS_X10 1129 | ||
39 | #define INS_CURR_TIMEOUT (3 * HZ) | ||
40 | |||
41 | #define SEC_TO_SAMPLE(S) (S * 4) | ||
42 | |||
43 | #define NBR_AVG_SAMPLES 20 | ||
44 | |||
45 | #define LOW_BAT_CHECK_INTERVAL (2 * HZ) | ||
46 | |||
47 | #define VALID_CAPACITY_SEC (45 * 60) /* 45 minutes */ | ||
48 | #define BATT_OK_MIN 2360 /* mV */ | ||
49 | #define BATT_OK_INCREMENT 50 /* mV */ | ||
50 | #define BATT_OK_MAX_NR_INCREMENTS 0xE | ||
51 | |||
52 | /* FG constants */ | ||
53 | #define BATT_OVV 0x01 | ||
54 | |||
55 | #define interpolate(x, x1, y1, x2, y2) \ | ||
56 | ((y1) + ((((y2) - (y1)) * ((x) - (x1))) / ((x2) - (x1)))); | ||
57 | |||
58 | #define to_ab8500_fg_device_info(x) container_of((x), \ | ||
59 | struct ab8500_fg, fg_psy); | ||
60 | |||
61 | /** | ||
62 | * struct ab8500_fg_interrupts - ab8500 fg interupts | ||
63 | * @name: name of the interrupt | ||
64 | * @isr function pointer to the isr | ||
65 | */ | ||
66 | struct ab8500_fg_interrupts { | ||
67 | char *name; | ||
68 | irqreturn_t (*isr)(int irq, void *data); | ||
69 | }; | ||
70 | |||
71 | enum ab8500_fg_discharge_state { | ||
72 | AB8500_FG_DISCHARGE_INIT, | ||
73 | AB8500_FG_DISCHARGE_INITMEASURING, | ||
74 | AB8500_FG_DISCHARGE_INIT_RECOVERY, | ||
75 | AB8500_FG_DISCHARGE_RECOVERY, | ||
76 | AB8500_FG_DISCHARGE_READOUT_INIT, | ||
77 | AB8500_FG_DISCHARGE_READOUT, | ||
78 | AB8500_FG_DISCHARGE_WAKEUP, | ||
79 | }; | ||
80 | |||
81 | static char *discharge_state[] = { | ||
82 | "DISCHARGE_INIT", | ||
83 | "DISCHARGE_INITMEASURING", | ||
84 | "DISCHARGE_INIT_RECOVERY", | ||
85 | "DISCHARGE_RECOVERY", | ||
86 | "DISCHARGE_READOUT_INIT", | ||
87 | "DISCHARGE_READOUT", | ||
88 | "DISCHARGE_WAKEUP", | ||
89 | }; | ||
90 | |||
91 | enum ab8500_fg_charge_state { | ||
92 | AB8500_FG_CHARGE_INIT, | ||
93 | AB8500_FG_CHARGE_READOUT, | ||
94 | }; | ||
95 | |||
96 | static char *charge_state[] = { | ||
97 | "CHARGE_INIT", | ||
98 | "CHARGE_READOUT", | ||
99 | }; | ||
100 | |||
101 | enum ab8500_fg_calibration_state { | ||
102 | AB8500_FG_CALIB_INIT, | ||
103 | AB8500_FG_CALIB_WAIT, | ||
104 | AB8500_FG_CALIB_END, | ||
105 | }; | ||
106 | |||
107 | struct ab8500_fg_avg_cap { | ||
108 | int avg; | ||
109 | int samples[NBR_AVG_SAMPLES]; | ||
110 | __kernel_time_t time_stamps[NBR_AVG_SAMPLES]; | ||
111 | int pos; | ||
112 | int nbr_samples; | ||
113 | int sum; | ||
114 | }; | ||
115 | |||
116 | struct ab8500_fg_battery_capacity { | ||
117 | int max_mah_design; | ||
118 | int max_mah; | ||
119 | int mah; | ||
120 | int permille; | ||
121 | int level; | ||
122 | int prev_mah; | ||
123 | int prev_percent; | ||
124 | int prev_level; | ||
125 | int user_mah; | ||
126 | }; | ||
127 | |||
128 | struct ab8500_fg_flags { | ||
129 | bool fg_enabled; | ||
130 | bool conv_done; | ||
131 | bool charging; | ||
132 | bool fully_charged; | ||
133 | bool force_full; | ||
134 | bool low_bat_delay; | ||
135 | bool low_bat; | ||
136 | bool bat_ovv; | ||
137 | bool batt_unknown; | ||
138 | bool calibrate; | ||
139 | bool user_cap; | ||
140 | bool batt_id_received; | ||
141 | }; | ||
142 | |||
143 | struct inst_curr_result_list { | ||
144 | struct list_head list; | ||
145 | int *result; | ||
146 | }; | ||
147 | |||
148 | /** | ||
149 | * struct ab8500_fg - ab8500 FG device information | ||
150 | * @dev: Pointer to the structure device | ||
151 | * @node: a list of AB8500 FGs, hence prepared for reentrance | ||
152 | * @irq holds the CCEOC interrupt number | ||
153 | * @vbat: Battery voltage in mV | ||
154 | * @vbat_nom: Nominal battery voltage in mV | ||
155 | * @inst_curr: Instantenous battery current in mA | ||
156 | * @avg_curr: Average battery current in mA | ||
157 | * @bat_temp battery temperature | ||
158 | * @fg_samples: Number of samples used in the FG accumulation | ||
159 | * @accu_charge: Accumulated charge from the last conversion | ||
160 | * @recovery_cnt: Counter for recovery mode | ||
161 | * @high_curr_cnt: Counter for high current mode | ||
162 | * @init_cnt: Counter for init mode | ||
163 | * @recovery_needed: Indicate if recovery is needed | ||
164 | * @high_curr_mode: Indicate if we're in high current mode | ||
165 | * @init_capacity: Indicate if initial capacity measuring should be done | ||
166 | * @turn_off_fg: True if fg was off before current measurement | ||
167 | * @calib_state State during offset calibration | ||
168 | * @discharge_state: Current discharge state | ||
169 | * @charge_state: Current charge state | ||
170 | * @ab8500_fg_complete Completion struct used for the instant current reading | ||
171 | * @flags: Structure for information about events triggered | ||
172 | * @bat_cap: Structure for battery capacity specific parameters | ||
173 | * @avg_cap: Average capacity filter | ||
174 | * @parent: Pointer to the struct ab8500 | ||
175 | * @gpadc: Pointer to the struct gpadc | ||
176 | * @bat: Pointer to the abx500_bm platform data | ||
177 | * @fg_psy: Structure that holds the FG specific battery properties | ||
178 | * @fg_wq: Work queue for running the FG algorithm | ||
179 | * @fg_periodic_work: Work to run the FG algorithm periodically | ||
180 | * @fg_low_bat_work: Work to check low bat condition | ||
181 | * @fg_reinit_work Work used to reset and reinitialise the FG algorithm | ||
182 | * @fg_work: Work to run the FG algorithm instantly | ||
183 | * @fg_acc_cur_work: Work to read the FG accumulator | ||
184 | * @fg_check_hw_failure_work: Work for checking HW state | ||
185 | * @cc_lock: Mutex for locking the CC | ||
186 | * @fg_kobject: Structure of type kobject | ||
187 | */ | ||
188 | struct ab8500_fg { | ||
189 | struct device *dev; | ||
190 | struct list_head node; | ||
191 | int irq; | ||
192 | int vbat; | ||
193 | int vbat_nom; | ||
194 | int inst_curr; | ||
195 | int avg_curr; | ||
196 | int bat_temp; | ||
197 | int fg_samples; | ||
198 | int accu_charge; | ||
199 | int recovery_cnt; | ||
200 | int high_curr_cnt; | ||
201 | int init_cnt; | ||
202 | bool recovery_needed; | ||
203 | bool high_curr_mode; | ||
204 | bool init_capacity; | ||
205 | bool turn_off_fg; | ||
206 | enum ab8500_fg_calibration_state calib_state; | ||
207 | enum ab8500_fg_discharge_state discharge_state; | ||
208 | enum ab8500_fg_charge_state charge_state; | ||
209 | struct completion ab8500_fg_complete; | ||
210 | struct ab8500_fg_flags flags; | ||
211 | struct ab8500_fg_battery_capacity bat_cap; | ||
212 | struct ab8500_fg_avg_cap avg_cap; | ||
213 | struct ab8500 *parent; | ||
214 | struct ab8500_gpadc *gpadc; | ||
215 | struct abx500_bm_data *bat; | ||
216 | struct power_supply fg_psy; | ||
217 | struct workqueue_struct *fg_wq; | ||
218 | struct delayed_work fg_periodic_work; | ||
219 | struct delayed_work fg_low_bat_work; | ||
220 | struct delayed_work fg_reinit_work; | ||
221 | struct work_struct fg_work; | ||
222 | struct work_struct fg_acc_cur_work; | ||
223 | struct delayed_work fg_check_hw_failure_work; | ||
224 | struct mutex cc_lock; | ||
225 | struct kobject fg_kobject; | ||
226 | }; | ||
227 | static LIST_HEAD(ab8500_fg_list); | ||
228 | |||
229 | /** | ||
230 | * ab8500_fg_get() - returns a reference to the primary AB8500 fuel gauge | ||
231 | * (i.e. the first fuel gauge in the instance list) | ||
232 | */ | ||
233 | struct ab8500_fg *ab8500_fg_get(void) | ||
234 | { | ||
235 | struct ab8500_fg *fg; | ||
236 | |||
237 | if (list_empty(&ab8500_fg_list)) | ||
238 | return NULL; | ||
239 | |||
240 | fg = list_first_entry(&ab8500_fg_list, struct ab8500_fg, node); | ||
241 | return fg; | ||
242 | } | ||
243 | |||
244 | /* Main battery properties */ | ||
245 | static enum power_supply_property ab8500_fg_props[] = { | ||
246 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
247 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
248 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
249 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, | ||
250 | POWER_SUPPLY_PROP_ENERGY_FULL, | ||
251 | POWER_SUPPLY_PROP_ENERGY_NOW, | ||
252 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
253 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
254 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
255 | POWER_SUPPLY_PROP_CAPACITY, | ||
256 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
257 | }; | ||
258 | |||
259 | /* | ||
260 | * This array maps the raw hex value to lowbat voltage used by the AB8500 | ||
261 | * Values taken from the UM0836 | ||
262 | */ | ||
263 | static int ab8500_fg_lowbat_voltage_map[] = { | ||
264 | 2300 , | ||
265 | 2325 , | ||
266 | 2350 , | ||
267 | 2375 , | ||
268 | 2400 , | ||
269 | 2425 , | ||
270 | 2450 , | ||
271 | 2475 , | ||
272 | 2500 , | ||
273 | 2525 , | ||
274 | 2550 , | ||
275 | 2575 , | ||
276 | 2600 , | ||
277 | 2625 , | ||
278 | 2650 , | ||
279 | 2675 , | ||
280 | 2700 , | ||
281 | 2725 , | ||
282 | 2750 , | ||
283 | 2775 , | ||
284 | 2800 , | ||
285 | 2825 , | ||
286 | 2850 , | ||
287 | 2875 , | ||
288 | 2900 , | ||
289 | 2925 , | ||
290 | 2950 , | ||
291 | 2975 , | ||
292 | 3000 , | ||
293 | 3025 , | ||
294 | 3050 , | ||
295 | 3075 , | ||
296 | 3100 , | ||
297 | 3125 , | ||
298 | 3150 , | ||
299 | 3175 , | ||
300 | 3200 , | ||
301 | 3225 , | ||
302 | 3250 , | ||
303 | 3275 , | ||
304 | 3300 , | ||
305 | 3325 , | ||
306 | 3350 , | ||
307 | 3375 , | ||
308 | 3400 , | ||
309 | 3425 , | ||
310 | 3450 , | ||
311 | 3475 , | ||
312 | 3500 , | ||
313 | 3525 , | ||
314 | 3550 , | ||
315 | 3575 , | ||
316 | 3600 , | ||
317 | 3625 , | ||
318 | 3650 , | ||
319 | 3675 , | ||
320 | 3700 , | ||
321 | 3725 , | ||
322 | 3750 , | ||
323 | 3775 , | ||
324 | 3800 , | ||
325 | 3825 , | ||
326 | 3850 , | ||
327 | 3850 , | ||
328 | }; | ||
329 | |||
330 | static u8 ab8500_volt_to_regval(int voltage) | ||
331 | { | ||
332 | int i; | ||
333 | |||
334 | if (voltage < ab8500_fg_lowbat_voltage_map[0]) | ||
335 | return 0; | ||
336 | |||
337 | for (i = 0; i < ARRAY_SIZE(ab8500_fg_lowbat_voltage_map); i++) { | ||
338 | if (voltage < ab8500_fg_lowbat_voltage_map[i]) | ||
339 | return (u8) i - 1; | ||
340 | } | ||
341 | |||
342 | /* If not captured above, return index of last element */ | ||
343 | return (u8) ARRAY_SIZE(ab8500_fg_lowbat_voltage_map) - 1; | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * ab8500_fg_is_low_curr() - Low or high current mode | ||
348 | * @di: pointer to the ab8500_fg structure | ||
349 | * @curr: the current to base or our decision on | ||
350 | * | ||
351 | * Low current mode if the current consumption is below a certain threshold | ||
352 | */ | ||
353 | static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr) | ||
354 | { | ||
355 | /* | ||
356 | * We want to know if we're in low current mode | ||
357 | */ | ||
358 | if (curr > -di->bat->fg_params->high_curr_threshold) | ||
359 | return true; | ||
360 | else | ||
361 | return false; | ||
362 | } | ||
363 | |||
364 | /** | ||
365 | * ab8500_fg_add_cap_sample() - Add capacity to average filter | ||
366 | * @di: pointer to the ab8500_fg structure | ||
367 | * @sample: the capacity in mAh to add to the filter | ||
368 | * | ||
369 | * A capacity is added to the filter and a new mean capacity is calculated and | ||
370 | * returned | ||
371 | */ | ||
372 | static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample) | ||
373 | { | ||
374 | struct timespec ts; | ||
375 | struct ab8500_fg_avg_cap *avg = &di->avg_cap; | ||
376 | |||
377 | getnstimeofday(&ts); | ||
378 | |||
379 | do { | ||
380 | avg->sum += sample - avg->samples[avg->pos]; | ||
381 | avg->samples[avg->pos] = sample; | ||
382 | avg->time_stamps[avg->pos] = ts.tv_sec; | ||
383 | avg->pos++; | ||
384 | |||
385 | if (avg->pos == NBR_AVG_SAMPLES) | ||
386 | avg->pos = 0; | ||
387 | |||
388 | if (avg->nbr_samples < NBR_AVG_SAMPLES) | ||
389 | avg->nbr_samples++; | ||
390 | |||
391 | /* | ||
392 | * Check the time stamp for each sample. If too old, | ||
393 | * replace with latest sample | ||
394 | */ | ||
395 | } while (ts.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]); | ||
396 | |||
397 | avg->avg = avg->sum / avg->nbr_samples; | ||
398 | |||
399 | return avg->avg; | ||
400 | } | ||
401 | |||
402 | /** | ||
403 | * ab8500_fg_clear_cap_samples() - Clear average filter | ||
404 | * @di: pointer to the ab8500_fg structure | ||
405 | * | ||
406 | * The capacity filter is is reset to zero. | ||
407 | */ | ||
408 | static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di) | ||
409 | { | ||
410 | int i; | ||
411 | struct ab8500_fg_avg_cap *avg = &di->avg_cap; | ||
412 | |||
413 | avg->pos = 0; | ||
414 | avg->nbr_samples = 0; | ||
415 | avg->sum = 0; | ||
416 | avg->avg = 0; | ||
417 | |||
418 | for (i = 0; i < NBR_AVG_SAMPLES; i++) { | ||
419 | avg->samples[i] = 0; | ||
420 | avg->time_stamps[i] = 0; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | /** | ||
425 | * ab8500_fg_fill_cap_sample() - Fill average filter | ||
426 | * @di: pointer to the ab8500_fg structure | ||
427 | * @sample: the capacity in mAh to fill the filter with | ||
428 | * | ||
429 | * The capacity filter is filled with a capacity in mAh | ||
430 | */ | ||
431 | static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample) | ||
432 | { | ||
433 | int i; | ||
434 | struct timespec ts; | ||
435 | struct ab8500_fg_avg_cap *avg = &di->avg_cap; | ||
436 | |||
437 | getnstimeofday(&ts); | ||
438 | |||
439 | for (i = 0; i < NBR_AVG_SAMPLES; i++) { | ||
440 | avg->samples[i] = sample; | ||
441 | avg->time_stamps[i] = ts.tv_sec; | ||
442 | } | ||
443 | |||
444 | avg->pos = 0; | ||
445 | avg->nbr_samples = NBR_AVG_SAMPLES; | ||
446 | avg->sum = sample * NBR_AVG_SAMPLES; | ||
447 | avg->avg = sample; | ||
448 | } | ||
449 | |||
450 | /** | ||
451 | * ab8500_fg_coulomb_counter() - enable coulomb counter | ||
452 | * @di: pointer to the ab8500_fg structure | ||
453 | * @enable: enable/disable | ||
454 | * | ||
455 | * Enable/Disable coulomb counter. | ||
456 | * On failure returns negative value. | ||
457 | */ | ||
458 | static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) | ||
459 | { | ||
460 | int ret = 0; | ||
461 | mutex_lock(&di->cc_lock); | ||
462 | if (enable) { | ||
463 | /* To be able to reprogram the number of samples, we have to | ||
464 | * first stop the CC and then enable it again */ | ||
465 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
466 | AB8500_RTC_CC_CONF_REG, 0x00); | ||
467 | if (ret) | ||
468 | goto cc_err; | ||
469 | |||
470 | /* Program the samples */ | ||
471 | ret = abx500_set_register_interruptible(di->dev, | ||
472 | AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU, | ||
473 | di->fg_samples); | ||
474 | if (ret) | ||
475 | goto cc_err; | ||
476 | |||
477 | /* Start the CC */ | ||
478 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
479 | AB8500_RTC_CC_CONF_REG, | ||
480 | (CC_DEEP_SLEEP_ENA | CC_PWR_UP_ENA)); | ||
481 | if (ret) | ||
482 | goto cc_err; | ||
483 | |||
484 | di->flags.fg_enabled = true; | ||
485 | } else { | ||
486 | /* Clear any pending read requests */ | ||
487 | ret = abx500_set_register_interruptible(di->dev, | ||
488 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, 0); | ||
489 | if (ret) | ||
490 | goto cc_err; | ||
491 | |||
492 | ret = abx500_set_register_interruptible(di->dev, | ||
493 | AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU_CTRL, 0); | ||
494 | if (ret) | ||
495 | goto cc_err; | ||
496 | |||
497 | /* Stop the CC */ | ||
498 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
499 | AB8500_RTC_CC_CONF_REG, 0); | ||
500 | if (ret) | ||
501 | goto cc_err; | ||
502 | |||
503 | di->flags.fg_enabled = false; | ||
504 | |||
505 | } | ||
506 | dev_dbg(di->dev, " CC enabled: %d Samples: %d\n", | ||
507 | enable, di->fg_samples); | ||
508 | |||
509 | mutex_unlock(&di->cc_lock); | ||
510 | |||
511 | return ret; | ||
512 | cc_err: | ||
513 | dev_err(di->dev, "%s Enabling coulomb counter failed\n", __func__); | ||
514 | mutex_unlock(&di->cc_lock); | ||
515 | return ret; | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * ab8500_fg_inst_curr_start() - start battery instantaneous current | ||
520 | * @di: pointer to the ab8500_fg structure | ||
521 | * | ||
522 | * Returns 0 or error code | ||
523 | * Note: This is part "one" and has to be called before | ||
524 | * ab8500_fg_inst_curr_finalize() | ||
525 | */ | ||
526 | int ab8500_fg_inst_curr_start(struct ab8500_fg *di) | ||
527 | { | ||
528 | u8 reg_val; | ||
529 | int ret; | ||
530 | |||
531 | mutex_lock(&di->cc_lock); | ||
532 | |||
533 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | ||
534 | AB8500_RTC_CC_CONF_REG, ®_val); | ||
535 | if (ret < 0) | ||
536 | goto fail; | ||
537 | |||
538 | if (!(reg_val & CC_PWR_UP_ENA)) { | ||
539 | dev_dbg(di->dev, "%s Enable FG\n", __func__); | ||
540 | di->turn_off_fg = true; | ||
541 | |||
542 | /* Program the samples */ | ||
543 | ret = abx500_set_register_interruptible(di->dev, | ||
544 | AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU, | ||
545 | SEC_TO_SAMPLE(10)); | ||
546 | if (ret) | ||
547 | goto fail; | ||
548 | |||
549 | /* Start the CC */ | ||
550 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
551 | AB8500_RTC_CC_CONF_REG, | ||
552 | (CC_DEEP_SLEEP_ENA | CC_PWR_UP_ENA)); | ||
553 | if (ret) | ||
554 | goto fail; | ||
555 | } else { | ||
556 | di->turn_off_fg = false; | ||
557 | } | ||
558 | |||
559 | /* Return and WFI */ | ||
560 | INIT_COMPLETION(di->ab8500_fg_complete); | ||
561 | enable_irq(di->irq); | ||
562 | |||
563 | /* Note: cc_lock is still locked */ | ||
564 | return 0; | ||
565 | fail: | ||
566 | mutex_unlock(&di->cc_lock); | ||
567 | return ret; | ||
568 | } | ||
569 | |||
570 | /** | ||
571 | * ab8500_fg_inst_curr_done() - check if fg conversion is done | ||
572 | * @di: pointer to the ab8500_fg structure | ||
573 | * | ||
574 | * Returns 1 if conversion done, 0 if still waiting | ||
575 | */ | ||
576 | int ab8500_fg_inst_curr_done(struct ab8500_fg *di) | ||
577 | { | ||
578 | return completion_done(&di->ab8500_fg_complete); | ||
579 | } | ||
580 | |||
581 | /** | ||
582 | * ab8500_fg_inst_curr_finalize() - battery instantaneous current | ||
583 | * @di: pointer to the ab8500_fg structure | ||
584 | * @res: battery instantenous current(on success) | ||
585 | * | ||
586 | * Returns 0 or an error code | ||
587 | * Note: This is part "two" and has to be called at earliest 250 ms | ||
588 | * after ab8500_fg_inst_curr_start() | ||
589 | */ | ||
590 | int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) | ||
591 | { | ||
592 | u8 low, high; | ||
593 | int val; | ||
594 | int ret; | ||
595 | int timeout; | ||
596 | |||
597 | if (!completion_done(&di->ab8500_fg_complete)) { | ||
598 | timeout = wait_for_completion_timeout(&di->ab8500_fg_complete, | ||
599 | INS_CURR_TIMEOUT); | ||
600 | dev_dbg(di->dev, "Finalize time: %d ms\n", | ||
601 | ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ); | ||
602 | if (!timeout) { | ||
603 | ret = -ETIME; | ||
604 | disable_irq(di->irq); | ||
605 | dev_err(di->dev, "completion timed out [%d]\n", | ||
606 | __LINE__); | ||
607 | goto fail; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | disable_irq(di->irq); | ||
612 | |||
613 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
614 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, | ||
615 | READ_REQ, READ_REQ); | ||
616 | |||
617 | /* 100uS between read request and read is needed */ | ||
618 | usleep_range(100, 100); | ||
619 | |||
620 | /* Read CC Sample conversion value Low and high */ | ||
621 | ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, | ||
622 | AB8500_GASG_CC_SMPL_CNVL_REG, &low); | ||
623 | if (ret < 0) | ||
624 | goto fail; | ||
625 | |||
626 | ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, | ||
627 | AB8500_GASG_CC_SMPL_CNVH_REG, &high); | ||
628 | if (ret < 0) | ||
629 | goto fail; | ||
630 | |||
631 | /* | ||
632 | * negative value for Discharging | ||
633 | * convert 2's compliment into decimal | ||
634 | */ | ||
635 | if (high & 0x10) | ||
636 | val = (low | (high << 8) | 0xFFFFE000); | ||
637 | else | ||
638 | val = (low | (high << 8)); | ||
639 | |||
640 | /* | ||
641 | * Convert to unit value in mA | ||
642 | * Full scale input voltage is | ||
643 | * 66.660mV => LSB = 66.660mV/(4096*res) = 1.627mA | ||
644 | * Given a 250ms conversion cycle time the LSB corresponds | ||
645 | * to 112.9 nAh. Convert to current by dividing by the conversion | ||
646 | * time in hours (250ms = 1 / (3600 * 4)h) | ||
647 | * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm | ||
648 | */ | ||
649 | val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) / | ||
650 | (1000 * di->bat->fg_res); | ||
651 | |||
652 | if (di->turn_off_fg) { | ||
653 | dev_dbg(di->dev, "%s Disable FG\n", __func__); | ||
654 | |||
655 | /* Clear any pending read requests */ | ||
656 | ret = abx500_set_register_interruptible(di->dev, | ||
657 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, 0); | ||
658 | if (ret) | ||
659 | goto fail; | ||
660 | |||
661 | /* Stop the CC */ | ||
662 | ret = abx500_set_register_interruptible(di->dev, AB8500_RTC, | ||
663 | AB8500_RTC_CC_CONF_REG, 0); | ||
664 | if (ret) | ||
665 | goto fail; | ||
666 | } | ||
667 | mutex_unlock(&di->cc_lock); | ||
668 | (*res) = val; | ||
669 | |||
670 | return 0; | ||
671 | fail: | ||
672 | mutex_unlock(&di->cc_lock); | ||
673 | return ret; | ||
674 | } | ||
675 | |||
676 | /** | ||
677 | * ab8500_fg_inst_curr_blocking() - battery instantaneous current | ||
678 | * @di: pointer to the ab8500_fg structure | ||
679 | * @res: battery instantenous current(on success) | ||
680 | * | ||
681 | * Returns 0 else error code | ||
682 | */ | ||
683 | int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di) | ||
684 | { | ||
685 | int ret; | ||
686 | int res = 0; | ||
687 | |||
688 | ret = ab8500_fg_inst_curr_start(di); | ||
689 | if (ret) { | ||
690 | dev_err(di->dev, "Failed to initialize fg_inst\n"); | ||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | ret = ab8500_fg_inst_curr_finalize(di, &res); | ||
695 | if (ret) { | ||
696 | dev_err(di->dev, "Failed to finalize fg_inst\n"); | ||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | return res; | ||
701 | } | ||
702 | |||
703 | /** | ||
704 | * ab8500_fg_acc_cur_work() - average battery current | ||
705 | * @work: pointer to the work_struct structure | ||
706 | * | ||
707 | * Updated the average battery current obtained from the | ||
708 | * coulomb counter. | ||
709 | */ | ||
710 | static void ab8500_fg_acc_cur_work(struct work_struct *work) | ||
711 | { | ||
712 | int val; | ||
713 | int ret; | ||
714 | u8 low, med, high; | ||
715 | |||
716 | struct ab8500_fg *di = container_of(work, | ||
717 | struct ab8500_fg, fg_acc_cur_work); | ||
718 | |||
719 | mutex_lock(&di->cc_lock); | ||
720 | ret = abx500_set_register_interruptible(di->dev, AB8500_GAS_GAUGE, | ||
721 | AB8500_GASG_CC_NCOV_ACCU_CTRL, RD_NCONV_ACCU_REQ); | ||
722 | if (ret) | ||
723 | goto exit; | ||
724 | |||
725 | ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, | ||
726 | AB8500_GASG_CC_NCOV_ACCU_LOW, &low); | ||
727 | if (ret < 0) | ||
728 | goto exit; | ||
729 | |||
730 | ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, | ||
731 | AB8500_GASG_CC_NCOV_ACCU_MED, &med); | ||
732 | if (ret < 0) | ||
733 | goto exit; | ||
734 | |||
735 | ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, | ||
736 | AB8500_GASG_CC_NCOV_ACCU_HIGH, &high); | ||
737 | if (ret < 0) | ||
738 | goto exit; | ||
739 | |||
740 | /* Check for sign bit in case of negative value, 2's compliment */ | ||
741 | if (high & 0x10) | ||
742 | val = (low | (med << 8) | (high << 16) | 0xFFE00000); | ||
743 | else | ||
744 | val = (low | (med << 8) | (high << 16)); | ||
745 | |||
746 | /* | ||
747 | * Convert to uAh | ||
748 | * Given a 250ms conversion cycle time the LSB corresponds | ||
749 | * to 112.9 nAh. | ||
750 | * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm | ||
751 | */ | ||
752 | di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10) / | ||
753 | (100 * di->bat->fg_res); | ||
754 | |||
755 | /* | ||
756 | * Convert to unit value in mA | ||
757 | * Full scale input voltage is | ||
758 | * 66.660mV => LSB = 66.660mV/(4096*res) = 1.627mA | ||
759 | * Given a 250ms conversion cycle time the LSB corresponds | ||
760 | * to 112.9 nAh. Convert to current by dividing by the conversion | ||
761 | * time in hours (= samples / (3600 * 4)h) | ||
762 | * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm | ||
763 | */ | ||
764 | di->avg_curr = (val * QLSB_NANO_AMP_HOURS_X10 * 36) / | ||
765 | (1000 * di->bat->fg_res * (di->fg_samples / 4)); | ||
766 | |||
767 | di->flags.conv_done = true; | ||
768 | |||
769 | mutex_unlock(&di->cc_lock); | ||
770 | |||
771 | queue_work(di->fg_wq, &di->fg_work); | ||
772 | |||
773 | return; | ||
774 | exit: | ||
775 | dev_err(di->dev, | ||
776 | "Failed to read or write gas gauge registers\n"); | ||
777 | mutex_unlock(&di->cc_lock); | ||
778 | queue_work(di->fg_wq, &di->fg_work); | ||
779 | } | ||
780 | |||
781 | /** | ||
782 | * ab8500_fg_bat_voltage() - get battery voltage | ||
783 | * @di: pointer to the ab8500_fg structure | ||
784 | * | ||
785 | * Returns battery voltage(on success) else error code | ||
786 | */ | ||
787 | static int ab8500_fg_bat_voltage(struct ab8500_fg *di) | ||
788 | { | ||
789 | int vbat; | ||
790 | static int prev; | ||
791 | |||
792 | vbat = ab8500_gpadc_convert(di->gpadc, MAIN_BAT_V); | ||
793 | if (vbat < 0) { | ||
794 | dev_err(di->dev, | ||
795 | "%s gpadc conversion failed, using previous value\n", | ||
796 | __func__); | ||
797 | return prev; | ||
798 | } | ||
799 | |||
800 | prev = vbat; | ||
801 | return vbat; | ||
802 | } | ||
803 | |||
804 | /** | ||
805 | * ab8500_fg_volt_to_capacity() - Voltage based capacity | ||
806 | * @di: pointer to the ab8500_fg structure | ||
807 | * @voltage: The voltage to convert to a capacity | ||
808 | * | ||
809 | * Returns battery capacity in per mille based on voltage | ||
810 | */ | ||
811 | static int ab8500_fg_volt_to_capacity(struct ab8500_fg *di, int voltage) | ||
812 | { | ||
813 | int i, tbl_size; | ||
814 | struct abx500_v_to_cap *tbl; | ||
815 | int cap = 0; | ||
816 | |||
817 | tbl = di->bat->bat_type[di->bat->batt_id].v_to_cap_tbl, | ||
818 | tbl_size = di->bat->bat_type[di->bat->batt_id].n_v_cap_tbl_elements; | ||
819 | |||
820 | for (i = 0; i < tbl_size; ++i) { | ||
821 | if (voltage > tbl[i].voltage) | ||
822 | break; | ||
823 | } | ||
824 | |||
825 | if ((i > 0) && (i < tbl_size)) { | ||
826 | cap = interpolate(voltage, | ||
827 | tbl[i].voltage, | ||
828 | tbl[i].capacity * 10, | ||
829 | tbl[i-1].voltage, | ||
830 | tbl[i-1].capacity * 10); | ||
831 | } else if (i == 0) { | ||
832 | cap = 1000; | ||
833 | } else { | ||
834 | cap = 0; | ||
835 | } | ||
836 | |||
837 | dev_dbg(di->dev, "%s Vbat: %d, Cap: %d per mille", | ||
838 | __func__, voltage, cap); | ||
839 | |||
840 | return cap; | ||
841 | } | ||
842 | |||
843 | /** | ||
844 | * ab8500_fg_uncomp_volt_to_capacity() - Uncompensated voltage based capacity | ||
845 | * @di: pointer to the ab8500_fg structure | ||
846 | * | ||
847 | * Returns battery capacity based on battery voltage that is not compensated | ||
848 | * for the voltage drop due to the load | ||
849 | */ | ||
850 | static int ab8500_fg_uncomp_volt_to_capacity(struct ab8500_fg *di) | ||
851 | { | ||
852 | di->vbat = ab8500_fg_bat_voltage(di); | ||
853 | return ab8500_fg_volt_to_capacity(di, di->vbat); | ||
854 | } | ||
855 | |||
856 | /** | ||
857 | * ab8500_fg_battery_resistance() - Returns the battery inner resistance | ||
858 | * @di: pointer to the ab8500_fg structure | ||
859 | * | ||
860 | * Returns battery inner resistance added with the fuel gauge resistor value | ||
861 | * to get the total resistance in the whole link from gnd to bat+ node. | ||
862 | */ | ||
863 | static int ab8500_fg_battery_resistance(struct ab8500_fg *di) | ||
864 | { | ||
865 | int i, tbl_size; | ||
866 | struct batres_vs_temp *tbl; | ||
867 | int resist = 0; | ||
868 | |||
869 | tbl = di->bat->bat_type[di->bat->batt_id].batres_tbl; | ||
870 | tbl_size = di->bat->bat_type[di->bat->batt_id].n_batres_tbl_elements; | ||
871 | |||
872 | for (i = 0; i < tbl_size; ++i) { | ||
873 | if (di->bat_temp / 10 > tbl[i].temp) | ||
874 | break; | ||
875 | } | ||
876 | |||
877 | if ((i > 0) && (i < tbl_size)) { | ||
878 | resist = interpolate(di->bat_temp / 10, | ||
879 | tbl[i].temp, | ||
880 | tbl[i].resist, | ||
881 | tbl[i-1].temp, | ||
882 | tbl[i-1].resist); | ||
883 | } else if (i == 0) { | ||
884 | resist = tbl[0].resist; | ||
885 | } else { | ||
886 | resist = tbl[tbl_size - 1].resist; | ||
887 | } | ||
888 | |||
889 | dev_dbg(di->dev, "%s Temp: %d battery internal resistance: %d" | ||
890 | " fg resistance %d, total: %d (mOhm)\n", | ||
891 | __func__, di->bat_temp, resist, di->bat->fg_res / 10, | ||
892 | (di->bat->fg_res / 10) + resist); | ||
893 | |||
894 | /* fg_res variable is in 0.1mOhm */ | ||
895 | resist += di->bat->fg_res / 10; | ||
896 | |||
897 | return resist; | ||
898 | } | ||
899 | |||
900 | /** | ||
901 | * ab8500_fg_load_comp_volt_to_capacity() - Load compensated voltage based capacity | ||
902 | * @di: pointer to the ab8500_fg structure | ||
903 | * | ||
904 | * Returns battery capacity based on battery voltage that is load compensated | ||
905 | * for the voltage drop | ||
906 | */ | ||
907 | static int ab8500_fg_load_comp_volt_to_capacity(struct ab8500_fg *di) | ||
908 | { | ||
909 | int vbat_comp, res; | ||
910 | int i = 0; | ||
911 | int vbat = 0; | ||
912 | |||
913 | ab8500_fg_inst_curr_start(di); | ||
914 | |||
915 | do { | ||
916 | vbat += ab8500_fg_bat_voltage(di); | ||
917 | i++; | ||
918 | msleep(5); | ||
919 | } while (!ab8500_fg_inst_curr_done(di)); | ||
920 | |||
921 | ab8500_fg_inst_curr_finalize(di, &di->inst_curr); | ||
922 | |||
923 | di->vbat = vbat / i; | ||
924 | res = ab8500_fg_battery_resistance(di); | ||
925 | |||
926 | /* Use Ohms law to get the load compensated voltage */ | ||
927 | vbat_comp = di->vbat - (di->inst_curr * res) / 1000; | ||
928 | |||
929 | dev_dbg(di->dev, "%s Measured Vbat: %dmV,Compensated Vbat %dmV, " | ||
930 | "R: %dmOhm, Current: %dmA Vbat Samples: %d\n", | ||
931 | __func__, di->vbat, vbat_comp, res, di->inst_curr, i); | ||
932 | |||
933 | return ab8500_fg_volt_to_capacity(di, vbat_comp); | ||
934 | } | ||
935 | |||
936 | /** | ||
937 | * ab8500_fg_convert_mah_to_permille() - Capacity in mAh to permille | ||
938 | * @di: pointer to the ab8500_fg structure | ||
939 | * @cap_mah: capacity in mAh | ||
940 | * | ||
941 | * Converts capacity in mAh to capacity in permille | ||
942 | */ | ||
943 | static int ab8500_fg_convert_mah_to_permille(struct ab8500_fg *di, int cap_mah) | ||
944 | { | ||
945 | return (cap_mah * 1000) / di->bat_cap.max_mah_design; | ||
946 | } | ||
947 | |||
948 | /** | ||
949 | * ab8500_fg_convert_permille_to_mah() - Capacity in permille to mAh | ||
950 | * @di: pointer to the ab8500_fg structure | ||
951 | * @cap_pm: capacity in permille | ||
952 | * | ||
953 | * Converts capacity in permille to capacity in mAh | ||
954 | */ | ||
955 | static int ab8500_fg_convert_permille_to_mah(struct ab8500_fg *di, int cap_pm) | ||
956 | { | ||
957 | return cap_pm * di->bat_cap.max_mah_design / 1000; | ||
958 | } | ||
959 | |||
960 | /** | ||
961 | * ab8500_fg_convert_mah_to_uwh() - Capacity in mAh to uWh | ||
962 | * @di: pointer to the ab8500_fg structure | ||
963 | * @cap_mah: capacity in mAh | ||
964 | * | ||
965 | * Converts capacity in mAh to capacity in uWh | ||
966 | */ | ||
967 | static int ab8500_fg_convert_mah_to_uwh(struct ab8500_fg *di, int cap_mah) | ||
968 | { | ||
969 | u64 div_res; | ||
970 | u32 div_rem; | ||
971 | |||
972 | div_res = ((u64) cap_mah) * ((u64) di->vbat_nom); | ||
973 | div_rem = do_div(div_res, 1000); | ||
974 | |||
975 | /* Make sure to round upwards if necessary */ | ||
976 | if (div_rem >= 1000 / 2) | ||
977 | div_res++; | ||
978 | |||
979 | return (int) div_res; | ||
980 | } | ||
981 | |||
982 | /** | ||
983 | * ab8500_fg_calc_cap_charging() - Calculate remaining capacity while charging | ||
984 | * @di: pointer to the ab8500_fg structure | ||
985 | * | ||
986 | * Return the capacity in mAh based on previous calculated capcity and the FG | ||
987 | * accumulator register value. The filter is filled with this capacity | ||
988 | */ | ||
989 | static int ab8500_fg_calc_cap_charging(struct ab8500_fg *di) | ||
990 | { | ||
991 | dev_dbg(di->dev, "%s cap_mah %d accu_charge %d\n", | ||
992 | __func__, | ||
993 | di->bat_cap.mah, | ||
994 | di->accu_charge); | ||
995 | |||
996 | /* Capacity should not be less than 0 */ | ||
997 | if (di->bat_cap.mah + di->accu_charge > 0) | ||
998 | di->bat_cap.mah += di->accu_charge; | ||
999 | else | ||
1000 | di->bat_cap.mah = 0; | ||
1001 | /* | ||
1002 | * We force capacity to 100% once when the algorithm | ||
1003 | * reports that it's full. | ||
1004 | */ | ||
1005 | if (di->bat_cap.mah >= di->bat_cap.max_mah_design || | ||
1006 | di->flags.force_full) { | ||
1007 | di->bat_cap.mah = di->bat_cap.max_mah_design; | ||
1008 | } | ||
1009 | |||
1010 | ab8500_fg_fill_cap_sample(di, di->bat_cap.mah); | ||
1011 | di->bat_cap.permille = | ||
1012 | ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah); | ||
1013 | |||
1014 | /* We need to update battery voltage and inst current when charging */ | ||
1015 | di->vbat = ab8500_fg_bat_voltage(di); | ||
1016 | di->inst_curr = ab8500_fg_inst_curr_blocking(di); | ||
1017 | |||
1018 | return di->bat_cap.mah; | ||
1019 | } | ||
1020 | |||
1021 | /** | ||
1022 | * ab8500_fg_calc_cap_discharge_voltage() - Capacity in discharge with voltage | ||
1023 | * @di: pointer to the ab8500_fg structure | ||
1024 | * @comp: if voltage should be load compensated before capacity calc | ||
1025 | * | ||
1026 | * Return the capacity in mAh based on the battery voltage. The voltage can | ||
1027 | * either be load compensated or not. This value is added to the filter and a | ||
1028 | * new mean value is calculated and returned. | ||
1029 | */ | ||
1030 | static int ab8500_fg_calc_cap_discharge_voltage(struct ab8500_fg *di, bool comp) | ||
1031 | { | ||
1032 | int permille, mah; | ||
1033 | |||
1034 | if (comp) | ||
1035 | permille = ab8500_fg_load_comp_volt_to_capacity(di); | ||
1036 | else | ||
1037 | permille = ab8500_fg_uncomp_volt_to_capacity(di); | ||
1038 | |||
1039 | mah = ab8500_fg_convert_permille_to_mah(di, permille); | ||
1040 | |||
1041 | di->bat_cap.mah = ab8500_fg_add_cap_sample(di, mah); | ||
1042 | di->bat_cap.permille = | ||
1043 | ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah); | ||
1044 | |||
1045 | return di->bat_cap.mah; | ||
1046 | } | ||
1047 | |||
1048 | /** | ||
1049 | * ab8500_fg_calc_cap_discharge_fg() - Capacity in discharge with FG | ||
1050 | * @di: pointer to the ab8500_fg structure | ||
1051 | * | ||
1052 | * Return the capacity in mAh based on previous calculated capcity and the FG | ||
1053 | * accumulator register value. This value is added to the filter and a | ||
1054 | * new mean value is calculated and returned. | ||
1055 | */ | ||
1056 | static int ab8500_fg_calc_cap_discharge_fg(struct ab8500_fg *di) | ||
1057 | { | ||
1058 | int permille_volt, permille; | ||
1059 | |||
1060 | dev_dbg(di->dev, "%s cap_mah %d accu_charge %d\n", | ||
1061 | __func__, | ||
1062 | di->bat_cap.mah, | ||
1063 | di->accu_charge); | ||
1064 | |||
1065 | /* Capacity should not be less than 0 */ | ||
1066 | if (di->bat_cap.mah + di->accu_charge > 0) | ||
1067 | di->bat_cap.mah += di->accu_charge; | ||
1068 | else | ||
1069 | di->bat_cap.mah = 0; | ||
1070 | |||
1071 | if (di->bat_cap.mah >= di->bat_cap.max_mah_design) | ||
1072 | di->bat_cap.mah = di->bat_cap.max_mah_design; | ||
1073 | |||
1074 | /* | ||
1075 | * Check against voltage based capacity. It can not be lower | ||
1076 | * than what the uncompensated voltage says | ||
1077 | */ | ||
1078 | permille = ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah); | ||
1079 | permille_volt = ab8500_fg_uncomp_volt_to_capacity(di); | ||
1080 | |||
1081 | if (permille < permille_volt) { | ||
1082 | di->bat_cap.permille = permille_volt; | ||
1083 | di->bat_cap.mah = ab8500_fg_convert_permille_to_mah(di, | ||
1084 | di->bat_cap.permille); | ||
1085 | |||
1086 | dev_dbg(di->dev, "%s voltage based: perm %d perm_volt %d\n", | ||
1087 | __func__, | ||
1088 | permille, | ||
1089 | permille_volt); | ||
1090 | |||
1091 | ab8500_fg_fill_cap_sample(di, di->bat_cap.mah); | ||
1092 | } else { | ||
1093 | ab8500_fg_fill_cap_sample(di, di->bat_cap.mah); | ||
1094 | di->bat_cap.permille = | ||
1095 | ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah); | ||
1096 | } | ||
1097 | |||
1098 | return di->bat_cap.mah; | ||
1099 | } | ||
1100 | |||
1101 | /** | ||
1102 | * ab8500_fg_capacity_level() - Get the battery capacity level | ||
1103 | * @di: pointer to the ab8500_fg structure | ||
1104 | * | ||
1105 | * Get the battery capacity level based on the capacity in percent | ||
1106 | */ | ||
1107 | static int ab8500_fg_capacity_level(struct ab8500_fg *di) | ||
1108 | { | ||
1109 | int ret, percent; | ||
1110 | |||
1111 | percent = di->bat_cap.permille / 10; | ||
1112 | |||
1113 | if (percent <= di->bat->cap_levels->critical || | ||
1114 | di->flags.low_bat) | ||
1115 | ret = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | ||
1116 | else if (percent <= di->bat->cap_levels->low) | ||
1117 | ret = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | ||
1118 | else if (percent <= di->bat->cap_levels->normal) | ||
1119 | ret = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | ||
1120 | else if (percent <= di->bat->cap_levels->high) | ||
1121 | ret = POWER_SUPPLY_CAPACITY_LEVEL_HIGH; | ||
1122 | else | ||
1123 | ret = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | ||
1124 | |||
1125 | return ret; | ||
1126 | } | ||
1127 | |||
1128 | /** | ||
1129 | * ab8500_fg_check_capacity_limits() - Check if capacity has changed | ||
1130 | * @di: pointer to the ab8500_fg structure | ||
1131 | * @init: capacity is allowed to go up in init mode | ||
1132 | * | ||
1133 | * Check if capacity or capacity limit has changed and notify the system | ||
1134 | * about it using the power_supply framework | ||
1135 | */ | ||
1136 | static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) | ||
1137 | { | ||
1138 | bool changed = false; | ||
1139 | |||
1140 | di->bat_cap.level = ab8500_fg_capacity_level(di); | ||
1141 | |||
1142 | if (di->bat_cap.level != di->bat_cap.prev_level) { | ||
1143 | /* | ||
1144 | * We do not allow reported capacity level to go up | ||
1145 | * unless we're charging or if we're in init | ||
1146 | */ | ||
1147 | if (!(!di->flags.charging && di->bat_cap.level > | ||
1148 | di->bat_cap.prev_level) || init) { | ||
1149 | dev_dbg(di->dev, "level changed from %d to %d\n", | ||
1150 | di->bat_cap.prev_level, | ||
1151 | di->bat_cap.level); | ||
1152 | di->bat_cap.prev_level = di->bat_cap.level; | ||
1153 | changed = true; | ||
1154 | } else { | ||
1155 | dev_dbg(di->dev, "level not allowed to go up " | ||
1156 | "since no charger is connected: %d to %d\n", | ||
1157 | di->bat_cap.prev_level, | ||
1158 | di->bat_cap.level); | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | /* | ||
1163 | * If we have received the LOW_BAT IRQ, set capacity to 0 to initiate | ||
1164 | * shutdown | ||
1165 | */ | ||
1166 | if (di->flags.low_bat) { | ||
1167 | dev_dbg(di->dev, "Battery low, set capacity to 0\n"); | ||
1168 | di->bat_cap.prev_percent = 0; | ||
1169 | di->bat_cap.permille = 0; | ||
1170 | di->bat_cap.prev_mah = 0; | ||
1171 | di->bat_cap.mah = 0; | ||
1172 | changed = true; | ||
1173 | } else if (di->flags.fully_charged) { | ||
1174 | /* | ||
1175 | * We report 100% if algorithm reported fully charged | ||
1176 | * unless capacity drops too much | ||
1177 | */ | ||
1178 | if (di->flags.force_full) { | ||
1179 | di->bat_cap.prev_percent = di->bat_cap.permille / 10; | ||
1180 | di->bat_cap.prev_mah = di->bat_cap.mah; | ||
1181 | } else if (!di->flags.force_full && | ||
1182 | di->bat_cap.prev_percent != | ||
1183 | (di->bat_cap.permille) / 10 && | ||
1184 | (di->bat_cap.permille / 10) < | ||
1185 | di->bat->fg_params->maint_thres) { | ||
1186 | dev_dbg(di->dev, | ||
1187 | "battery reported full " | ||
1188 | "but capacity dropping: %d\n", | ||
1189 | di->bat_cap.permille / 10); | ||
1190 | di->bat_cap.prev_percent = di->bat_cap.permille / 10; | ||
1191 | di->bat_cap.prev_mah = di->bat_cap.mah; | ||
1192 | |||
1193 | changed = true; | ||
1194 | } | ||
1195 | } else if (di->bat_cap.prev_percent != di->bat_cap.permille / 10) { | ||
1196 | if (di->bat_cap.permille / 10 == 0) { | ||
1197 | /* | ||
1198 | * We will not report 0% unless we've got | ||
1199 | * the LOW_BAT IRQ, no matter what the FG | ||
1200 | * algorithm says. | ||
1201 | */ | ||
1202 | di->bat_cap.prev_percent = 1; | ||
1203 | di->bat_cap.permille = 1; | ||
1204 | di->bat_cap.prev_mah = 1; | ||
1205 | di->bat_cap.mah = 1; | ||
1206 | |||
1207 | changed = true; | ||
1208 | } else if (!(!di->flags.charging && | ||
1209 | (di->bat_cap.permille / 10) > | ||
1210 | di->bat_cap.prev_percent) || init) { | ||
1211 | /* | ||
1212 | * We do not allow reported capacity to go up | ||
1213 | * unless we're charging or if we're in init | ||
1214 | */ | ||
1215 | dev_dbg(di->dev, | ||
1216 | "capacity changed from %d to %d (%d)\n", | ||
1217 | di->bat_cap.prev_percent, | ||
1218 | di->bat_cap.permille / 10, | ||
1219 | di->bat_cap.permille); | ||
1220 | di->bat_cap.prev_percent = di->bat_cap.permille / 10; | ||
1221 | di->bat_cap.prev_mah = di->bat_cap.mah; | ||
1222 | |||
1223 | changed = true; | ||
1224 | } else { | ||
1225 | dev_dbg(di->dev, "capacity not allowed to go up since " | ||
1226 | "no charger is connected: %d to %d (%d)\n", | ||
1227 | di->bat_cap.prev_percent, | ||
1228 | di->bat_cap.permille / 10, | ||
1229 | di->bat_cap.permille); | ||
1230 | } | ||
1231 | } | ||
1232 | |||
1233 | if (changed) { | ||
1234 | power_supply_changed(&di->fg_psy); | ||
1235 | if (di->flags.fully_charged && di->flags.force_full) { | ||
1236 | dev_dbg(di->dev, "Battery full, notifying.\n"); | ||
1237 | di->flags.force_full = false; | ||
1238 | sysfs_notify(&di->fg_kobject, NULL, "charge_full"); | ||
1239 | } | ||
1240 | sysfs_notify(&di->fg_kobject, NULL, "charge_now"); | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | static void ab8500_fg_charge_state_to(struct ab8500_fg *di, | ||
1245 | enum ab8500_fg_charge_state new_state) | ||
1246 | { | ||
1247 | dev_dbg(di->dev, "Charge state from %d [%s] to %d [%s]\n", | ||
1248 | di->charge_state, | ||
1249 | charge_state[di->charge_state], | ||
1250 | new_state, | ||
1251 | charge_state[new_state]); | ||
1252 | |||
1253 | di->charge_state = new_state; | ||
1254 | } | ||
1255 | |||
1256 | static void ab8500_fg_discharge_state_to(struct ab8500_fg *di, | ||
1257 | enum ab8500_fg_discharge_state new_state) | ||
1258 | { | ||
1259 | dev_dbg(di->dev, "Disharge state from %d [%s] to %d [%s]\n", | ||
1260 | di->discharge_state, | ||
1261 | discharge_state[di->discharge_state], | ||
1262 | new_state, | ||
1263 | discharge_state[new_state]); | ||
1264 | |||
1265 | di->discharge_state = new_state; | ||
1266 | } | ||
1267 | |||
1268 | /** | ||
1269 | * ab8500_fg_algorithm_charging() - FG algorithm for when charging | ||
1270 | * @di: pointer to the ab8500_fg structure | ||
1271 | * | ||
1272 | * Battery capacity calculation state machine for when we're charging | ||
1273 | */ | ||
1274 | static void ab8500_fg_algorithm_charging(struct ab8500_fg *di) | ||
1275 | { | ||
1276 | /* | ||
1277 | * If we change to discharge mode | ||
1278 | * we should start with recovery | ||
1279 | */ | ||
1280 | if (di->discharge_state != AB8500_FG_DISCHARGE_INIT_RECOVERY) | ||
1281 | ab8500_fg_discharge_state_to(di, | ||
1282 | AB8500_FG_DISCHARGE_INIT_RECOVERY); | ||
1283 | |||
1284 | switch (di->charge_state) { | ||
1285 | case AB8500_FG_CHARGE_INIT: | ||
1286 | di->fg_samples = SEC_TO_SAMPLE( | ||
1287 | di->bat->fg_params->accu_charging); | ||
1288 | |||
1289 | ab8500_fg_coulomb_counter(di, true); | ||
1290 | ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_READOUT); | ||
1291 | |||
1292 | break; | ||
1293 | |||
1294 | case AB8500_FG_CHARGE_READOUT: | ||
1295 | /* | ||
1296 | * Read the FG and calculate the new capacity | ||
1297 | */ | ||
1298 | mutex_lock(&di->cc_lock); | ||
1299 | if (!di->flags.conv_done) { | ||
1300 | /* Wasn't the CC IRQ that got us here */ | ||
1301 | mutex_unlock(&di->cc_lock); | ||
1302 | dev_dbg(di->dev, "%s CC conv not done\n", | ||
1303 | __func__); | ||
1304 | |||
1305 | break; | ||
1306 | } | ||
1307 | di->flags.conv_done = false; | ||
1308 | mutex_unlock(&di->cc_lock); | ||
1309 | |||
1310 | ab8500_fg_calc_cap_charging(di); | ||
1311 | |||
1312 | break; | ||
1313 | |||
1314 | default: | ||
1315 | break; | ||
1316 | } | ||
1317 | |||
1318 | /* Check capacity limits */ | ||
1319 | ab8500_fg_check_capacity_limits(di, false); | ||
1320 | } | ||
1321 | |||
1322 | static void force_capacity(struct ab8500_fg *di) | ||
1323 | { | ||
1324 | int cap; | ||
1325 | |||
1326 | ab8500_fg_clear_cap_samples(di); | ||
1327 | cap = di->bat_cap.user_mah; | ||
1328 | if (cap > di->bat_cap.max_mah_design) { | ||
1329 | dev_dbg(di->dev, "Remaining cap %d can't be bigger than total" | ||
1330 | " %d\n", cap, di->bat_cap.max_mah_design); | ||
1331 | cap = di->bat_cap.max_mah_design; | ||
1332 | } | ||
1333 | ab8500_fg_fill_cap_sample(di, di->bat_cap.user_mah); | ||
1334 | di->bat_cap.permille = ab8500_fg_convert_mah_to_permille(di, cap); | ||
1335 | di->bat_cap.mah = cap; | ||
1336 | ab8500_fg_check_capacity_limits(di, true); | ||
1337 | } | ||
1338 | |||
1339 | static bool check_sysfs_capacity(struct ab8500_fg *di) | ||
1340 | { | ||
1341 | int cap, lower, upper; | ||
1342 | int cap_permille; | ||
1343 | |||
1344 | cap = di->bat_cap.user_mah; | ||
1345 | |||
1346 | cap_permille = ab8500_fg_convert_mah_to_permille(di, | ||
1347 | di->bat_cap.user_mah); | ||
1348 | |||
1349 | lower = di->bat_cap.permille - di->bat->fg_params->user_cap_limit * 10; | ||
1350 | upper = di->bat_cap.permille + di->bat->fg_params->user_cap_limit * 10; | ||
1351 | |||
1352 | if (lower < 0) | ||
1353 | lower = 0; | ||
1354 | /* 1000 is permille, -> 100 percent */ | ||
1355 | if (upper > 1000) | ||
1356 | upper = 1000; | ||
1357 | |||
1358 | dev_dbg(di->dev, "Capacity limits:" | ||
1359 | " (Lower: %d User: %d Upper: %d) [user: %d, was: %d]\n", | ||
1360 | lower, cap_permille, upper, cap, di->bat_cap.mah); | ||
1361 | |||
1362 | /* If within limits, use the saved capacity and exit estimation...*/ | ||
1363 | if (cap_permille > lower && cap_permille < upper) { | ||
1364 | dev_dbg(di->dev, "OK! Using users cap %d uAh now\n", cap); | ||
1365 | force_capacity(di); | ||
1366 | return true; | ||
1367 | } | ||
1368 | dev_dbg(di->dev, "Capacity from user out of limits, ignoring"); | ||
1369 | return false; | ||
1370 | } | ||
1371 | |||
1372 | /** | ||
1373 | * ab8500_fg_algorithm_discharging() - FG algorithm for when discharging | ||
1374 | * @di: pointer to the ab8500_fg structure | ||
1375 | * | ||
1376 | * Battery capacity calculation state machine for when we're discharging | ||
1377 | */ | ||
1378 | static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | ||
1379 | { | ||
1380 | int sleep_time; | ||
1381 | |||
1382 | /* If we change to charge mode we should start with init */ | ||
1383 | if (di->charge_state != AB8500_FG_CHARGE_INIT) | ||
1384 | ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); | ||
1385 | |||
1386 | switch (di->discharge_state) { | ||
1387 | case AB8500_FG_DISCHARGE_INIT: | ||
1388 | /* We use the FG IRQ to work on */ | ||
1389 | di->init_cnt = 0; | ||
1390 | di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); | ||
1391 | ab8500_fg_coulomb_counter(di, true); | ||
1392 | ab8500_fg_discharge_state_to(di, | ||
1393 | AB8500_FG_DISCHARGE_INITMEASURING); | ||
1394 | |||
1395 | /* Intentional fallthrough */ | ||
1396 | case AB8500_FG_DISCHARGE_INITMEASURING: | ||
1397 | /* | ||
1398 | * Discard a number of samples during startup. | ||
1399 | * After that, use compensated voltage for a few | ||
1400 | * samples to get an initial capacity. | ||
1401 | * Then go to READOUT | ||
1402 | */ | ||
1403 | sleep_time = di->bat->fg_params->init_timer; | ||
1404 | |||
1405 | /* Discard the first [x] seconds */ | ||
1406 | if (di->init_cnt > | ||
1407 | di->bat->fg_params->init_discard_time) { | ||
1408 | ab8500_fg_calc_cap_discharge_voltage(di, true); | ||
1409 | |||
1410 | ab8500_fg_check_capacity_limits(di, true); | ||
1411 | } | ||
1412 | |||
1413 | di->init_cnt += sleep_time; | ||
1414 | if (di->init_cnt > di->bat->fg_params->init_total_time) | ||
1415 | ab8500_fg_discharge_state_to(di, | ||
1416 | AB8500_FG_DISCHARGE_READOUT_INIT); | ||
1417 | |||
1418 | break; | ||
1419 | |||
1420 | case AB8500_FG_DISCHARGE_INIT_RECOVERY: | ||
1421 | di->recovery_cnt = 0; | ||
1422 | di->recovery_needed = true; | ||
1423 | ab8500_fg_discharge_state_to(di, | ||
1424 | AB8500_FG_DISCHARGE_RECOVERY); | ||
1425 | |||
1426 | /* Intentional fallthrough */ | ||
1427 | |||
1428 | case AB8500_FG_DISCHARGE_RECOVERY: | ||
1429 | sleep_time = di->bat->fg_params->recovery_sleep_timer; | ||
1430 | |||
1431 | /* | ||
1432 | * We should check the power consumption | ||
1433 | * If low, go to READOUT (after x min) or | ||
1434 | * RECOVERY_SLEEP if time left. | ||
1435 | * If high, go to READOUT | ||
1436 | */ | ||
1437 | di->inst_curr = ab8500_fg_inst_curr_blocking(di); | ||
1438 | |||
1439 | if (ab8500_fg_is_low_curr(di, di->inst_curr)) { | ||
1440 | if (di->recovery_cnt > | ||
1441 | di->bat->fg_params->recovery_total_time) { | ||
1442 | di->fg_samples = SEC_TO_SAMPLE( | ||
1443 | di->bat->fg_params->accu_high_curr); | ||
1444 | ab8500_fg_coulomb_counter(di, true); | ||
1445 | ab8500_fg_discharge_state_to(di, | ||
1446 | AB8500_FG_DISCHARGE_READOUT); | ||
1447 | di->recovery_needed = false; | ||
1448 | } else { | ||
1449 | queue_delayed_work(di->fg_wq, | ||
1450 | &di->fg_periodic_work, | ||
1451 | sleep_time * HZ); | ||
1452 | } | ||
1453 | di->recovery_cnt += sleep_time; | ||
1454 | } else { | ||
1455 | di->fg_samples = SEC_TO_SAMPLE( | ||
1456 | di->bat->fg_params->accu_high_curr); | ||
1457 | ab8500_fg_coulomb_counter(di, true); | ||
1458 | ab8500_fg_discharge_state_to(di, | ||
1459 | AB8500_FG_DISCHARGE_READOUT); | ||
1460 | } | ||
1461 | break; | ||
1462 | |||
1463 | case AB8500_FG_DISCHARGE_READOUT_INIT: | ||
1464 | di->fg_samples = SEC_TO_SAMPLE( | ||
1465 | di->bat->fg_params->accu_high_curr); | ||
1466 | ab8500_fg_coulomb_counter(di, true); | ||
1467 | ab8500_fg_discharge_state_to(di, | ||
1468 | AB8500_FG_DISCHARGE_READOUT); | ||
1469 | break; | ||
1470 | |||
1471 | case AB8500_FG_DISCHARGE_READOUT: | ||
1472 | di->inst_curr = ab8500_fg_inst_curr_blocking(di); | ||
1473 | |||
1474 | if (ab8500_fg_is_low_curr(di, di->inst_curr)) { | ||
1475 | /* Detect mode change */ | ||
1476 | if (di->high_curr_mode) { | ||
1477 | di->high_curr_mode = false; | ||
1478 | di->high_curr_cnt = 0; | ||
1479 | } | ||
1480 | |||
1481 | if (di->recovery_needed) { | ||
1482 | ab8500_fg_discharge_state_to(di, | ||
1483 | AB8500_FG_DISCHARGE_RECOVERY); | ||
1484 | |||
1485 | queue_delayed_work(di->fg_wq, | ||
1486 | &di->fg_periodic_work, 0); | ||
1487 | |||
1488 | break; | ||
1489 | } | ||
1490 | |||
1491 | ab8500_fg_calc_cap_discharge_voltage(di, true); | ||
1492 | } else { | ||
1493 | mutex_lock(&di->cc_lock); | ||
1494 | if (!di->flags.conv_done) { | ||
1495 | /* Wasn't the CC IRQ that got us here */ | ||
1496 | mutex_unlock(&di->cc_lock); | ||
1497 | dev_dbg(di->dev, "%s CC conv not done\n", | ||
1498 | __func__); | ||
1499 | |||
1500 | break; | ||
1501 | } | ||
1502 | di->flags.conv_done = false; | ||
1503 | mutex_unlock(&di->cc_lock); | ||
1504 | |||
1505 | /* Detect mode change */ | ||
1506 | if (!di->high_curr_mode) { | ||
1507 | di->high_curr_mode = true; | ||
1508 | di->high_curr_cnt = 0; | ||
1509 | } | ||
1510 | |||
1511 | di->high_curr_cnt += | ||
1512 | di->bat->fg_params->accu_high_curr; | ||
1513 | if (di->high_curr_cnt > | ||
1514 | di->bat->fg_params->high_curr_time) | ||
1515 | di->recovery_needed = true; | ||
1516 | |||
1517 | ab8500_fg_calc_cap_discharge_fg(di); | ||
1518 | } | ||
1519 | |||
1520 | ab8500_fg_check_capacity_limits(di, false); | ||
1521 | |||
1522 | break; | ||
1523 | |||
1524 | case AB8500_FG_DISCHARGE_WAKEUP: | ||
1525 | ab8500_fg_coulomb_counter(di, true); | ||
1526 | di->inst_curr = ab8500_fg_inst_curr_blocking(di); | ||
1527 | |||
1528 | ab8500_fg_calc_cap_discharge_voltage(di, true); | ||
1529 | |||
1530 | di->fg_samples = SEC_TO_SAMPLE( | ||
1531 | di->bat->fg_params->accu_high_curr); | ||
1532 | ab8500_fg_coulomb_counter(di, true); | ||
1533 | ab8500_fg_discharge_state_to(di, | ||
1534 | AB8500_FG_DISCHARGE_READOUT); | ||
1535 | |||
1536 | ab8500_fg_check_capacity_limits(di, false); | ||
1537 | |||
1538 | break; | ||
1539 | |||
1540 | default: | ||
1541 | break; | ||
1542 | } | ||
1543 | } | ||
1544 | |||
1545 | /** | ||
1546 | * ab8500_fg_algorithm_calibrate() - Internal columb counter offset calibration | ||
1547 | * @di: pointer to the ab8500_fg structure | ||
1548 | * | ||
1549 | */ | ||
1550 | static void ab8500_fg_algorithm_calibrate(struct ab8500_fg *di) | ||
1551 | { | ||
1552 | int ret; | ||
1553 | |||
1554 | switch (di->calib_state) { | ||
1555 | case AB8500_FG_CALIB_INIT: | ||
1556 | dev_dbg(di->dev, "Calibration ongoing...\n"); | ||
1557 | |||
1558 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
1559 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, | ||
1560 | CC_INT_CAL_N_AVG_MASK, CC_INT_CAL_SAMPLES_8); | ||
1561 | if (ret < 0) | ||
1562 | goto err; | ||
1563 | |||
1564 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
1565 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, | ||
1566 | CC_INTAVGOFFSET_ENA, CC_INTAVGOFFSET_ENA); | ||
1567 | if (ret < 0) | ||
1568 | goto err; | ||
1569 | di->calib_state = AB8500_FG_CALIB_WAIT; | ||
1570 | break; | ||
1571 | case AB8500_FG_CALIB_END: | ||
1572 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
1573 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, | ||
1574 | CC_MUXOFFSET, CC_MUXOFFSET); | ||
1575 | if (ret < 0) | ||
1576 | goto err; | ||
1577 | di->flags.calibrate = false; | ||
1578 | dev_dbg(di->dev, "Calibration done...\n"); | ||
1579 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | ||
1580 | break; | ||
1581 | case AB8500_FG_CALIB_WAIT: | ||
1582 | dev_dbg(di->dev, "Calibration WFI\n"); | ||
1583 | default: | ||
1584 | break; | ||
1585 | } | ||
1586 | return; | ||
1587 | err: | ||
1588 | /* Something went wrong, don't calibrate then */ | ||
1589 | dev_err(di->dev, "failed to calibrate the CC\n"); | ||
1590 | di->flags.calibrate = false; | ||
1591 | di->calib_state = AB8500_FG_CALIB_INIT; | ||
1592 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | ||
1593 | } | ||
1594 | |||
1595 | /** | ||
1596 | * ab8500_fg_algorithm() - Entry point for the FG algorithm | ||
1597 | * @di: pointer to the ab8500_fg structure | ||
1598 | * | ||
1599 | * Entry point for the battery capacity calculation state machine | ||
1600 | */ | ||
1601 | static void ab8500_fg_algorithm(struct ab8500_fg *di) | ||
1602 | { | ||
1603 | if (di->flags.calibrate) | ||
1604 | ab8500_fg_algorithm_calibrate(di); | ||
1605 | else { | ||
1606 | if (di->flags.charging) | ||
1607 | ab8500_fg_algorithm_charging(di); | ||
1608 | else | ||
1609 | ab8500_fg_algorithm_discharging(di); | ||
1610 | } | ||
1611 | |||
1612 | dev_dbg(di->dev, "[FG_DATA] %d %d %d %d %d %d %d %d %d " | ||
1613 | "%d %d %d %d %d %d %d\n", | ||
1614 | di->bat_cap.max_mah_design, | ||
1615 | di->bat_cap.mah, | ||
1616 | di->bat_cap.permille, | ||
1617 | di->bat_cap.level, | ||
1618 | di->bat_cap.prev_mah, | ||
1619 | di->bat_cap.prev_percent, | ||
1620 | di->bat_cap.prev_level, | ||
1621 | di->vbat, | ||
1622 | di->inst_curr, | ||
1623 | di->avg_curr, | ||
1624 | di->accu_charge, | ||
1625 | di->flags.charging, | ||
1626 | di->charge_state, | ||
1627 | di->discharge_state, | ||
1628 | di->high_curr_mode, | ||
1629 | di->recovery_needed); | ||
1630 | } | ||
1631 | |||
1632 | /** | ||
1633 | * ab8500_fg_periodic_work() - Run the FG state machine periodically | ||
1634 | * @work: pointer to the work_struct structure | ||
1635 | * | ||
1636 | * Work queue function for periodic work | ||
1637 | */ | ||
1638 | static void ab8500_fg_periodic_work(struct work_struct *work) | ||
1639 | { | ||
1640 | struct ab8500_fg *di = container_of(work, struct ab8500_fg, | ||
1641 | fg_periodic_work.work); | ||
1642 | |||
1643 | if (di->init_capacity) { | ||
1644 | /* A dummy read that will return 0 */ | ||
1645 | di->inst_curr = ab8500_fg_inst_curr_blocking(di); | ||
1646 | /* Get an initial capacity calculation */ | ||
1647 | ab8500_fg_calc_cap_discharge_voltage(di, true); | ||
1648 | ab8500_fg_check_capacity_limits(di, true); | ||
1649 | di->init_capacity = false; | ||
1650 | |||
1651 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | ||
1652 | } else if (di->flags.user_cap) { | ||
1653 | if (check_sysfs_capacity(di)) { | ||
1654 | ab8500_fg_check_capacity_limits(di, true); | ||
1655 | if (di->flags.charging) | ||
1656 | ab8500_fg_charge_state_to(di, | ||
1657 | AB8500_FG_CHARGE_INIT); | ||
1658 | else | ||
1659 | ab8500_fg_discharge_state_to(di, | ||
1660 | AB8500_FG_DISCHARGE_READOUT_INIT); | ||
1661 | } | ||
1662 | di->flags.user_cap = false; | ||
1663 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | ||
1664 | } else | ||
1665 | ab8500_fg_algorithm(di); | ||
1666 | |||
1667 | } | ||
1668 | |||
1669 | /** | ||
1670 | * ab8500_fg_check_hw_failure_work() - Check OVV_BAT condition | ||
1671 | * @work: pointer to the work_struct structure | ||
1672 | * | ||
1673 | * Work queue function for checking the OVV_BAT condition | ||
1674 | */ | ||
1675 | static void ab8500_fg_check_hw_failure_work(struct work_struct *work) | ||
1676 | { | ||
1677 | int ret; | ||
1678 | u8 reg_value; | ||
1679 | |||
1680 | struct ab8500_fg *di = container_of(work, struct ab8500_fg, | ||
1681 | fg_check_hw_failure_work.work); | ||
1682 | |||
1683 | /* | ||
1684 | * If we have had a battery over-voltage situation, | ||
1685 | * check ovv-bit to see if it should be reset. | ||
1686 | */ | ||
1687 | if (di->flags.bat_ovv) { | ||
1688 | ret = abx500_get_register_interruptible(di->dev, | ||
1689 | AB8500_CHARGER, AB8500_CH_STAT_REG, | ||
1690 | ®_value); | ||
1691 | if (ret < 0) { | ||
1692 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | ||
1693 | return; | ||
1694 | } | ||
1695 | if ((reg_value & BATT_OVV) != BATT_OVV) { | ||
1696 | dev_dbg(di->dev, "Battery recovered from OVV\n"); | ||
1697 | di->flags.bat_ovv = false; | ||
1698 | power_supply_changed(&di->fg_psy); | ||
1699 | return; | ||
1700 | } | ||
1701 | |||
1702 | /* Not yet recovered from ovv, reschedule this test */ | ||
1703 | queue_delayed_work(di->fg_wq, &di->fg_check_hw_failure_work, | ||
1704 | round_jiffies(HZ)); | ||
1705 | } | ||
1706 | } | ||
1707 | |||
1708 | /** | ||
1709 | * ab8500_fg_low_bat_work() - Check LOW_BAT condition | ||
1710 | * @work: pointer to the work_struct structure | ||
1711 | * | ||
1712 | * Work queue function for checking the LOW_BAT condition | ||
1713 | */ | ||
1714 | static void ab8500_fg_low_bat_work(struct work_struct *work) | ||
1715 | { | ||
1716 | int vbat; | ||
1717 | |||
1718 | struct ab8500_fg *di = container_of(work, struct ab8500_fg, | ||
1719 | fg_low_bat_work.work); | ||
1720 | |||
1721 | vbat = ab8500_fg_bat_voltage(di); | ||
1722 | |||
1723 | /* Check if LOW_BAT still fulfilled */ | ||
1724 | if (vbat < di->bat->fg_params->lowbat_threshold) { | ||
1725 | di->flags.low_bat = true; | ||
1726 | dev_warn(di->dev, "Battery voltage still LOW\n"); | ||
1727 | |||
1728 | /* | ||
1729 | * We need to re-schedule this check to be able to detect | ||
1730 | * if the voltage increases again during charging | ||
1731 | */ | ||
1732 | queue_delayed_work(di->fg_wq, &di->fg_low_bat_work, | ||
1733 | round_jiffies(LOW_BAT_CHECK_INTERVAL)); | ||
1734 | } else { | ||
1735 | di->flags.low_bat = false; | ||
1736 | dev_warn(di->dev, "Battery voltage OK again\n"); | ||
1737 | } | ||
1738 | |||
1739 | /* This is needed to dispatch LOW_BAT */ | ||
1740 | ab8500_fg_check_capacity_limits(di, false); | ||
1741 | |||
1742 | /* Set this flag to check if LOW_BAT IRQ still occurs */ | ||
1743 | di->flags.low_bat_delay = false; | ||
1744 | } | ||
1745 | |||
1746 | /** | ||
1747 | * ab8500_fg_battok_calc - calculate the bit pattern corresponding | ||
1748 | * to the target voltage. | ||
1749 | * @di: pointer to the ab8500_fg structure | ||
1750 | * @target target voltage | ||
1751 | * | ||
1752 | * Returns bit pattern closest to the target voltage | ||
1753 | * valid return values are 0-14. (0-BATT_OK_MAX_NR_INCREMENTS) | ||
1754 | */ | ||
1755 | |||
1756 | static int ab8500_fg_battok_calc(struct ab8500_fg *di, int target) | ||
1757 | { | ||
1758 | if (target > BATT_OK_MIN + | ||
1759 | (BATT_OK_INCREMENT * BATT_OK_MAX_NR_INCREMENTS)) | ||
1760 | return BATT_OK_MAX_NR_INCREMENTS; | ||
1761 | if (target < BATT_OK_MIN) | ||
1762 | return 0; | ||
1763 | return (target - BATT_OK_MIN) / BATT_OK_INCREMENT; | ||
1764 | } | ||
1765 | |||
1766 | /** | ||
1767 | * ab8500_fg_battok_init_hw_register - init battok levels | ||
1768 | * @di: pointer to the ab8500_fg structure | ||
1769 | * | ||
1770 | */ | ||
1771 | |||
1772 | static int ab8500_fg_battok_init_hw_register(struct ab8500_fg *di) | ||
1773 | { | ||
1774 | int selected; | ||
1775 | int sel0; | ||
1776 | int sel1; | ||
1777 | int cbp_sel0; | ||
1778 | int cbp_sel1; | ||
1779 | int ret; | ||
1780 | int new_val; | ||
1781 | |||
1782 | sel0 = di->bat->fg_params->battok_falling_th_sel0; | ||
1783 | sel1 = di->bat->fg_params->battok_raising_th_sel1; | ||
1784 | |||
1785 | cbp_sel0 = ab8500_fg_battok_calc(di, sel0); | ||
1786 | cbp_sel1 = ab8500_fg_battok_calc(di, sel1); | ||
1787 | |||
1788 | selected = BATT_OK_MIN + cbp_sel0 * BATT_OK_INCREMENT; | ||
1789 | |||
1790 | if (selected != sel0) | ||
1791 | dev_warn(di->dev, "Invalid voltage step:%d, using %d %d\n", | ||
1792 | sel0, selected, cbp_sel0); | ||
1793 | |||
1794 | selected = BATT_OK_MIN + cbp_sel1 * BATT_OK_INCREMENT; | ||
1795 | |||
1796 | if (selected != sel1) | ||
1797 | dev_warn(di->dev, "Invalid voltage step:%d, using %d %d\n", | ||
1798 | sel1, selected, cbp_sel1); | ||
1799 | |||
1800 | new_val = cbp_sel0 | (cbp_sel1 << 4); | ||
1801 | |||
1802 | dev_dbg(di->dev, "using: %x %d %d\n", new_val, cbp_sel0, cbp_sel1); | ||
1803 | ret = abx500_set_register_interruptible(di->dev, AB8500_SYS_CTRL2_BLOCK, | ||
1804 | AB8500_BATT_OK_REG, new_val); | ||
1805 | return ret; | ||
1806 | } | ||
1807 | |||
1808 | /** | ||
1809 | * ab8500_fg_instant_work() - Run the FG state machine instantly | ||
1810 | * @work: pointer to the work_struct structure | ||
1811 | * | ||
1812 | * Work queue function for instant work | ||
1813 | */ | ||
1814 | static void ab8500_fg_instant_work(struct work_struct *work) | ||
1815 | { | ||
1816 | struct ab8500_fg *di = container_of(work, struct ab8500_fg, fg_work); | ||
1817 | |||
1818 | ab8500_fg_algorithm(di); | ||
1819 | } | ||
1820 | |||
1821 | /** | ||
1822 | * ab8500_fg_cc_data_end_handler() - isr to get battery avg current. | ||
1823 | * @irq: interrupt number | ||
1824 | * @_di: pointer to the ab8500_fg structure | ||
1825 | * | ||
1826 | * Returns IRQ status(IRQ_HANDLED) | ||
1827 | */ | ||
1828 | static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di) | ||
1829 | { | ||
1830 | struct ab8500_fg *di = _di; | ||
1831 | complete(&di->ab8500_fg_complete); | ||
1832 | return IRQ_HANDLED; | ||
1833 | } | ||
1834 | |||
1835 | /** | ||
1836 | * ab8500_fg_cc_convend_handler() - isr to get battery avg current. | ||
1837 | * @irq: interrupt number | ||
1838 | * @_di: pointer to the ab8500_fg structure | ||
1839 | * | ||
1840 | * Returns IRQ status(IRQ_HANDLED) | ||
1841 | */ | ||
1842 | static irqreturn_t ab8500_fg_cc_int_calib_handler(int irq, void *_di) | ||
1843 | { | ||
1844 | struct ab8500_fg *di = _di; | ||
1845 | di->calib_state = AB8500_FG_CALIB_END; | ||
1846 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | ||
1847 | return IRQ_HANDLED; | ||
1848 | } | ||
1849 | |||
1850 | /** | ||
1851 | * ab8500_fg_cc_convend_handler() - isr to get battery avg current. | ||
1852 | * @irq: interrupt number | ||
1853 | * @_di: pointer to the ab8500_fg structure | ||
1854 | * | ||
1855 | * Returns IRQ status(IRQ_HANDLED) | ||
1856 | */ | ||
1857 | static irqreturn_t ab8500_fg_cc_convend_handler(int irq, void *_di) | ||
1858 | { | ||
1859 | struct ab8500_fg *di = _di; | ||
1860 | |||
1861 | queue_work(di->fg_wq, &di->fg_acc_cur_work); | ||
1862 | |||
1863 | return IRQ_HANDLED; | ||
1864 | } | ||
1865 | |||
1866 | /** | ||
1867 | * ab8500_fg_batt_ovv_handler() - Battery OVV occured | ||
1868 | * @irq: interrupt number | ||
1869 | * @_di: pointer to the ab8500_fg structure | ||
1870 | * | ||
1871 | * Returns IRQ status(IRQ_HANDLED) | ||
1872 | */ | ||
1873 | static irqreturn_t ab8500_fg_batt_ovv_handler(int irq, void *_di) | ||
1874 | { | ||
1875 | struct ab8500_fg *di = _di; | ||
1876 | |||
1877 | dev_dbg(di->dev, "Battery OVV\n"); | ||
1878 | di->flags.bat_ovv = true; | ||
1879 | power_supply_changed(&di->fg_psy); | ||
1880 | |||
1881 | /* Schedule a new HW failure check */ | ||
1882 | queue_delayed_work(di->fg_wq, &di->fg_check_hw_failure_work, 0); | ||
1883 | |||
1884 | return IRQ_HANDLED; | ||
1885 | } | ||
1886 | |||
1887 | /** | ||
1888 | * ab8500_fg_lowbatf_handler() - Battery voltage is below LOW threshold | ||
1889 | * @irq: interrupt number | ||
1890 | * @_di: pointer to the ab8500_fg structure | ||
1891 | * | ||
1892 | * Returns IRQ status(IRQ_HANDLED) | ||
1893 | */ | ||
1894 | static irqreturn_t ab8500_fg_lowbatf_handler(int irq, void *_di) | ||
1895 | { | ||
1896 | struct ab8500_fg *di = _di; | ||
1897 | |||
1898 | if (!di->flags.low_bat_delay) { | ||
1899 | dev_warn(di->dev, "Battery voltage is below LOW threshold\n"); | ||
1900 | di->flags.low_bat_delay = true; | ||
1901 | /* | ||
1902 | * Start a timer to check LOW_BAT again after some time | ||
1903 | * This is done to avoid shutdown on single voltage dips | ||
1904 | */ | ||
1905 | queue_delayed_work(di->fg_wq, &di->fg_low_bat_work, | ||
1906 | round_jiffies(LOW_BAT_CHECK_INTERVAL)); | ||
1907 | } | ||
1908 | return IRQ_HANDLED; | ||
1909 | } | ||
1910 | |||
1911 | /** | ||
1912 | * ab8500_fg_get_property() - get the fg properties | ||
1913 | * @psy: pointer to the power_supply structure | ||
1914 | * @psp: pointer to the power_supply_property structure | ||
1915 | * @val: pointer to the power_supply_propval union | ||
1916 | * | ||
1917 | * This function gets called when an application tries to get the | ||
1918 | * fg properties by reading the sysfs files. | ||
1919 | * voltage_now: battery voltage | ||
1920 | * current_now: battery instant current | ||
1921 | * current_avg: battery average current | ||
1922 | * charge_full_design: capacity where battery is considered full | ||
1923 | * charge_now: battery capacity in nAh | ||
1924 | * capacity: capacity in percent | ||
1925 | * capacity_level: capacity level | ||
1926 | * | ||
1927 | * Returns error code in case of failure else 0 on success | ||
1928 | */ | ||
1929 | static int ab8500_fg_get_property(struct power_supply *psy, | ||
1930 | enum power_supply_property psp, | ||
1931 | union power_supply_propval *val) | ||
1932 | { | ||
1933 | struct ab8500_fg *di; | ||
1934 | |||
1935 | di = to_ab8500_fg_device_info(psy); | ||
1936 | |||
1937 | /* | ||
1938 | * If battery is identified as unknown and charging of unknown | ||
1939 | * batteries is disabled, we always report 100% capacity and | ||
1940 | * capacity level UNKNOWN, since we can't calculate | ||
1941 | * remaining capacity | ||
1942 | */ | ||
1943 | |||
1944 | switch (psp) { | ||
1945 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
1946 | if (di->flags.bat_ovv) | ||
1947 | val->intval = BATT_OVV_VALUE * 1000; | ||
1948 | else | ||
1949 | val->intval = di->vbat * 1000; | ||
1950 | break; | ||
1951 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
1952 | val->intval = di->inst_curr * 1000; | ||
1953 | break; | ||
1954 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
1955 | val->intval = di->avg_curr * 1000; | ||
1956 | break; | ||
1957 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: | ||
1958 | val->intval = ab8500_fg_convert_mah_to_uwh(di, | ||
1959 | di->bat_cap.max_mah_design); | ||
1960 | break; | ||
1961 | case POWER_SUPPLY_PROP_ENERGY_FULL: | ||
1962 | val->intval = ab8500_fg_convert_mah_to_uwh(di, | ||
1963 | di->bat_cap.max_mah); | ||
1964 | break; | ||
1965 | case POWER_SUPPLY_PROP_ENERGY_NOW: | ||
1966 | if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && | ||
1967 | di->flags.batt_id_received) | ||
1968 | val->intval = ab8500_fg_convert_mah_to_uwh(di, | ||
1969 | di->bat_cap.max_mah); | ||
1970 | else | ||
1971 | val->intval = ab8500_fg_convert_mah_to_uwh(di, | ||
1972 | di->bat_cap.prev_mah); | ||
1973 | break; | ||
1974 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
1975 | val->intval = di->bat_cap.max_mah_design; | ||
1976 | break; | ||
1977 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
1978 | val->intval = di->bat_cap.max_mah; | ||
1979 | break; | ||
1980 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
1981 | if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && | ||
1982 | di->flags.batt_id_received) | ||
1983 | val->intval = di->bat_cap.max_mah; | ||
1984 | else | ||
1985 | val->intval = di->bat_cap.prev_mah; | ||
1986 | break; | ||
1987 | case POWER_SUPPLY_PROP_CAPACITY: | ||
1988 | if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && | ||
1989 | di->flags.batt_id_received) | ||
1990 | val->intval = 100; | ||
1991 | else | ||
1992 | val->intval = di->bat_cap.prev_percent; | ||
1993 | break; | ||
1994 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: | ||
1995 | if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && | ||
1996 | di->flags.batt_id_received) | ||
1997 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; | ||
1998 | else | ||
1999 | val->intval = di->bat_cap.prev_level; | ||
2000 | break; | ||
2001 | default: | ||
2002 | return -EINVAL; | ||
2003 | } | ||
2004 | return 0; | ||
2005 | } | ||
2006 | |||
2007 | static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data) | ||
2008 | { | ||
2009 | struct power_supply *psy; | ||
2010 | struct power_supply *ext; | ||
2011 | struct ab8500_fg *di; | ||
2012 | union power_supply_propval ret; | ||
2013 | int i, j; | ||
2014 | bool psy_found = false; | ||
2015 | |||
2016 | psy = (struct power_supply *)data; | ||
2017 | ext = dev_get_drvdata(dev); | ||
2018 | di = to_ab8500_fg_device_info(psy); | ||
2019 | |||
2020 | /* | ||
2021 | * For all psy where the name of your driver | ||
2022 | * appears in any supplied_to | ||
2023 | */ | ||
2024 | for (i = 0; i < ext->num_supplicants; i++) { | ||
2025 | if (!strcmp(ext->supplied_to[i], psy->name)) | ||
2026 | psy_found = true; | ||
2027 | } | ||
2028 | |||
2029 | if (!psy_found) | ||
2030 | return 0; | ||
2031 | |||
2032 | /* Go through all properties for the psy */ | ||
2033 | for (j = 0; j < ext->num_properties; j++) { | ||
2034 | enum power_supply_property prop; | ||
2035 | prop = ext->properties[j]; | ||
2036 | |||
2037 | if (ext->get_property(ext, prop, &ret)) | ||
2038 | continue; | ||
2039 | |||
2040 | switch (prop) { | ||
2041 | case POWER_SUPPLY_PROP_STATUS: | ||
2042 | switch (ext->type) { | ||
2043 | case POWER_SUPPLY_TYPE_BATTERY: | ||
2044 | switch (ret.intval) { | ||
2045 | case POWER_SUPPLY_STATUS_UNKNOWN: | ||
2046 | case POWER_SUPPLY_STATUS_DISCHARGING: | ||
2047 | case POWER_SUPPLY_STATUS_NOT_CHARGING: | ||
2048 | if (!di->flags.charging) | ||
2049 | break; | ||
2050 | di->flags.charging = false; | ||
2051 | di->flags.fully_charged = false; | ||
2052 | queue_work(di->fg_wq, &di->fg_work); | ||
2053 | break; | ||
2054 | case POWER_SUPPLY_STATUS_FULL: | ||
2055 | if (di->flags.fully_charged) | ||
2056 | break; | ||
2057 | di->flags.fully_charged = true; | ||
2058 | di->flags.force_full = true; | ||
2059 | /* Save current capacity as maximum */ | ||
2060 | di->bat_cap.max_mah = di->bat_cap.mah; | ||
2061 | queue_work(di->fg_wq, &di->fg_work); | ||
2062 | break; | ||
2063 | case POWER_SUPPLY_STATUS_CHARGING: | ||
2064 | if (di->flags.charging) | ||
2065 | break; | ||
2066 | di->flags.charging = true; | ||
2067 | di->flags.fully_charged = false; | ||
2068 | queue_work(di->fg_wq, &di->fg_work); | ||
2069 | break; | ||
2070 | }; | ||
2071 | default: | ||
2072 | break; | ||
2073 | }; | ||
2074 | break; | ||
2075 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
2076 | switch (ext->type) { | ||
2077 | case POWER_SUPPLY_TYPE_BATTERY: | ||
2078 | if (!di->flags.batt_id_received) { | ||
2079 | const struct abx500_battery_type *b; | ||
2080 | |||
2081 | b = &(di->bat->bat_type[di->bat->batt_id]); | ||
2082 | |||
2083 | di->flags.batt_id_received = true; | ||
2084 | |||
2085 | di->bat_cap.max_mah_design = | ||
2086 | MILLI_TO_MICRO * | ||
2087 | b->charge_full_design; | ||
2088 | |||
2089 | di->bat_cap.max_mah = | ||
2090 | di->bat_cap.max_mah_design; | ||
2091 | |||
2092 | di->vbat_nom = b->nominal_voltage; | ||
2093 | } | ||
2094 | |||
2095 | if (ret.intval) | ||
2096 | di->flags.batt_unknown = false; | ||
2097 | else | ||
2098 | di->flags.batt_unknown = true; | ||
2099 | break; | ||
2100 | default: | ||
2101 | break; | ||
2102 | } | ||
2103 | break; | ||
2104 | case POWER_SUPPLY_PROP_TEMP: | ||
2105 | switch (ext->type) { | ||
2106 | case POWER_SUPPLY_TYPE_BATTERY: | ||
2107 | if (di->flags.batt_id_received) | ||
2108 | di->bat_temp = ret.intval; | ||
2109 | break; | ||
2110 | default: | ||
2111 | break; | ||
2112 | } | ||
2113 | break; | ||
2114 | default: | ||
2115 | break; | ||
2116 | } | ||
2117 | } | ||
2118 | return 0; | ||
2119 | } | ||
2120 | |||
2121 | /** | ||
2122 | * ab8500_fg_init_hw_registers() - Set up FG related registers | ||
2123 | * @di: pointer to the ab8500_fg structure | ||
2124 | * | ||
2125 | * Set up battery OVV, low battery voltage registers | ||
2126 | */ | ||
2127 | static int ab8500_fg_init_hw_registers(struct ab8500_fg *di) | ||
2128 | { | ||
2129 | int ret; | ||
2130 | |||
2131 | /* Set VBAT OVV threshold */ | ||
2132 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
2133 | AB8500_CHARGER, | ||
2134 | AB8500_BATT_OVV, | ||
2135 | BATT_OVV_TH_4P75, | ||
2136 | BATT_OVV_TH_4P75); | ||
2137 | if (ret) { | ||
2138 | dev_err(di->dev, "failed to set BATT_OVV\n"); | ||
2139 | goto out; | ||
2140 | } | ||
2141 | |||
2142 | /* Enable VBAT OVV detection */ | ||
2143 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
2144 | AB8500_CHARGER, | ||
2145 | AB8500_BATT_OVV, | ||
2146 | BATT_OVV_ENA, | ||
2147 | BATT_OVV_ENA); | ||
2148 | if (ret) { | ||
2149 | dev_err(di->dev, "failed to enable BATT_OVV\n"); | ||
2150 | goto out; | ||
2151 | } | ||
2152 | |||
2153 | /* Low Battery Voltage */ | ||
2154 | ret = abx500_set_register_interruptible(di->dev, | ||
2155 | AB8500_SYS_CTRL2_BLOCK, | ||
2156 | AB8500_LOW_BAT_REG, | ||
2157 | ab8500_volt_to_regval( | ||
2158 | di->bat->fg_params->lowbat_threshold) << 1 | | ||
2159 | LOW_BAT_ENABLE); | ||
2160 | if (ret) { | ||
2161 | dev_err(di->dev, "%s write failed\n", __func__); | ||
2162 | goto out; | ||
2163 | } | ||
2164 | |||
2165 | /* Battery OK threshold */ | ||
2166 | ret = ab8500_fg_battok_init_hw_register(di); | ||
2167 | if (ret) { | ||
2168 | dev_err(di->dev, "BattOk init write failed.\n"); | ||
2169 | goto out; | ||
2170 | } | ||
2171 | out: | ||
2172 | return ret; | ||
2173 | } | ||
2174 | |||
2175 | /** | ||
2176 | * ab8500_fg_external_power_changed() - callback for power supply changes | ||
2177 | * @psy: pointer to the structure power_supply | ||
2178 | * | ||
2179 | * This function is the entry point of the pointer external_power_changed | ||
2180 | * of the structure power_supply. | ||
2181 | * This function gets executed when there is a change in any external power | ||
2182 | * supply that this driver needs to be notified of. | ||
2183 | */ | ||
2184 | static void ab8500_fg_external_power_changed(struct power_supply *psy) | ||
2185 | { | ||
2186 | struct ab8500_fg *di = to_ab8500_fg_device_info(psy); | ||
2187 | |||
2188 | class_for_each_device(power_supply_class, NULL, | ||
2189 | &di->fg_psy, ab8500_fg_get_ext_psy_data); | ||
2190 | } | ||
2191 | |||
2192 | /** | ||
2193 | * abab8500_fg_reinit_work() - work to reset the FG algorithm | ||
2194 | * @work: pointer to the work_struct structure | ||
2195 | * | ||
2196 | * Used to reset the current battery capacity to be able to | ||
2197 | * retrigger a new voltage base capacity calculation. For | ||
2198 | * test and verification purpose. | ||
2199 | */ | ||
2200 | static void ab8500_fg_reinit_work(struct work_struct *work) | ||
2201 | { | ||
2202 | struct ab8500_fg *di = container_of(work, struct ab8500_fg, | ||
2203 | fg_reinit_work.work); | ||
2204 | |||
2205 | if (di->flags.calibrate == false) { | ||
2206 | dev_dbg(di->dev, "Resetting FG state machine to init.\n"); | ||
2207 | ab8500_fg_clear_cap_samples(di); | ||
2208 | ab8500_fg_calc_cap_discharge_voltage(di, true); | ||
2209 | ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); | ||
2210 | ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); | ||
2211 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | ||
2212 | |||
2213 | } else { | ||
2214 | dev_err(di->dev, "Residual offset calibration ongoing " | ||
2215 | "retrying..\n"); | ||
2216 | /* Wait one second until next try*/ | ||
2217 | queue_delayed_work(di->fg_wq, &di->fg_reinit_work, | ||
2218 | round_jiffies(1)); | ||
2219 | } | ||
2220 | } | ||
2221 | |||
2222 | /** | ||
2223 | * ab8500_fg_reinit() - forces FG algorithm to reinitialize with current values | ||
2224 | * | ||
2225 | * This function can be used to force the FG algorithm to recalculate a new | ||
2226 | * voltage based battery capacity. | ||
2227 | */ | ||
2228 | void ab8500_fg_reinit(void) | ||
2229 | { | ||
2230 | struct ab8500_fg *di = ab8500_fg_get(); | ||
2231 | /* User won't be notified if a null pointer returned. */ | ||
2232 | if (di != NULL) | ||
2233 | queue_delayed_work(di->fg_wq, &di->fg_reinit_work, 0); | ||
2234 | } | ||
2235 | |||
2236 | /* Exposure to the sysfs interface */ | ||
2237 | |||
2238 | struct ab8500_fg_sysfs_entry { | ||
2239 | struct attribute attr; | ||
2240 | ssize_t (*show)(struct ab8500_fg *, char *); | ||
2241 | ssize_t (*store)(struct ab8500_fg *, const char *, size_t); | ||
2242 | }; | ||
2243 | |||
2244 | static ssize_t charge_full_show(struct ab8500_fg *di, char *buf) | ||
2245 | { | ||
2246 | return sprintf(buf, "%d\n", di->bat_cap.max_mah); | ||
2247 | } | ||
2248 | |||
2249 | static ssize_t charge_full_store(struct ab8500_fg *di, const char *buf, | ||
2250 | size_t count) | ||
2251 | { | ||
2252 | unsigned long charge_full; | ||
2253 | ssize_t ret = -EINVAL; | ||
2254 | |||
2255 | ret = strict_strtoul(buf, 10, &charge_full); | ||
2256 | |||
2257 | dev_dbg(di->dev, "Ret %zd charge_full %lu", ret, charge_full); | ||
2258 | |||
2259 | if (!ret) { | ||
2260 | di->bat_cap.max_mah = (int) charge_full; | ||
2261 | ret = count; | ||
2262 | } | ||
2263 | return ret; | ||
2264 | } | ||
2265 | |||
2266 | static ssize_t charge_now_show(struct ab8500_fg *di, char *buf) | ||
2267 | { | ||
2268 | return sprintf(buf, "%d\n", di->bat_cap.prev_mah); | ||
2269 | } | ||
2270 | |||
2271 | static ssize_t charge_now_store(struct ab8500_fg *di, const char *buf, | ||
2272 | size_t count) | ||
2273 | { | ||
2274 | unsigned long charge_now; | ||
2275 | ssize_t ret; | ||
2276 | |||
2277 | ret = strict_strtoul(buf, 10, &charge_now); | ||
2278 | |||
2279 | dev_dbg(di->dev, "Ret %zd charge_now %lu was %d", | ||
2280 | ret, charge_now, di->bat_cap.prev_mah); | ||
2281 | |||
2282 | if (!ret) { | ||
2283 | di->bat_cap.user_mah = (int) charge_now; | ||
2284 | di->flags.user_cap = true; | ||
2285 | ret = count; | ||
2286 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | ||
2287 | } | ||
2288 | return ret; | ||
2289 | } | ||
2290 | |||
2291 | static struct ab8500_fg_sysfs_entry charge_full_attr = | ||
2292 | __ATTR(charge_full, 0644, charge_full_show, charge_full_store); | ||
2293 | |||
2294 | static struct ab8500_fg_sysfs_entry charge_now_attr = | ||
2295 | __ATTR(charge_now, 0644, charge_now_show, charge_now_store); | ||
2296 | |||
2297 | static ssize_t | ||
2298 | ab8500_fg_show(struct kobject *kobj, struct attribute *attr, char *buf) | ||
2299 | { | ||
2300 | struct ab8500_fg_sysfs_entry *entry; | ||
2301 | struct ab8500_fg *di; | ||
2302 | |||
2303 | entry = container_of(attr, struct ab8500_fg_sysfs_entry, attr); | ||
2304 | di = container_of(kobj, struct ab8500_fg, fg_kobject); | ||
2305 | |||
2306 | if (!entry->show) | ||
2307 | return -EIO; | ||
2308 | |||
2309 | return entry->show(di, buf); | ||
2310 | } | ||
2311 | static ssize_t | ||
2312 | ab8500_fg_store(struct kobject *kobj, struct attribute *attr, const char *buf, | ||
2313 | size_t count) | ||
2314 | { | ||
2315 | struct ab8500_fg_sysfs_entry *entry; | ||
2316 | struct ab8500_fg *di; | ||
2317 | |||
2318 | entry = container_of(attr, struct ab8500_fg_sysfs_entry, attr); | ||
2319 | di = container_of(kobj, struct ab8500_fg, fg_kobject); | ||
2320 | |||
2321 | if (!entry->store) | ||
2322 | return -EIO; | ||
2323 | |||
2324 | return entry->store(di, buf, count); | ||
2325 | } | ||
2326 | |||
2327 | static const struct sysfs_ops ab8500_fg_sysfs_ops = { | ||
2328 | .show = ab8500_fg_show, | ||
2329 | .store = ab8500_fg_store, | ||
2330 | }; | ||
2331 | |||
2332 | static struct attribute *ab8500_fg_attrs[] = { | ||
2333 | &charge_full_attr.attr, | ||
2334 | &charge_now_attr.attr, | ||
2335 | NULL, | ||
2336 | }; | ||
2337 | |||
2338 | static struct kobj_type ab8500_fg_ktype = { | ||
2339 | .sysfs_ops = &ab8500_fg_sysfs_ops, | ||
2340 | .default_attrs = ab8500_fg_attrs, | ||
2341 | }; | ||
2342 | |||
2343 | /** | ||
2344 | * ab8500_chargalg_sysfs_exit() - de-init of sysfs entry | ||
2345 | * @di: pointer to the struct ab8500_chargalg | ||
2346 | * | ||
2347 | * This function removes the entry in sysfs. | ||
2348 | */ | ||
2349 | static void ab8500_fg_sysfs_exit(struct ab8500_fg *di) | ||
2350 | { | ||
2351 | kobject_del(&di->fg_kobject); | ||
2352 | } | ||
2353 | |||
2354 | /** | ||
2355 | * ab8500_chargalg_sysfs_init() - init of sysfs entry | ||
2356 | * @di: pointer to the struct ab8500_chargalg | ||
2357 | * | ||
2358 | * This function adds an entry in sysfs. | ||
2359 | * Returns error code in case of failure else 0(on success) | ||
2360 | */ | ||
2361 | static int ab8500_fg_sysfs_init(struct ab8500_fg *di) | ||
2362 | { | ||
2363 | int ret = 0; | ||
2364 | |||
2365 | ret = kobject_init_and_add(&di->fg_kobject, | ||
2366 | &ab8500_fg_ktype, | ||
2367 | NULL, "battery"); | ||
2368 | if (ret < 0) | ||
2369 | dev_err(di->dev, "failed to create sysfs entry\n"); | ||
2370 | |||
2371 | return ret; | ||
2372 | } | ||
2373 | /* Exposure to the sysfs interface <<END>> */ | ||
2374 | |||
2375 | #if defined(CONFIG_PM) | ||
2376 | static int ab8500_fg_resume(struct platform_device *pdev) | ||
2377 | { | ||
2378 | struct ab8500_fg *di = platform_get_drvdata(pdev); | ||
2379 | |||
2380 | /* | ||
2381 | * Change state if we're not charging. If we're charging we will wake | ||
2382 | * up on the FG IRQ | ||
2383 | */ | ||
2384 | if (!di->flags.charging) { | ||
2385 | ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_WAKEUP); | ||
2386 | queue_work(di->fg_wq, &di->fg_work); | ||
2387 | } | ||
2388 | |||
2389 | return 0; | ||
2390 | } | ||
2391 | |||
2392 | static int ab8500_fg_suspend(struct platform_device *pdev, | ||
2393 | pm_message_t state) | ||
2394 | { | ||
2395 | struct ab8500_fg *di = platform_get_drvdata(pdev); | ||
2396 | |||
2397 | flush_delayed_work(&di->fg_periodic_work); | ||
2398 | |||
2399 | /* | ||
2400 | * If the FG is enabled we will disable it before going to suspend | ||
2401 | * only if we're not charging | ||
2402 | */ | ||
2403 | if (di->flags.fg_enabled && !di->flags.charging) | ||
2404 | ab8500_fg_coulomb_counter(di, false); | ||
2405 | |||
2406 | return 0; | ||
2407 | } | ||
2408 | #else | ||
2409 | #define ab8500_fg_suspend NULL | ||
2410 | #define ab8500_fg_resume NULL | ||
2411 | #endif | ||
2412 | |||
2413 | static int ab8500_fg_remove(struct platform_device *pdev) | ||
2414 | { | ||
2415 | int ret = 0; | ||
2416 | struct ab8500_fg *di = platform_get_drvdata(pdev); | ||
2417 | |||
2418 | list_del(&di->node); | ||
2419 | |||
2420 | /* Disable coulomb counter */ | ||
2421 | ret = ab8500_fg_coulomb_counter(di, false); | ||
2422 | if (ret) | ||
2423 | dev_err(di->dev, "failed to disable coulomb counter\n"); | ||
2424 | |||
2425 | destroy_workqueue(di->fg_wq); | ||
2426 | ab8500_fg_sysfs_exit(di); | ||
2427 | |||
2428 | flush_scheduled_work(); | ||
2429 | power_supply_unregister(&di->fg_psy); | ||
2430 | platform_set_drvdata(pdev, NULL); | ||
2431 | return ret; | ||
2432 | } | ||
2433 | |||
2434 | /* ab8500 fg driver interrupts and their respective isr */ | ||
2435 | static struct ab8500_fg_interrupts ab8500_fg_irq[] = { | ||
2436 | {"NCONV_ACCU", ab8500_fg_cc_convend_handler}, | ||
2437 | {"BATT_OVV", ab8500_fg_batt_ovv_handler}, | ||
2438 | {"LOW_BAT_F", ab8500_fg_lowbatf_handler}, | ||
2439 | {"CC_INT_CALIB", ab8500_fg_cc_int_calib_handler}, | ||
2440 | {"CCEOC", ab8500_fg_cc_data_end_handler}, | ||
2441 | }; | ||
2442 | |||
2443 | static char *supply_interface[] = { | ||
2444 | "ab8500_chargalg", | ||
2445 | "ab8500_usb", | ||
2446 | }; | ||
2447 | |||
2448 | static int ab8500_fg_probe(struct platform_device *pdev) | ||
2449 | { | ||
2450 | struct device_node *np = pdev->dev.of_node; | ||
2451 | struct ab8500_fg *di; | ||
2452 | int i, irq; | ||
2453 | int ret = 0; | ||
2454 | |||
2455 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); | ||
2456 | if (!di) { | ||
2457 | dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__); | ||
2458 | return -ENOMEM; | ||
2459 | } | ||
2460 | di->bat = pdev->mfd_cell->platform_data; | ||
2461 | if (!di->bat) { | ||
2462 | if (np) { | ||
2463 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | ||
2464 | if (ret) { | ||
2465 | dev_err(&pdev->dev, | ||
2466 | "failed to get battery information\n"); | ||
2467 | return ret; | ||
2468 | } | ||
2469 | } else { | ||
2470 | dev_err(&pdev->dev, "missing dt node for ab8500_fg\n"); | ||
2471 | return -EINVAL; | ||
2472 | } | ||
2473 | } else { | ||
2474 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
2475 | } | ||
2476 | |||
2477 | mutex_init(&di->cc_lock); | ||
2478 | |||
2479 | /* get parent data */ | ||
2480 | di->dev = &pdev->dev; | ||
2481 | di->parent = dev_get_drvdata(pdev->dev.parent); | ||
2482 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
2483 | |||
2484 | di->fg_psy.name = "ab8500_fg"; | ||
2485 | di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY; | ||
2486 | di->fg_psy.properties = ab8500_fg_props; | ||
2487 | di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props); | ||
2488 | di->fg_psy.get_property = ab8500_fg_get_property; | ||
2489 | di->fg_psy.supplied_to = supply_interface; | ||
2490 | di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface), | ||
2491 | di->fg_psy.external_power_changed = ab8500_fg_external_power_changed; | ||
2492 | |||
2493 | di->bat_cap.max_mah_design = MILLI_TO_MICRO * | ||
2494 | di->bat->bat_type[di->bat->batt_id].charge_full_design; | ||
2495 | |||
2496 | di->bat_cap.max_mah = di->bat_cap.max_mah_design; | ||
2497 | |||
2498 | di->vbat_nom = di->bat->bat_type[di->bat->batt_id].nominal_voltage; | ||
2499 | |||
2500 | di->init_capacity = true; | ||
2501 | |||
2502 | ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); | ||
2503 | ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); | ||
2504 | |||
2505 | /* Create a work queue for running the FG algorithm */ | ||
2506 | di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq"); | ||
2507 | if (di->fg_wq == NULL) { | ||
2508 | dev_err(di->dev, "failed to create work queue\n"); | ||
2509 | return -ENOMEM; | ||
2510 | } | ||
2511 | |||
2512 | /* Init work for running the fg algorithm instantly */ | ||
2513 | INIT_WORK(&di->fg_work, ab8500_fg_instant_work); | ||
2514 | |||
2515 | /* Init work for getting the battery accumulated current */ | ||
2516 | INIT_WORK(&di->fg_acc_cur_work, ab8500_fg_acc_cur_work); | ||
2517 | |||
2518 | /* Init work for reinitialising the fg algorithm */ | ||
2519 | INIT_DEFERRABLE_WORK(&di->fg_reinit_work, | ||
2520 | ab8500_fg_reinit_work); | ||
2521 | |||
2522 | /* Work delayed Queue to run the state machine */ | ||
2523 | INIT_DEFERRABLE_WORK(&di->fg_periodic_work, | ||
2524 | ab8500_fg_periodic_work); | ||
2525 | |||
2526 | /* Work to check low battery condition */ | ||
2527 | INIT_DEFERRABLE_WORK(&di->fg_low_bat_work, | ||
2528 | ab8500_fg_low_bat_work); | ||
2529 | |||
2530 | /* Init work for HW failure check */ | ||
2531 | INIT_DEFERRABLE_WORK(&di->fg_check_hw_failure_work, | ||
2532 | ab8500_fg_check_hw_failure_work); | ||
2533 | |||
2534 | /* Initialize OVV, and other registers */ | ||
2535 | ret = ab8500_fg_init_hw_registers(di); | ||
2536 | if (ret) { | ||
2537 | dev_err(di->dev, "failed to initialize registers\n"); | ||
2538 | goto free_inst_curr_wq; | ||
2539 | } | ||
2540 | |||
2541 | /* Consider battery unknown until we're informed otherwise */ | ||
2542 | di->flags.batt_unknown = true; | ||
2543 | di->flags.batt_id_received = false; | ||
2544 | |||
2545 | /* Register FG power supply class */ | ||
2546 | ret = power_supply_register(di->dev, &di->fg_psy); | ||
2547 | if (ret) { | ||
2548 | dev_err(di->dev, "failed to register FG psy\n"); | ||
2549 | goto free_inst_curr_wq; | ||
2550 | } | ||
2551 | |||
2552 | di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); | ||
2553 | ab8500_fg_coulomb_counter(di, true); | ||
2554 | |||
2555 | /* Initialize completion used to notify completion of inst current */ | ||
2556 | init_completion(&di->ab8500_fg_complete); | ||
2557 | |||
2558 | /* Register interrupts */ | ||
2559 | for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq); i++) { | ||
2560 | irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); | ||
2561 | ret = request_threaded_irq(irq, NULL, ab8500_fg_irq[i].isr, | ||
2562 | IRQF_SHARED | IRQF_NO_SUSPEND, | ||
2563 | ab8500_fg_irq[i].name, di); | ||
2564 | |||
2565 | if (ret != 0) { | ||
2566 | dev_err(di->dev, "failed to request %s IRQ %d: %d\n" | ||
2567 | , ab8500_fg_irq[i].name, irq, ret); | ||
2568 | goto free_irq; | ||
2569 | } | ||
2570 | dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", | ||
2571 | ab8500_fg_irq[i].name, irq, ret); | ||
2572 | } | ||
2573 | di->irq = platform_get_irq_byname(pdev, "CCEOC"); | ||
2574 | disable_irq(di->irq); | ||
2575 | |||
2576 | platform_set_drvdata(pdev, di); | ||
2577 | |||
2578 | ret = ab8500_fg_sysfs_init(di); | ||
2579 | if (ret) { | ||
2580 | dev_err(di->dev, "failed to create sysfs entry\n"); | ||
2581 | goto free_irq; | ||
2582 | } | ||
2583 | |||
2584 | /* Calibrate the fg first time */ | ||
2585 | di->flags.calibrate = true; | ||
2586 | di->calib_state = AB8500_FG_CALIB_INIT; | ||
2587 | |||
2588 | /* Use room temp as default value until we get an update from driver. */ | ||
2589 | di->bat_temp = 210; | ||
2590 | |||
2591 | /* Run the FG algorithm */ | ||
2592 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | ||
2593 | |||
2594 | list_add_tail(&di->node, &ab8500_fg_list); | ||
2595 | |||
2596 | return ret; | ||
2597 | |||
2598 | free_irq: | ||
2599 | power_supply_unregister(&di->fg_psy); | ||
2600 | |||
2601 | /* We also have to free all successfully registered irqs */ | ||
2602 | for (i = i - 1; i >= 0; i--) { | ||
2603 | irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); | ||
2604 | free_irq(irq, di); | ||
2605 | } | ||
2606 | free_inst_curr_wq: | ||
2607 | destroy_workqueue(di->fg_wq); | ||
2608 | return ret; | ||
2609 | } | ||
2610 | |||
2611 | static const struct of_device_id ab8500_fg_match[] = { | ||
2612 | { .compatible = "stericsson,ab8500-fg", }, | ||
2613 | { }, | ||
2614 | }; | ||
2615 | |||
2616 | static struct platform_driver ab8500_fg_driver = { | ||
2617 | .probe = ab8500_fg_probe, | ||
2618 | .remove = ab8500_fg_remove, | ||
2619 | .suspend = ab8500_fg_suspend, | ||
2620 | .resume = ab8500_fg_resume, | ||
2621 | .driver = { | ||
2622 | .name = "ab8500-fg", | ||
2623 | .owner = THIS_MODULE, | ||
2624 | .of_match_table = ab8500_fg_match, | ||
2625 | }, | ||
2626 | }; | ||
2627 | |||
2628 | static int __init ab8500_fg_init(void) | ||
2629 | { | ||
2630 | return platform_driver_register(&ab8500_fg_driver); | ||
2631 | } | ||
2632 | |||
2633 | static void __exit ab8500_fg_exit(void) | ||
2634 | { | ||
2635 | platform_driver_unregister(&ab8500_fg_driver); | ||
2636 | } | ||
2637 | |||
2638 | subsys_initcall_sync(ab8500_fg_init); | ||
2639 | module_exit(ab8500_fg_exit); | ||
2640 | |||
2641 | MODULE_LICENSE("GPL v2"); | ||
2642 | MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); | ||
2643 | MODULE_ALIAS("platform:ab8500-fg"); | ||
2644 | MODULE_DESCRIPTION("AB8500 Fuel Gauge driver"); | ||
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c deleted file mode 100644 index 29708914606..00000000000 --- a/drivers/power/abx500_chargalg.c +++ /dev/null | |||
@@ -1,1941 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Charging algorithm driver for abx500 variants | ||
5 | * | ||
6 | * License Terms: GNU General Public License v2 | ||
7 | * Authors: | ||
8 | * Johan Palsson <johan.palsson@stericsson.com> | ||
9 | * Karl Komierowski <karl.komierowski@stericsson.com> | ||
10 | * Arun R Murthy <arun.murthy@stericsson.com> | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/power_supply.h> | ||
21 | #include <linux/completion.h> | ||
22 | #include <linux/workqueue.h> | ||
23 | #include <linux/kobject.h> | ||
24 | #include <linux/of.h> | ||
25 | #include <linux/mfd/core.h> | ||
26 | #include <linux/mfd/abx500.h> | ||
27 | #include <linux/mfd/abx500/ux500_chargalg.h> | ||
28 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
29 | |||
30 | /* Watchdog kick interval */ | ||
31 | #define CHG_WD_INTERVAL (6 * HZ) | ||
32 | |||
33 | /* End-of-charge criteria counter */ | ||
34 | #define EOC_COND_CNT 10 | ||
35 | |||
36 | /* Recharge criteria counter */ | ||
37 | #define RCH_COND_CNT 3 | ||
38 | |||
39 | #define to_abx500_chargalg_device_info(x) container_of((x), \ | ||
40 | struct abx500_chargalg, chargalg_psy); | ||
41 | |||
42 | enum abx500_chargers { | ||
43 | NO_CHG, | ||
44 | AC_CHG, | ||
45 | USB_CHG, | ||
46 | }; | ||
47 | |||
48 | struct abx500_chargalg_charger_info { | ||
49 | enum abx500_chargers conn_chg; | ||
50 | enum abx500_chargers prev_conn_chg; | ||
51 | enum abx500_chargers online_chg; | ||
52 | enum abx500_chargers prev_online_chg; | ||
53 | enum abx500_chargers charger_type; | ||
54 | bool usb_chg_ok; | ||
55 | bool ac_chg_ok; | ||
56 | int usb_volt; | ||
57 | int usb_curr; | ||
58 | int ac_volt; | ||
59 | int ac_curr; | ||
60 | int usb_vset; | ||
61 | int usb_iset; | ||
62 | int ac_vset; | ||
63 | int ac_iset; | ||
64 | }; | ||
65 | |||
66 | struct abx500_chargalg_suspension_status { | ||
67 | bool suspended_change; | ||
68 | bool ac_suspended; | ||
69 | bool usb_suspended; | ||
70 | }; | ||
71 | |||
72 | struct abx500_chargalg_battery_data { | ||
73 | int temp; | ||
74 | int volt; | ||
75 | int avg_curr; | ||
76 | int inst_curr; | ||
77 | int percent; | ||
78 | }; | ||
79 | |||
80 | enum abx500_chargalg_states { | ||
81 | STATE_HANDHELD_INIT, | ||
82 | STATE_HANDHELD, | ||
83 | STATE_CHG_NOT_OK_INIT, | ||
84 | STATE_CHG_NOT_OK, | ||
85 | STATE_HW_TEMP_PROTECT_INIT, | ||
86 | STATE_HW_TEMP_PROTECT, | ||
87 | STATE_NORMAL_INIT, | ||
88 | STATE_NORMAL, | ||
89 | STATE_WAIT_FOR_RECHARGE_INIT, | ||
90 | STATE_WAIT_FOR_RECHARGE, | ||
91 | STATE_MAINTENANCE_A_INIT, | ||
92 | STATE_MAINTENANCE_A, | ||
93 | STATE_MAINTENANCE_B_INIT, | ||
94 | STATE_MAINTENANCE_B, | ||
95 | STATE_TEMP_UNDEROVER_INIT, | ||
96 | STATE_TEMP_UNDEROVER, | ||
97 | STATE_TEMP_LOWHIGH_INIT, | ||
98 | STATE_TEMP_LOWHIGH, | ||
99 | STATE_SUSPENDED_INIT, | ||
100 | STATE_SUSPENDED, | ||
101 | STATE_OVV_PROTECT_INIT, | ||
102 | STATE_OVV_PROTECT, | ||
103 | STATE_SAFETY_TIMER_EXPIRED_INIT, | ||
104 | STATE_SAFETY_TIMER_EXPIRED, | ||
105 | STATE_BATT_REMOVED_INIT, | ||
106 | STATE_BATT_REMOVED, | ||
107 | STATE_WD_EXPIRED_INIT, | ||
108 | STATE_WD_EXPIRED, | ||
109 | }; | ||
110 | |||
111 | static const char *states[] = { | ||
112 | "HANDHELD_INIT", | ||
113 | "HANDHELD", | ||
114 | "CHG_NOT_OK_INIT", | ||
115 | "CHG_NOT_OK", | ||
116 | "HW_TEMP_PROTECT_INIT", | ||
117 | "HW_TEMP_PROTECT", | ||
118 | "NORMAL_INIT", | ||
119 | "NORMAL", | ||
120 | "WAIT_FOR_RECHARGE_INIT", | ||
121 | "WAIT_FOR_RECHARGE", | ||
122 | "MAINTENANCE_A_INIT", | ||
123 | "MAINTENANCE_A", | ||
124 | "MAINTENANCE_B_INIT", | ||
125 | "MAINTENANCE_B", | ||
126 | "TEMP_UNDEROVER_INIT", | ||
127 | "TEMP_UNDEROVER", | ||
128 | "TEMP_LOWHIGH_INIT", | ||
129 | "TEMP_LOWHIGH", | ||
130 | "SUSPENDED_INIT", | ||
131 | "SUSPENDED", | ||
132 | "OVV_PROTECT_INIT", | ||
133 | "OVV_PROTECT", | ||
134 | "SAFETY_TIMER_EXPIRED_INIT", | ||
135 | "SAFETY_TIMER_EXPIRED", | ||
136 | "BATT_REMOVED_INIT", | ||
137 | "BATT_REMOVED", | ||
138 | "WD_EXPIRED_INIT", | ||
139 | "WD_EXPIRED", | ||
140 | }; | ||
141 | |||
142 | struct abx500_chargalg_events { | ||
143 | bool batt_unknown; | ||
144 | bool mainextchnotok; | ||
145 | bool batt_ovv; | ||
146 | bool batt_rem; | ||
147 | bool btemp_underover; | ||
148 | bool btemp_lowhigh; | ||
149 | bool main_thermal_prot; | ||
150 | bool usb_thermal_prot; | ||
151 | bool main_ovv; | ||
152 | bool vbus_ovv; | ||
153 | bool usbchargernotok; | ||
154 | bool safety_timer_expired; | ||
155 | bool maintenance_timer_expired; | ||
156 | bool ac_wd_expired; | ||
157 | bool usb_wd_expired; | ||
158 | bool ac_cv_active; | ||
159 | bool usb_cv_active; | ||
160 | bool vbus_collapsed; | ||
161 | }; | ||
162 | |||
163 | /** | ||
164 | * struct abx500_charge_curr_maximization - Charger maximization parameters | ||
165 | * @original_iset: the non optimized/maximised charger current | ||
166 | * @current_iset: the charging current used at this moment | ||
167 | * @test_delta_i: the delta between the current we want to charge and the | ||
168 | current that is really going into the battery | ||
169 | * @condition_cnt: number of iterations needed before a new charger current | ||
170 | is set | ||
171 | * @max_current: maximum charger current | ||
172 | * @wait_cnt: to avoid too fast current step down in case of charger | ||
173 | * voltage collapse, we insert this delay between step | ||
174 | * down | ||
175 | * @level: tells in how many steps the charging current has been | ||
176 | increased | ||
177 | */ | ||
178 | struct abx500_charge_curr_maximization { | ||
179 | int original_iset; | ||
180 | int current_iset; | ||
181 | int test_delta_i; | ||
182 | int condition_cnt; | ||
183 | int max_current; | ||
184 | int wait_cnt; | ||
185 | u8 level; | ||
186 | }; | ||
187 | |||
188 | enum maxim_ret { | ||
189 | MAXIM_RET_NOACTION, | ||
190 | MAXIM_RET_CHANGE, | ||
191 | MAXIM_RET_IBAT_TOO_HIGH, | ||
192 | }; | ||
193 | |||
194 | /** | ||
195 | * struct abx500_chargalg - abx500 Charging algorithm device information | ||
196 | * @dev: pointer to the structure device | ||
197 | * @charge_status: battery operating status | ||
198 | * @eoc_cnt: counter used to determine end-of_charge | ||
199 | * @rch_cnt: counter used to determine start of recharge | ||
200 | * @maintenance_chg: indicate if maintenance charge is active | ||
201 | * @t_hyst_norm temperature hysteresis when the temperature has been | ||
202 | * over or under normal limits | ||
203 | * @t_hyst_lowhigh temperature hysteresis when the temperature has been | ||
204 | * over or under the high or low limits | ||
205 | * @charge_state: current state of the charging algorithm | ||
206 | * @ccm charging current maximization parameters | ||
207 | * @chg_info: information about connected charger types | ||
208 | * @batt_data: data of the battery | ||
209 | * @susp_status: current charger suspension status | ||
210 | * @bat: pointer to the abx500_bm platform data | ||
211 | * @chargalg_psy: structure that holds the battery properties exposed by | ||
212 | * the charging algorithm | ||
213 | * @events: structure for information about events triggered | ||
214 | * @chargalg_wq: work queue for running the charging algorithm | ||
215 | * @chargalg_periodic_work: work to run the charging algorithm periodically | ||
216 | * @chargalg_wd_work: work to kick the charger watchdog periodically | ||
217 | * @chargalg_work: work to run the charging algorithm instantly | ||
218 | * @safety_timer: charging safety timer | ||
219 | * @maintenance_timer: maintenance charging timer | ||
220 | * @chargalg_kobject: structure of type kobject | ||
221 | */ | ||
222 | struct abx500_chargalg { | ||
223 | struct device *dev; | ||
224 | int charge_status; | ||
225 | int eoc_cnt; | ||
226 | int rch_cnt; | ||
227 | bool maintenance_chg; | ||
228 | int t_hyst_norm; | ||
229 | int t_hyst_lowhigh; | ||
230 | enum abx500_chargalg_states charge_state; | ||
231 | struct abx500_charge_curr_maximization ccm; | ||
232 | struct abx500_chargalg_charger_info chg_info; | ||
233 | struct abx500_chargalg_battery_data batt_data; | ||
234 | struct abx500_chargalg_suspension_status susp_status; | ||
235 | struct abx500_bm_data *bat; | ||
236 | struct power_supply chargalg_psy; | ||
237 | struct ux500_charger *ac_chg; | ||
238 | struct ux500_charger *usb_chg; | ||
239 | struct abx500_chargalg_events events; | ||
240 | struct workqueue_struct *chargalg_wq; | ||
241 | struct delayed_work chargalg_periodic_work; | ||
242 | struct delayed_work chargalg_wd_work; | ||
243 | struct work_struct chargalg_work; | ||
244 | struct timer_list safety_timer; | ||
245 | struct timer_list maintenance_timer; | ||
246 | struct kobject chargalg_kobject; | ||
247 | }; | ||
248 | |||
249 | /* Main battery properties */ | ||
250 | static enum power_supply_property abx500_chargalg_props[] = { | ||
251 | POWER_SUPPLY_PROP_STATUS, | ||
252 | POWER_SUPPLY_PROP_HEALTH, | ||
253 | }; | ||
254 | |||
255 | /** | ||
256 | * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer | ||
257 | * @data: pointer to the abx500_chargalg structure | ||
258 | * | ||
259 | * This function gets called when the safety timer for the charger | ||
260 | * expires | ||
261 | */ | ||
262 | static void abx500_chargalg_safety_timer_expired(unsigned long data) | ||
263 | { | ||
264 | struct abx500_chargalg *di = (struct abx500_chargalg *) data; | ||
265 | dev_err(di->dev, "Safety timer expired\n"); | ||
266 | di->events.safety_timer_expired = true; | ||
267 | |||
268 | /* Trigger execution of the algorithm instantly */ | ||
269 | queue_work(di->chargalg_wq, &di->chargalg_work); | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * abx500_chargalg_maintenance_timer_expired() - Expiration of | ||
274 | * the maintenance timer | ||
275 | * @i: pointer to the abx500_chargalg structure | ||
276 | * | ||
277 | * This function gets called when the maintenence timer | ||
278 | * expires | ||
279 | */ | ||
280 | static void abx500_chargalg_maintenance_timer_expired(unsigned long data) | ||
281 | { | ||
282 | |||
283 | struct abx500_chargalg *di = (struct abx500_chargalg *) data; | ||
284 | dev_dbg(di->dev, "Maintenance timer expired\n"); | ||
285 | di->events.maintenance_timer_expired = true; | ||
286 | |||
287 | /* Trigger execution of the algorithm instantly */ | ||
288 | queue_work(di->chargalg_wq, &di->chargalg_work); | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * abx500_chargalg_state_to() - Change charge state | ||
293 | * @di: pointer to the abx500_chargalg structure | ||
294 | * | ||
295 | * This function gets called when a charge state change should occur | ||
296 | */ | ||
297 | static void abx500_chargalg_state_to(struct abx500_chargalg *di, | ||
298 | enum abx500_chargalg_states state) | ||
299 | { | ||
300 | dev_dbg(di->dev, | ||
301 | "State changed: %s (From state: [%d] %s =to=> [%d] %s )\n", | ||
302 | di->charge_state == state ? "NO" : "YES", | ||
303 | di->charge_state, | ||
304 | states[di->charge_state], | ||
305 | state, | ||
306 | states[state]); | ||
307 | |||
308 | di->charge_state = state; | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * abx500_chargalg_check_charger_connection() - Check charger connection change | ||
313 | * @di: pointer to the abx500_chargalg structure | ||
314 | * | ||
315 | * This function will check if there is a change in the charger connection | ||
316 | * and change charge state accordingly. AC has precedence over USB. | ||
317 | */ | ||
318 | static int abx500_chargalg_check_charger_connection(struct abx500_chargalg *di) | ||
319 | { | ||
320 | if (di->chg_info.conn_chg != di->chg_info.prev_conn_chg || | ||
321 | di->susp_status.suspended_change) { | ||
322 | /* | ||
323 | * Charger state changed or suspension | ||
324 | * has changed since last update | ||
325 | */ | ||
326 | if ((di->chg_info.conn_chg & AC_CHG) && | ||
327 | !di->susp_status.ac_suspended) { | ||
328 | dev_dbg(di->dev, "Charging source is AC\n"); | ||
329 | if (di->chg_info.charger_type != AC_CHG) { | ||
330 | di->chg_info.charger_type = AC_CHG; | ||
331 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
332 | } | ||
333 | } else if ((di->chg_info.conn_chg & USB_CHG) && | ||
334 | !di->susp_status.usb_suspended) { | ||
335 | dev_dbg(di->dev, "Charging source is USB\n"); | ||
336 | di->chg_info.charger_type = USB_CHG; | ||
337 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
338 | } else if (di->chg_info.conn_chg && | ||
339 | (di->susp_status.ac_suspended || | ||
340 | di->susp_status.usb_suspended)) { | ||
341 | dev_dbg(di->dev, "Charging is suspended\n"); | ||
342 | di->chg_info.charger_type = NO_CHG; | ||
343 | abx500_chargalg_state_to(di, STATE_SUSPENDED_INIT); | ||
344 | } else { | ||
345 | dev_dbg(di->dev, "Charging source is OFF\n"); | ||
346 | di->chg_info.charger_type = NO_CHG; | ||
347 | abx500_chargalg_state_to(di, STATE_HANDHELD_INIT); | ||
348 | } | ||
349 | di->chg_info.prev_conn_chg = di->chg_info.conn_chg; | ||
350 | di->susp_status.suspended_change = false; | ||
351 | } | ||
352 | return di->chg_info.conn_chg; | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * abx500_chargalg_start_safety_timer() - Start charging safety timer | ||
357 | * @di: pointer to the abx500_chargalg structure | ||
358 | * | ||
359 | * The safety timer is used to avoid overcharging of old or bad batteries. | ||
360 | * There are different timers for AC and USB | ||
361 | */ | ||
362 | static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di) | ||
363 | { | ||
364 | unsigned long timer_expiration = 0; | ||
365 | |||
366 | switch (di->chg_info.charger_type) { | ||
367 | case AC_CHG: | ||
368 | timer_expiration = | ||
369 | round_jiffies(jiffies + | ||
370 | (di->bat->main_safety_tmr_h * 3600 * HZ)); | ||
371 | break; | ||
372 | |||
373 | case USB_CHG: | ||
374 | timer_expiration = | ||
375 | round_jiffies(jiffies + | ||
376 | (di->bat->usb_safety_tmr_h * 3600 * HZ)); | ||
377 | break; | ||
378 | |||
379 | default: | ||
380 | dev_err(di->dev, "Unknown charger to charge from\n"); | ||
381 | break; | ||
382 | } | ||
383 | |||
384 | di->events.safety_timer_expired = false; | ||
385 | di->safety_timer.expires = timer_expiration; | ||
386 | if (!timer_pending(&di->safety_timer)) | ||
387 | add_timer(&di->safety_timer); | ||
388 | else | ||
389 | mod_timer(&di->safety_timer, timer_expiration); | ||
390 | } | ||
391 | |||
392 | /** | ||
393 | * abx500_chargalg_stop_safety_timer() - Stop charging safety timer | ||
394 | * @di: pointer to the abx500_chargalg structure | ||
395 | * | ||
396 | * The safety timer is stopped whenever the NORMAL state is exited | ||
397 | */ | ||
398 | static void abx500_chargalg_stop_safety_timer(struct abx500_chargalg *di) | ||
399 | { | ||
400 | di->events.safety_timer_expired = false; | ||
401 | del_timer(&di->safety_timer); | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * abx500_chargalg_start_maintenance_timer() - Start charging maintenance timer | ||
406 | * @di: pointer to the abx500_chargalg structure | ||
407 | * @duration: duration of ther maintenance timer in hours | ||
408 | * | ||
409 | * The maintenance timer is used to maintain the charge in the battery once | ||
410 | * the battery is considered full. These timers are chosen to match the | ||
411 | * discharge curve of the battery | ||
412 | */ | ||
413 | static void abx500_chargalg_start_maintenance_timer(struct abx500_chargalg *di, | ||
414 | int duration) | ||
415 | { | ||
416 | unsigned long timer_expiration; | ||
417 | |||
418 | /* Convert from hours to jiffies */ | ||
419 | timer_expiration = round_jiffies(jiffies + (duration * 3600 * HZ)); | ||
420 | |||
421 | di->events.maintenance_timer_expired = false; | ||
422 | di->maintenance_timer.expires = timer_expiration; | ||
423 | if (!timer_pending(&di->maintenance_timer)) | ||
424 | add_timer(&di->maintenance_timer); | ||
425 | else | ||
426 | mod_timer(&di->maintenance_timer, timer_expiration); | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * abx500_chargalg_stop_maintenance_timer() - Stop maintenance timer | ||
431 | * @di: pointer to the abx500_chargalg structure | ||
432 | * | ||
433 | * The maintenance timer is stopped whenever maintenance ends or when another | ||
434 | * state is entered | ||
435 | */ | ||
436 | static void abx500_chargalg_stop_maintenance_timer(struct abx500_chargalg *di) | ||
437 | { | ||
438 | di->events.maintenance_timer_expired = false; | ||
439 | del_timer(&di->maintenance_timer); | ||
440 | } | ||
441 | |||
442 | /** | ||
443 | * abx500_chargalg_kick_watchdog() - Kick charger watchdog | ||
444 | * @di: pointer to the abx500_chargalg structure | ||
445 | * | ||
446 | * The charger watchdog have to be kicked periodically whenever the charger is | ||
447 | * on, else the ABB will reset the system | ||
448 | */ | ||
449 | static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di) | ||
450 | { | ||
451 | /* Check if charger exists and kick watchdog if charging */ | ||
452 | if (di->ac_chg && di->ac_chg->ops.kick_wd && | ||
453 | di->chg_info.online_chg & AC_CHG) | ||
454 | return di->ac_chg->ops.kick_wd(di->ac_chg); | ||
455 | else if (di->usb_chg && di->usb_chg->ops.kick_wd && | ||
456 | di->chg_info.online_chg & USB_CHG) | ||
457 | return di->usb_chg->ops.kick_wd(di->usb_chg); | ||
458 | |||
459 | return -ENXIO; | ||
460 | } | ||
461 | |||
462 | /** | ||
463 | * abx500_chargalg_ac_en() - Turn on/off the AC charger | ||
464 | * @di: pointer to the abx500_chargalg structure | ||
465 | * @enable: charger on/off | ||
466 | * @vset: requested charger output voltage | ||
467 | * @iset: requested charger output current | ||
468 | * | ||
469 | * The AC charger will be turned on/off with the requested charge voltage and | ||
470 | * current | ||
471 | */ | ||
472 | static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable, | ||
473 | int vset, int iset) | ||
474 | { | ||
475 | if (!di->ac_chg || !di->ac_chg->ops.enable) | ||
476 | return -ENXIO; | ||
477 | |||
478 | /* Select maximum of what both the charger and the battery supports */ | ||
479 | if (di->ac_chg->max_out_volt) | ||
480 | vset = min(vset, di->ac_chg->max_out_volt); | ||
481 | if (di->ac_chg->max_out_curr) | ||
482 | iset = min(iset, di->ac_chg->max_out_curr); | ||
483 | |||
484 | di->chg_info.ac_iset = iset; | ||
485 | di->chg_info.ac_vset = vset; | ||
486 | |||
487 | return di->ac_chg->ops.enable(di->ac_chg, enable, vset, iset); | ||
488 | } | ||
489 | |||
490 | /** | ||
491 | * abx500_chargalg_usb_en() - Turn on/off the USB charger | ||
492 | * @di: pointer to the abx500_chargalg structure | ||
493 | * @enable: charger on/off | ||
494 | * @vset: requested charger output voltage | ||
495 | * @iset: requested charger output current | ||
496 | * | ||
497 | * The USB charger will be turned on/off with the requested charge voltage and | ||
498 | * current | ||
499 | */ | ||
500 | static int abx500_chargalg_usb_en(struct abx500_chargalg *di, int enable, | ||
501 | int vset, int iset) | ||
502 | { | ||
503 | if (!di->usb_chg || !di->usb_chg->ops.enable) | ||
504 | return -ENXIO; | ||
505 | |||
506 | /* Select maximum of what both the charger and the battery supports */ | ||
507 | if (di->usb_chg->max_out_volt) | ||
508 | vset = min(vset, di->usb_chg->max_out_volt); | ||
509 | if (di->usb_chg->max_out_curr) | ||
510 | iset = min(iset, di->usb_chg->max_out_curr); | ||
511 | |||
512 | di->chg_info.usb_iset = iset; | ||
513 | di->chg_info.usb_vset = vset; | ||
514 | |||
515 | return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset); | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * abx500_chargalg_update_chg_curr() - Update charger current | ||
520 | * @di: pointer to the abx500_chargalg structure | ||
521 | * @iset: requested charger output current | ||
522 | * | ||
523 | * The charger output current will be updated for the charger | ||
524 | * that is currently in use | ||
525 | */ | ||
526 | static int abx500_chargalg_update_chg_curr(struct abx500_chargalg *di, | ||
527 | int iset) | ||
528 | { | ||
529 | /* Check if charger exists and update current if charging */ | ||
530 | if (di->ac_chg && di->ac_chg->ops.update_curr && | ||
531 | di->chg_info.charger_type & AC_CHG) { | ||
532 | /* | ||
533 | * Select maximum of what both the charger | ||
534 | * and the battery supports | ||
535 | */ | ||
536 | if (di->ac_chg->max_out_curr) | ||
537 | iset = min(iset, di->ac_chg->max_out_curr); | ||
538 | |||
539 | di->chg_info.ac_iset = iset; | ||
540 | |||
541 | return di->ac_chg->ops.update_curr(di->ac_chg, iset); | ||
542 | } else if (di->usb_chg && di->usb_chg->ops.update_curr && | ||
543 | di->chg_info.charger_type & USB_CHG) { | ||
544 | /* | ||
545 | * Select maximum of what both the charger | ||
546 | * and the battery supports | ||
547 | */ | ||
548 | if (di->usb_chg->max_out_curr) | ||
549 | iset = min(iset, di->usb_chg->max_out_curr); | ||
550 | |||
551 | di->chg_info.usb_iset = iset; | ||
552 | |||
553 | return di->usb_chg->ops.update_curr(di->usb_chg, iset); | ||
554 | } | ||
555 | |||
556 | return -ENXIO; | ||
557 | } | ||
558 | |||
559 | /** | ||
560 | * abx500_chargalg_stop_charging() - Stop charging | ||
561 | * @di: pointer to the abx500_chargalg structure | ||
562 | * | ||
563 | * This function is called from any state where charging should be stopped. | ||
564 | * All charging is disabled and all status parameters and timers are changed | ||
565 | * accordingly | ||
566 | */ | ||
567 | static void abx500_chargalg_stop_charging(struct abx500_chargalg *di) | ||
568 | { | ||
569 | abx500_chargalg_ac_en(di, false, 0, 0); | ||
570 | abx500_chargalg_usb_en(di, false, 0, 0); | ||
571 | abx500_chargalg_stop_safety_timer(di); | ||
572 | abx500_chargalg_stop_maintenance_timer(di); | ||
573 | di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
574 | di->maintenance_chg = false; | ||
575 | cancel_delayed_work(&di->chargalg_wd_work); | ||
576 | power_supply_changed(&di->chargalg_psy); | ||
577 | } | ||
578 | |||
579 | /** | ||
580 | * abx500_chargalg_hold_charging() - Pauses charging | ||
581 | * @di: pointer to the abx500_chargalg structure | ||
582 | * | ||
583 | * This function is called in the case where maintenance charging has been | ||
584 | * disabled and instead a battery voltage mode is entered to check when the | ||
585 | * battery voltage has reached a certain recharge voltage | ||
586 | */ | ||
587 | static void abx500_chargalg_hold_charging(struct abx500_chargalg *di) | ||
588 | { | ||
589 | abx500_chargalg_ac_en(di, false, 0, 0); | ||
590 | abx500_chargalg_usb_en(di, false, 0, 0); | ||
591 | abx500_chargalg_stop_safety_timer(di); | ||
592 | abx500_chargalg_stop_maintenance_timer(di); | ||
593 | di->charge_status = POWER_SUPPLY_STATUS_CHARGING; | ||
594 | di->maintenance_chg = false; | ||
595 | cancel_delayed_work(&di->chargalg_wd_work); | ||
596 | power_supply_changed(&di->chargalg_psy); | ||
597 | } | ||
598 | |||
599 | /** | ||
600 | * abx500_chargalg_start_charging() - Start the charger | ||
601 | * @di: pointer to the abx500_chargalg structure | ||
602 | * @vset: requested charger output voltage | ||
603 | * @iset: requested charger output current | ||
604 | * | ||
605 | * A charger will be enabled depending on the requested charger type that was | ||
606 | * detected previously. | ||
607 | */ | ||
608 | static void abx500_chargalg_start_charging(struct abx500_chargalg *di, | ||
609 | int vset, int iset) | ||
610 | { | ||
611 | switch (di->chg_info.charger_type) { | ||
612 | case AC_CHG: | ||
613 | dev_dbg(di->dev, | ||
614 | "AC parameters: Vset %d, Ich %d\n", vset, iset); | ||
615 | abx500_chargalg_usb_en(di, false, 0, 0); | ||
616 | abx500_chargalg_ac_en(di, true, vset, iset); | ||
617 | break; | ||
618 | |||
619 | case USB_CHG: | ||
620 | dev_dbg(di->dev, | ||
621 | "USB parameters: Vset %d, Ich %d\n", vset, iset); | ||
622 | abx500_chargalg_ac_en(di, false, 0, 0); | ||
623 | abx500_chargalg_usb_en(di, true, vset, iset); | ||
624 | break; | ||
625 | |||
626 | default: | ||
627 | dev_err(di->dev, "Unknown charger to charge from\n"); | ||
628 | break; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | /** | ||
633 | * abx500_chargalg_check_temp() - Check battery temperature ranges | ||
634 | * @di: pointer to the abx500_chargalg structure | ||
635 | * | ||
636 | * The battery temperature is checked against the predefined limits and the | ||
637 | * charge state is changed accordingly | ||
638 | */ | ||
639 | static void abx500_chargalg_check_temp(struct abx500_chargalg *di) | ||
640 | { | ||
641 | if (di->batt_data.temp > (di->bat->temp_low + di->t_hyst_norm) && | ||
642 | di->batt_data.temp < (di->bat->temp_high - di->t_hyst_norm)) { | ||
643 | /* Temp OK! */ | ||
644 | di->events.btemp_underover = false; | ||
645 | di->events.btemp_lowhigh = false; | ||
646 | di->t_hyst_norm = 0; | ||
647 | di->t_hyst_lowhigh = 0; | ||
648 | } else { | ||
649 | if (((di->batt_data.temp >= di->bat->temp_high) && | ||
650 | (di->batt_data.temp < | ||
651 | (di->bat->temp_over - di->t_hyst_lowhigh))) || | ||
652 | ((di->batt_data.temp > | ||
653 | (di->bat->temp_under + di->t_hyst_lowhigh)) && | ||
654 | (di->batt_data.temp <= di->bat->temp_low))) { | ||
655 | /* TEMP minor!!!!! */ | ||
656 | di->events.btemp_underover = false; | ||
657 | di->events.btemp_lowhigh = true; | ||
658 | di->t_hyst_norm = di->bat->temp_hysteresis; | ||
659 | di->t_hyst_lowhigh = 0; | ||
660 | } else if (di->batt_data.temp <= di->bat->temp_under || | ||
661 | di->batt_data.temp >= di->bat->temp_over) { | ||
662 | /* TEMP major!!!!! */ | ||
663 | di->events.btemp_underover = true; | ||
664 | di->events.btemp_lowhigh = false; | ||
665 | di->t_hyst_norm = 0; | ||
666 | di->t_hyst_lowhigh = di->bat->temp_hysteresis; | ||
667 | } else { | ||
668 | /* Within hysteresis */ | ||
669 | dev_dbg(di->dev, "Within hysteresis limit temp: %d " | ||
670 | "hyst_lowhigh %d, hyst normal %d\n", | ||
671 | di->batt_data.temp, di->t_hyst_lowhigh, | ||
672 | di->t_hyst_norm); | ||
673 | } | ||
674 | } | ||
675 | } | ||
676 | |||
677 | /** | ||
678 | * abx500_chargalg_check_charger_voltage() - Check charger voltage | ||
679 | * @di: pointer to the abx500_chargalg structure | ||
680 | * | ||
681 | * Charger voltage is checked against maximum limit | ||
682 | */ | ||
683 | static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di) | ||
684 | { | ||
685 | if (di->chg_info.usb_volt > di->bat->chg_params->usb_volt_max) | ||
686 | di->chg_info.usb_chg_ok = false; | ||
687 | else | ||
688 | di->chg_info.usb_chg_ok = true; | ||
689 | |||
690 | if (di->chg_info.ac_volt > di->bat->chg_params->ac_volt_max) | ||
691 | di->chg_info.ac_chg_ok = false; | ||
692 | else | ||
693 | di->chg_info.ac_chg_ok = true; | ||
694 | |||
695 | } | ||
696 | |||
697 | /** | ||
698 | * abx500_chargalg_end_of_charge() - Check if end-of-charge criteria is fulfilled | ||
699 | * @di: pointer to the abx500_chargalg structure | ||
700 | * | ||
701 | * End-of-charge criteria is fulfilled when the battery voltage is above a | ||
702 | * certain limit and the battery current is below a certain limit for a | ||
703 | * predefined number of consecutive seconds. If true, the battery is full | ||
704 | */ | ||
705 | static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di) | ||
706 | { | ||
707 | if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING && | ||
708 | di->charge_state == STATE_NORMAL && | ||
709 | !di->maintenance_chg && (di->batt_data.volt >= | ||
710 | di->bat->bat_type[di->bat->batt_id].termination_vol || | ||
711 | di->events.usb_cv_active || di->events.ac_cv_active) && | ||
712 | di->batt_data.avg_curr < | ||
713 | di->bat->bat_type[di->bat->batt_id].termination_curr && | ||
714 | di->batt_data.avg_curr > 0) { | ||
715 | if (++di->eoc_cnt >= EOC_COND_CNT) { | ||
716 | di->eoc_cnt = 0; | ||
717 | di->charge_status = POWER_SUPPLY_STATUS_FULL; | ||
718 | di->maintenance_chg = true; | ||
719 | dev_dbg(di->dev, "EOC reached!\n"); | ||
720 | power_supply_changed(&di->chargalg_psy); | ||
721 | } else { | ||
722 | dev_dbg(di->dev, | ||
723 | " EOC limit reached for the %d" | ||
724 | " time, out of %d before EOC\n", | ||
725 | di->eoc_cnt, | ||
726 | EOC_COND_CNT); | ||
727 | } | ||
728 | } else { | ||
729 | di->eoc_cnt = 0; | ||
730 | } | ||
731 | } | ||
732 | |||
733 | static void init_maxim_chg_curr(struct abx500_chargalg *di) | ||
734 | { | ||
735 | di->ccm.original_iset = | ||
736 | di->bat->bat_type[di->bat->batt_id].normal_cur_lvl; | ||
737 | di->ccm.current_iset = | ||
738 | di->bat->bat_type[di->bat->batt_id].normal_cur_lvl; | ||
739 | di->ccm.test_delta_i = di->bat->maxi->charger_curr_step; | ||
740 | di->ccm.max_current = di->bat->maxi->chg_curr; | ||
741 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | ||
742 | di->ccm.level = 0; | ||
743 | } | ||
744 | |||
745 | /** | ||
746 | * abx500_chargalg_chg_curr_maxim - increases the charger current to | ||
747 | * compensate for the system load | ||
748 | * @di pointer to the abx500_chargalg structure | ||
749 | * | ||
750 | * This maximization function is used to raise the charger current to get the | ||
751 | * battery current as close to the optimal value as possible. The battery | ||
752 | * current during charging is affected by the system load | ||
753 | */ | ||
754 | static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) | ||
755 | { | ||
756 | int delta_i; | ||
757 | |||
758 | if (!di->bat->maxi->ena_maxi) | ||
759 | return MAXIM_RET_NOACTION; | ||
760 | |||
761 | delta_i = di->ccm.original_iset - di->batt_data.inst_curr; | ||
762 | |||
763 | if (di->events.vbus_collapsed) { | ||
764 | dev_dbg(di->dev, "Charger voltage has collapsed %d\n", | ||
765 | di->ccm.wait_cnt); | ||
766 | if (di->ccm.wait_cnt == 0) { | ||
767 | dev_dbg(di->dev, "lowering current\n"); | ||
768 | di->ccm.wait_cnt++; | ||
769 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | ||
770 | di->ccm.max_current = | ||
771 | di->ccm.current_iset - di->ccm.test_delta_i; | ||
772 | di->ccm.current_iset = di->ccm.max_current; | ||
773 | di->ccm.level--; | ||
774 | return MAXIM_RET_CHANGE; | ||
775 | } else { | ||
776 | dev_dbg(di->dev, "waiting\n"); | ||
777 | /* Let's go in here twice before lowering curr again */ | ||
778 | di->ccm.wait_cnt = (di->ccm.wait_cnt + 1) % 3; | ||
779 | return MAXIM_RET_NOACTION; | ||
780 | } | ||
781 | } | ||
782 | |||
783 | di->ccm.wait_cnt = 0; | ||
784 | |||
785 | if ((di->batt_data.inst_curr > di->ccm.original_iset)) { | ||
786 | dev_dbg(di->dev, " Maximization Ibat (%dmA) too high" | ||
787 | " (limit %dmA) (current iset: %dmA)!\n", | ||
788 | di->batt_data.inst_curr, di->ccm.original_iset, | ||
789 | di->ccm.current_iset); | ||
790 | |||
791 | if (di->ccm.current_iset == di->ccm.original_iset) | ||
792 | return MAXIM_RET_NOACTION; | ||
793 | |||
794 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | ||
795 | di->ccm.current_iset = di->ccm.original_iset; | ||
796 | di->ccm.level = 0; | ||
797 | |||
798 | return MAXIM_RET_IBAT_TOO_HIGH; | ||
799 | } | ||
800 | |||
801 | if (delta_i > di->ccm.test_delta_i && | ||
802 | (di->ccm.current_iset + di->ccm.test_delta_i) < | ||
803 | di->ccm.max_current) { | ||
804 | if (di->ccm.condition_cnt-- == 0) { | ||
805 | /* Increse the iset with cco.test_delta_i */ | ||
806 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | ||
807 | di->ccm.current_iset += di->ccm.test_delta_i; | ||
808 | di->ccm.level++; | ||
809 | dev_dbg(di->dev, " Maximization needed, increase" | ||
810 | " with %d mA to %dmA (Optimal ibat: %d)" | ||
811 | " Level %d\n", | ||
812 | di->ccm.test_delta_i, | ||
813 | di->ccm.current_iset, | ||
814 | di->ccm.original_iset, | ||
815 | di->ccm.level); | ||
816 | return MAXIM_RET_CHANGE; | ||
817 | } else { | ||
818 | return MAXIM_RET_NOACTION; | ||
819 | } | ||
820 | } else { | ||
821 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | ||
822 | return MAXIM_RET_NOACTION; | ||
823 | } | ||
824 | } | ||
825 | |||
826 | static void handle_maxim_chg_curr(struct abx500_chargalg *di) | ||
827 | { | ||
828 | enum maxim_ret ret; | ||
829 | int result; | ||
830 | |||
831 | ret = abx500_chargalg_chg_curr_maxim(di); | ||
832 | switch (ret) { | ||
833 | case MAXIM_RET_CHANGE: | ||
834 | result = abx500_chargalg_update_chg_curr(di, | ||
835 | di->ccm.current_iset); | ||
836 | if (result) | ||
837 | dev_err(di->dev, "failed to set chg curr\n"); | ||
838 | break; | ||
839 | case MAXIM_RET_IBAT_TOO_HIGH: | ||
840 | result = abx500_chargalg_update_chg_curr(di, | ||
841 | di->bat->bat_type[di->bat->batt_id].normal_cur_lvl); | ||
842 | if (result) | ||
843 | dev_err(di->dev, "failed to set chg curr\n"); | ||
844 | break; | ||
845 | |||
846 | case MAXIM_RET_NOACTION: | ||
847 | default: | ||
848 | /* Do nothing..*/ | ||
849 | break; | ||
850 | } | ||
851 | } | ||
852 | |||
853 | static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data) | ||
854 | { | ||
855 | struct power_supply *psy; | ||
856 | struct power_supply *ext; | ||
857 | struct abx500_chargalg *di; | ||
858 | union power_supply_propval ret; | ||
859 | int i, j; | ||
860 | bool psy_found = false; | ||
861 | |||
862 | psy = (struct power_supply *)data; | ||
863 | ext = dev_get_drvdata(dev); | ||
864 | di = to_abx500_chargalg_device_info(psy); | ||
865 | /* For all psy where the driver name appears in any supplied_to */ | ||
866 | for (i = 0; i < ext->num_supplicants; i++) { | ||
867 | if (!strcmp(ext->supplied_to[i], psy->name)) | ||
868 | psy_found = true; | ||
869 | } | ||
870 | if (!psy_found) | ||
871 | return 0; | ||
872 | |||
873 | /* Go through all properties for the psy */ | ||
874 | for (j = 0; j < ext->num_properties; j++) { | ||
875 | enum power_supply_property prop; | ||
876 | prop = ext->properties[j]; | ||
877 | |||
878 | /* Initialize chargers if not already done */ | ||
879 | if (!di->ac_chg && | ||
880 | ext->type == POWER_SUPPLY_TYPE_MAINS) | ||
881 | di->ac_chg = psy_to_ux500_charger(ext); | ||
882 | else if (!di->usb_chg && | ||
883 | ext->type == POWER_SUPPLY_TYPE_USB) | ||
884 | di->usb_chg = psy_to_ux500_charger(ext); | ||
885 | |||
886 | if (ext->get_property(ext, prop, &ret)) | ||
887 | continue; | ||
888 | switch (prop) { | ||
889 | case POWER_SUPPLY_PROP_PRESENT: | ||
890 | switch (ext->type) { | ||
891 | case POWER_SUPPLY_TYPE_BATTERY: | ||
892 | /* Battery present */ | ||
893 | if (ret.intval) | ||
894 | di->events.batt_rem = false; | ||
895 | /* Battery removed */ | ||
896 | else | ||
897 | di->events.batt_rem = true; | ||
898 | break; | ||
899 | case POWER_SUPPLY_TYPE_MAINS: | ||
900 | /* AC disconnected */ | ||
901 | if (!ret.intval && | ||
902 | (di->chg_info.conn_chg & AC_CHG)) { | ||
903 | di->chg_info.prev_conn_chg = | ||
904 | di->chg_info.conn_chg; | ||
905 | di->chg_info.conn_chg &= ~AC_CHG; | ||
906 | } | ||
907 | /* AC connected */ | ||
908 | else if (ret.intval && | ||
909 | !(di->chg_info.conn_chg & AC_CHG)) { | ||
910 | di->chg_info.prev_conn_chg = | ||
911 | di->chg_info.conn_chg; | ||
912 | di->chg_info.conn_chg |= AC_CHG; | ||
913 | } | ||
914 | break; | ||
915 | case POWER_SUPPLY_TYPE_USB: | ||
916 | /* USB disconnected */ | ||
917 | if (!ret.intval && | ||
918 | (di->chg_info.conn_chg & USB_CHG)) { | ||
919 | di->chg_info.prev_conn_chg = | ||
920 | di->chg_info.conn_chg; | ||
921 | di->chg_info.conn_chg &= ~USB_CHG; | ||
922 | } | ||
923 | /* USB connected */ | ||
924 | else if (ret.intval && | ||
925 | !(di->chg_info.conn_chg & USB_CHG)) { | ||
926 | di->chg_info.prev_conn_chg = | ||
927 | di->chg_info.conn_chg; | ||
928 | di->chg_info.conn_chg |= USB_CHG; | ||
929 | } | ||
930 | break; | ||
931 | default: | ||
932 | break; | ||
933 | } | ||
934 | break; | ||
935 | |||
936 | case POWER_SUPPLY_PROP_ONLINE: | ||
937 | switch (ext->type) { | ||
938 | case POWER_SUPPLY_TYPE_BATTERY: | ||
939 | break; | ||
940 | case POWER_SUPPLY_TYPE_MAINS: | ||
941 | /* AC offline */ | ||
942 | if (!ret.intval && | ||
943 | (di->chg_info.online_chg & AC_CHG)) { | ||
944 | di->chg_info.prev_online_chg = | ||
945 | di->chg_info.online_chg; | ||
946 | di->chg_info.online_chg &= ~AC_CHG; | ||
947 | } | ||
948 | /* AC online */ | ||
949 | else if (ret.intval && | ||
950 | !(di->chg_info.online_chg & AC_CHG)) { | ||
951 | di->chg_info.prev_online_chg = | ||
952 | di->chg_info.online_chg; | ||
953 | di->chg_info.online_chg |= AC_CHG; | ||
954 | queue_delayed_work(di->chargalg_wq, | ||
955 | &di->chargalg_wd_work, 0); | ||
956 | } | ||
957 | break; | ||
958 | case POWER_SUPPLY_TYPE_USB: | ||
959 | /* USB offline */ | ||
960 | if (!ret.intval && | ||
961 | (di->chg_info.online_chg & USB_CHG)) { | ||
962 | di->chg_info.prev_online_chg = | ||
963 | di->chg_info.online_chg; | ||
964 | di->chg_info.online_chg &= ~USB_CHG; | ||
965 | } | ||
966 | /* USB online */ | ||
967 | else if (ret.intval && | ||
968 | !(di->chg_info.online_chg & USB_CHG)) { | ||
969 | di->chg_info.prev_online_chg = | ||
970 | di->chg_info.online_chg; | ||
971 | di->chg_info.online_chg |= USB_CHG; | ||
972 | queue_delayed_work(di->chargalg_wq, | ||
973 | &di->chargalg_wd_work, 0); | ||
974 | } | ||
975 | break; | ||
976 | default: | ||
977 | break; | ||
978 | } | ||
979 | break; | ||
980 | |||
981 | case POWER_SUPPLY_PROP_HEALTH: | ||
982 | switch (ext->type) { | ||
983 | case POWER_SUPPLY_TYPE_BATTERY: | ||
984 | break; | ||
985 | case POWER_SUPPLY_TYPE_MAINS: | ||
986 | switch (ret.intval) { | ||
987 | case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE: | ||
988 | di->events.mainextchnotok = true; | ||
989 | di->events.main_thermal_prot = false; | ||
990 | di->events.main_ovv = false; | ||
991 | di->events.ac_wd_expired = false; | ||
992 | break; | ||
993 | case POWER_SUPPLY_HEALTH_DEAD: | ||
994 | di->events.ac_wd_expired = true; | ||
995 | di->events.mainextchnotok = false; | ||
996 | di->events.main_ovv = false; | ||
997 | di->events.main_thermal_prot = false; | ||
998 | break; | ||
999 | case POWER_SUPPLY_HEALTH_COLD: | ||
1000 | case POWER_SUPPLY_HEALTH_OVERHEAT: | ||
1001 | di->events.main_thermal_prot = true; | ||
1002 | di->events.mainextchnotok = false; | ||
1003 | di->events.main_ovv = false; | ||
1004 | di->events.ac_wd_expired = false; | ||
1005 | break; | ||
1006 | case POWER_SUPPLY_HEALTH_OVERVOLTAGE: | ||
1007 | di->events.main_ovv = true; | ||
1008 | di->events.mainextchnotok = false; | ||
1009 | di->events.main_thermal_prot = false; | ||
1010 | di->events.ac_wd_expired = false; | ||
1011 | break; | ||
1012 | case POWER_SUPPLY_HEALTH_GOOD: | ||
1013 | di->events.main_thermal_prot = false; | ||
1014 | di->events.mainextchnotok = false; | ||
1015 | di->events.main_ovv = false; | ||
1016 | di->events.ac_wd_expired = false; | ||
1017 | break; | ||
1018 | default: | ||
1019 | break; | ||
1020 | } | ||
1021 | break; | ||
1022 | |||
1023 | case POWER_SUPPLY_TYPE_USB: | ||
1024 | switch (ret.intval) { | ||
1025 | case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE: | ||
1026 | di->events.usbchargernotok = true; | ||
1027 | di->events.usb_thermal_prot = false; | ||
1028 | di->events.vbus_ovv = false; | ||
1029 | di->events.usb_wd_expired = false; | ||
1030 | break; | ||
1031 | case POWER_SUPPLY_HEALTH_DEAD: | ||
1032 | di->events.usb_wd_expired = true; | ||
1033 | di->events.usbchargernotok = false; | ||
1034 | di->events.usb_thermal_prot = false; | ||
1035 | di->events.vbus_ovv = false; | ||
1036 | break; | ||
1037 | case POWER_SUPPLY_HEALTH_COLD: | ||
1038 | case POWER_SUPPLY_HEALTH_OVERHEAT: | ||
1039 | di->events.usb_thermal_prot = true; | ||
1040 | di->events.usbchargernotok = false; | ||
1041 | di->events.vbus_ovv = false; | ||
1042 | di->events.usb_wd_expired = false; | ||
1043 | break; | ||
1044 | case POWER_SUPPLY_HEALTH_OVERVOLTAGE: | ||
1045 | di->events.vbus_ovv = true; | ||
1046 | di->events.usbchargernotok = false; | ||
1047 | di->events.usb_thermal_prot = false; | ||
1048 | di->events.usb_wd_expired = false; | ||
1049 | break; | ||
1050 | case POWER_SUPPLY_HEALTH_GOOD: | ||
1051 | di->events.usbchargernotok = false; | ||
1052 | di->events.usb_thermal_prot = false; | ||
1053 | di->events.vbus_ovv = false; | ||
1054 | di->events.usb_wd_expired = false; | ||
1055 | break; | ||
1056 | default: | ||
1057 | break; | ||
1058 | } | ||
1059 | default: | ||
1060 | break; | ||
1061 | } | ||
1062 | break; | ||
1063 | |||
1064 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
1065 | switch (ext->type) { | ||
1066 | case POWER_SUPPLY_TYPE_BATTERY: | ||
1067 | di->batt_data.volt = ret.intval / 1000; | ||
1068 | break; | ||
1069 | case POWER_SUPPLY_TYPE_MAINS: | ||
1070 | di->chg_info.ac_volt = ret.intval / 1000; | ||
1071 | break; | ||
1072 | case POWER_SUPPLY_TYPE_USB: | ||
1073 | di->chg_info.usb_volt = ret.intval / 1000; | ||
1074 | break; | ||
1075 | default: | ||
1076 | break; | ||
1077 | } | ||
1078 | break; | ||
1079 | |||
1080 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | ||
1081 | switch (ext->type) { | ||
1082 | case POWER_SUPPLY_TYPE_MAINS: | ||
1083 | /* AVG is used to indicate when we are | ||
1084 | * in CV mode */ | ||
1085 | if (ret.intval) | ||
1086 | di->events.ac_cv_active = true; | ||
1087 | else | ||
1088 | di->events.ac_cv_active = false; | ||
1089 | |||
1090 | break; | ||
1091 | case POWER_SUPPLY_TYPE_USB: | ||
1092 | /* AVG is used to indicate when we are | ||
1093 | * in CV mode */ | ||
1094 | if (ret.intval) | ||
1095 | di->events.usb_cv_active = true; | ||
1096 | else | ||
1097 | di->events.usb_cv_active = false; | ||
1098 | |||
1099 | break; | ||
1100 | default: | ||
1101 | break; | ||
1102 | } | ||
1103 | break; | ||
1104 | |||
1105 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
1106 | switch (ext->type) { | ||
1107 | case POWER_SUPPLY_TYPE_BATTERY: | ||
1108 | if (ret.intval) | ||
1109 | di->events.batt_unknown = false; | ||
1110 | else | ||
1111 | di->events.batt_unknown = true; | ||
1112 | |||
1113 | break; | ||
1114 | default: | ||
1115 | break; | ||
1116 | } | ||
1117 | break; | ||
1118 | |||
1119 | case POWER_SUPPLY_PROP_TEMP: | ||
1120 | di->batt_data.temp = ret.intval / 10; | ||
1121 | break; | ||
1122 | |||
1123 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
1124 | switch (ext->type) { | ||
1125 | case POWER_SUPPLY_TYPE_MAINS: | ||
1126 | di->chg_info.ac_curr = | ||
1127 | ret.intval / 1000; | ||
1128 | break; | ||
1129 | case POWER_SUPPLY_TYPE_USB: | ||
1130 | di->chg_info.usb_curr = | ||
1131 | ret.intval / 1000; | ||
1132 | break; | ||
1133 | case POWER_SUPPLY_TYPE_BATTERY: | ||
1134 | di->batt_data.inst_curr = ret.intval / 1000; | ||
1135 | break; | ||
1136 | default: | ||
1137 | break; | ||
1138 | } | ||
1139 | break; | ||
1140 | |||
1141 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
1142 | switch (ext->type) { | ||
1143 | case POWER_SUPPLY_TYPE_BATTERY: | ||
1144 | di->batt_data.avg_curr = ret.intval / 1000; | ||
1145 | break; | ||
1146 | case POWER_SUPPLY_TYPE_USB: | ||
1147 | if (ret.intval) | ||
1148 | di->events.vbus_collapsed = true; | ||
1149 | else | ||
1150 | di->events.vbus_collapsed = false; | ||
1151 | break; | ||
1152 | default: | ||
1153 | break; | ||
1154 | } | ||
1155 | break; | ||
1156 | case POWER_SUPPLY_PROP_CAPACITY: | ||
1157 | di->batt_data.percent = ret.intval; | ||
1158 | break; | ||
1159 | default: | ||
1160 | break; | ||
1161 | } | ||
1162 | } | ||
1163 | return 0; | ||
1164 | } | ||
1165 | |||
1166 | /** | ||
1167 | * abx500_chargalg_external_power_changed() - callback for power supply changes | ||
1168 | * @psy: pointer to the structure power_supply | ||
1169 | * | ||
1170 | * This function is the entry point of the pointer external_power_changed | ||
1171 | * of the structure power_supply. | ||
1172 | * This function gets executed when there is a change in any external power | ||
1173 | * supply that this driver needs to be notified of. | ||
1174 | */ | ||
1175 | static void abx500_chargalg_external_power_changed(struct power_supply *psy) | ||
1176 | { | ||
1177 | struct abx500_chargalg *di = to_abx500_chargalg_device_info(psy); | ||
1178 | |||
1179 | /* | ||
1180 | * Trigger execution of the algorithm instantly and read | ||
1181 | * all power_supply properties there instead | ||
1182 | */ | ||
1183 | queue_work(di->chargalg_wq, &di->chargalg_work); | ||
1184 | } | ||
1185 | |||
1186 | /** | ||
1187 | * abx500_chargalg_algorithm() - Main function for the algorithm | ||
1188 | * @di: pointer to the abx500_chargalg structure | ||
1189 | * | ||
1190 | * This is the main control function for the charging algorithm. | ||
1191 | * It is called periodically or when something happens that will | ||
1192 | * trigger a state change | ||
1193 | */ | ||
1194 | static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | ||
1195 | { | ||
1196 | int charger_status; | ||
1197 | |||
1198 | /* Collect data from all power_supply class devices */ | ||
1199 | class_for_each_device(power_supply_class, NULL, | ||
1200 | &di->chargalg_psy, abx500_chargalg_get_ext_psy_data); | ||
1201 | |||
1202 | abx500_chargalg_end_of_charge(di); | ||
1203 | abx500_chargalg_check_temp(di); | ||
1204 | abx500_chargalg_check_charger_voltage(di); | ||
1205 | |||
1206 | charger_status = abx500_chargalg_check_charger_connection(di); | ||
1207 | /* | ||
1208 | * First check if we have a charger connected. | ||
1209 | * Also we don't allow charging of unknown batteries if configured | ||
1210 | * this way | ||
1211 | */ | ||
1212 | if (!charger_status || | ||
1213 | (di->events.batt_unknown && !di->bat->chg_unknown_bat)) { | ||
1214 | if (di->charge_state != STATE_HANDHELD) { | ||
1215 | di->events.safety_timer_expired = false; | ||
1216 | abx500_chargalg_state_to(di, STATE_HANDHELD_INIT); | ||
1217 | } | ||
1218 | } | ||
1219 | |||
1220 | /* If suspended, we should not continue checking the flags */ | ||
1221 | else if (di->charge_state == STATE_SUSPENDED_INIT || | ||
1222 | di->charge_state == STATE_SUSPENDED) { | ||
1223 | /* We don't do anything here, just don,t continue */ | ||
1224 | } | ||
1225 | |||
1226 | /* Safety timer expiration */ | ||
1227 | else if (di->events.safety_timer_expired) { | ||
1228 | if (di->charge_state != STATE_SAFETY_TIMER_EXPIRED) | ||
1229 | abx500_chargalg_state_to(di, | ||
1230 | STATE_SAFETY_TIMER_EXPIRED_INIT); | ||
1231 | } | ||
1232 | /* | ||
1233 | * Check if any interrupts has occured | ||
1234 | * that will prevent us from charging | ||
1235 | */ | ||
1236 | |||
1237 | /* Battery removed */ | ||
1238 | else if (di->events.batt_rem) { | ||
1239 | if (di->charge_state != STATE_BATT_REMOVED) | ||
1240 | abx500_chargalg_state_to(di, STATE_BATT_REMOVED_INIT); | ||
1241 | } | ||
1242 | /* Main or USB charger not ok. */ | ||
1243 | else if (di->events.mainextchnotok || di->events.usbchargernotok) { | ||
1244 | /* | ||
1245 | * If vbus_collapsed is set, we have to lower the charger | ||
1246 | * current, which is done in the normal state below | ||
1247 | */ | ||
1248 | if (di->charge_state != STATE_CHG_NOT_OK && | ||
1249 | !di->events.vbus_collapsed) | ||
1250 | abx500_chargalg_state_to(di, STATE_CHG_NOT_OK_INIT); | ||
1251 | } | ||
1252 | /* VBUS, Main or VBAT OVV. */ | ||
1253 | else if (di->events.vbus_ovv || | ||
1254 | di->events.main_ovv || | ||
1255 | di->events.batt_ovv || | ||
1256 | !di->chg_info.usb_chg_ok || | ||
1257 | !di->chg_info.ac_chg_ok) { | ||
1258 | if (di->charge_state != STATE_OVV_PROTECT) | ||
1259 | abx500_chargalg_state_to(di, STATE_OVV_PROTECT_INIT); | ||
1260 | } | ||
1261 | /* USB Thermal, stop charging */ | ||
1262 | else if (di->events.main_thermal_prot || | ||
1263 | di->events.usb_thermal_prot) { | ||
1264 | if (di->charge_state != STATE_HW_TEMP_PROTECT) | ||
1265 | abx500_chargalg_state_to(di, | ||
1266 | STATE_HW_TEMP_PROTECT_INIT); | ||
1267 | } | ||
1268 | /* Battery temp over/under */ | ||
1269 | else if (di->events.btemp_underover) { | ||
1270 | if (di->charge_state != STATE_TEMP_UNDEROVER) | ||
1271 | abx500_chargalg_state_to(di, | ||
1272 | STATE_TEMP_UNDEROVER_INIT); | ||
1273 | } | ||
1274 | /* Watchdog expired */ | ||
1275 | else if (di->events.ac_wd_expired || | ||
1276 | di->events.usb_wd_expired) { | ||
1277 | if (di->charge_state != STATE_WD_EXPIRED) | ||
1278 | abx500_chargalg_state_to(di, STATE_WD_EXPIRED_INIT); | ||
1279 | } | ||
1280 | /* Battery temp high/low */ | ||
1281 | else if (di->events.btemp_lowhigh) { | ||
1282 | if (di->charge_state != STATE_TEMP_LOWHIGH) | ||
1283 | abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH_INIT); | ||
1284 | } | ||
1285 | |||
1286 | dev_dbg(di->dev, | ||
1287 | "[CHARGALG] Vb %d Ib_avg %d Ib_inst %d Tb %d Cap %d Maint %d " | ||
1288 | "State %s Active_chg %d Chg_status %d AC %d USB %d " | ||
1289 | "AC_online %d USB_online %d AC_CV %d USB_CV %d AC_I %d " | ||
1290 | "USB_I %d AC_Vset %d AC_Iset %d USB_Vset %d USB_Iset %d\n", | ||
1291 | di->batt_data.volt, | ||
1292 | di->batt_data.avg_curr, | ||
1293 | di->batt_data.inst_curr, | ||
1294 | di->batt_data.temp, | ||
1295 | di->batt_data.percent, | ||
1296 | di->maintenance_chg, | ||
1297 | states[di->charge_state], | ||
1298 | di->chg_info.charger_type, | ||
1299 | di->charge_status, | ||
1300 | di->chg_info.conn_chg & AC_CHG, | ||
1301 | di->chg_info.conn_chg & USB_CHG, | ||
1302 | di->chg_info.online_chg & AC_CHG, | ||
1303 | di->chg_info.online_chg & USB_CHG, | ||
1304 | di->events.ac_cv_active, | ||
1305 | di->events.usb_cv_active, | ||
1306 | di->chg_info.ac_curr, | ||
1307 | di->chg_info.usb_curr, | ||
1308 | di->chg_info.ac_vset, | ||
1309 | di->chg_info.ac_iset, | ||
1310 | di->chg_info.usb_vset, | ||
1311 | di->chg_info.usb_iset); | ||
1312 | |||
1313 | switch (di->charge_state) { | ||
1314 | case STATE_HANDHELD_INIT: | ||
1315 | abx500_chargalg_stop_charging(di); | ||
1316 | di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
1317 | abx500_chargalg_state_to(di, STATE_HANDHELD); | ||
1318 | /* Intentional fallthrough */ | ||
1319 | |||
1320 | case STATE_HANDHELD: | ||
1321 | break; | ||
1322 | |||
1323 | case STATE_SUSPENDED_INIT: | ||
1324 | if (di->susp_status.ac_suspended) | ||
1325 | abx500_chargalg_ac_en(di, false, 0, 0); | ||
1326 | if (di->susp_status.usb_suspended) | ||
1327 | abx500_chargalg_usb_en(di, false, 0, 0); | ||
1328 | abx500_chargalg_stop_safety_timer(di); | ||
1329 | abx500_chargalg_stop_maintenance_timer(di); | ||
1330 | di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
1331 | di->maintenance_chg = false; | ||
1332 | abx500_chargalg_state_to(di, STATE_SUSPENDED); | ||
1333 | power_supply_changed(&di->chargalg_psy); | ||
1334 | /* Intentional fallthrough */ | ||
1335 | |||
1336 | case STATE_SUSPENDED: | ||
1337 | /* CHARGING is suspended */ | ||
1338 | break; | ||
1339 | |||
1340 | case STATE_BATT_REMOVED_INIT: | ||
1341 | abx500_chargalg_stop_charging(di); | ||
1342 | abx500_chargalg_state_to(di, STATE_BATT_REMOVED); | ||
1343 | /* Intentional fallthrough */ | ||
1344 | |||
1345 | case STATE_BATT_REMOVED: | ||
1346 | if (!di->events.batt_rem) | ||
1347 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1348 | break; | ||
1349 | |||
1350 | case STATE_HW_TEMP_PROTECT_INIT: | ||
1351 | abx500_chargalg_stop_charging(di); | ||
1352 | abx500_chargalg_state_to(di, STATE_HW_TEMP_PROTECT); | ||
1353 | /* Intentional fallthrough */ | ||
1354 | |||
1355 | case STATE_HW_TEMP_PROTECT: | ||
1356 | if (!di->events.main_thermal_prot && | ||
1357 | !di->events.usb_thermal_prot) | ||
1358 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1359 | break; | ||
1360 | |||
1361 | case STATE_OVV_PROTECT_INIT: | ||
1362 | abx500_chargalg_stop_charging(di); | ||
1363 | abx500_chargalg_state_to(di, STATE_OVV_PROTECT); | ||
1364 | /* Intentional fallthrough */ | ||
1365 | |||
1366 | case STATE_OVV_PROTECT: | ||
1367 | if (!di->events.vbus_ovv && | ||
1368 | !di->events.main_ovv && | ||
1369 | !di->events.batt_ovv && | ||
1370 | di->chg_info.usb_chg_ok && | ||
1371 | di->chg_info.ac_chg_ok) | ||
1372 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1373 | break; | ||
1374 | |||
1375 | case STATE_CHG_NOT_OK_INIT: | ||
1376 | abx500_chargalg_stop_charging(di); | ||
1377 | abx500_chargalg_state_to(di, STATE_CHG_NOT_OK); | ||
1378 | /* Intentional fallthrough */ | ||
1379 | |||
1380 | case STATE_CHG_NOT_OK: | ||
1381 | if (!di->events.mainextchnotok && | ||
1382 | !di->events.usbchargernotok) | ||
1383 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1384 | break; | ||
1385 | |||
1386 | case STATE_SAFETY_TIMER_EXPIRED_INIT: | ||
1387 | abx500_chargalg_stop_charging(di); | ||
1388 | abx500_chargalg_state_to(di, STATE_SAFETY_TIMER_EXPIRED); | ||
1389 | /* Intentional fallthrough */ | ||
1390 | |||
1391 | case STATE_SAFETY_TIMER_EXPIRED: | ||
1392 | /* We exit this state when charger is removed */ | ||
1393 | break; | ||
1394 | |||
1395 | case STATE_NORMAL_INIT: | ||
1396 | abx500_chargalg_start_charging(di, | ||
1397 | di->bat->bat_type[di->bat->batt_id].normal_vol_lvl, | ||
1398 | di->bat->bat_type[di->bat->batt_id].normal_cur_lvl); | ||
1399 | abx500_chargalg_state_to(di, STATE_NORMAL); | ||
1400 | abx500_chargalg_start_safety_timer(di); | ||
1401 | abx500_chargalg_stop_maintenance_timer(di); | ||
1402 | init_maxim_chg_curr(di); | ||
1403 | di->charge_status = POWER_SUPPLY_STATUS_CHARGING; | ||
1404 | di->eoc_cnt = 0; | ||
1405 | di->maintenance_chg = false; | ||
1406 | power_supply_changed(&di->chargalg_psy); | ||
1407 | |||
1408 | break; | ||
1409 | |||
1410 | case STATE_NORMAL: | ||
1411 | handle_maxim_chg_curr(di); | ||
1412 | if (di->charge_status == POWER_SUPPLY_STATUS_FULL && | ||
1413 | di->maintenance_chg) { | ||
1414 | if (di->bat->no_maintenance) | ||
1415 | abx500_chargalg_state_to(di, | ||
1416 | STATE_WAIT_FOR_RECHARGE_INIT); | ||
1417 | else | ||
1418 | abx500_chargalg_state_to(di, | ||
1419 | STATE_MAINTENANCE_A_INIT); | ||
1420 | } | ||
1421 | break; | ||
1422 | |||
1423 | /* This state will be used when the maintenance state is disabled */ | ||
1424 | case STATE_WAIT_FOR_RECHARGE_INIT: | ||
1425 | abx500_chargalg_hold_charging(di); | ||
1426 | abx500_chargalg_state_to(di, STATE_WAIT_FOR_RECHARGE); | ||
1427 | di->rch_cnt = RCH_COND_CNT; | ||
1428 | /* Intentional fallthrough */ | ||
1429 | |||
1430 | case STATE_WAIT_FOR_RECHARGE: | ||
1431 | if (di->batt_data.volt <= | ||
1432 | di->bat->bat_type[di->bat->batt_id].recharge_vol) { | ||
1433 | if (di->rch_cnt-- == 0) | ||
1434 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1435 | } else | ||
1436 | di->rch_cnt = RCH_COND_CNT; | ||
1437 | break; | ||
1438 | |||
1439 | case STATE_MAINTENANCE_A_INIT: | ||
1440 | abx500_chargalg_stop_safety_timer(di); | ||
1441 | abx500_chargalg_start_maintenance_timer(di, | ||
1442 | di->bat->bat_type[ | ||
1443 | di->bat->batt_id].maint_a_chg_timer_h); | ||
1444 | abx500_chargalg_start_charging(di, | ||
1445 | di->bat->bat_type[ | ||
1446 | di->bat->batt_id].maint_a_vol_lvl, | ||
1447 | di->bat->bat_type[ | ||
1448 | di->bat->batt_id].maint_a_cur_lvl); | ||
1449 | abx500_chargalg_state_to(di, STATE_MAINTENANCE_A); | ||
1450 | power_supply_changed(&di->chargalg_psy); | ||
1451 | /* Intentional fallthrough*/ | ||
1452 | |||
1453 | case STATE_MAINTENANCE_A: | ||
1454 | if (di->events.maintenance_timer_expired) { | ||
1455 | abx500_chargalg_stop_maintenance_timer(di); | ||
1456 | abx500_chargalg_state_to(di, STATE_MAINTENANCE_B_INIT); | ||
1457 | } | ||
1458 | break; | ||
1459 | |||
1460 | case STATE_MAINTENANCE_B_INIT: | ||
1461 | abx500_chargalg_start_maintenance_timer(di, | ||
1462 | di->bat->bat_type[ | ||
1463 | di->bat->batt_id].maint_b_chg_timer_h); | ||
1464 | abx500_chargalg_start_charging(di, | ||
1465 | di->bat->bat_type[ | ||
1466 | di->bat->batt_id].maint_b_vol_lvl, | ||
1467 | di->bat->bat_type[ | ||
1468 | di->bat->batt_id].maint_b_cur_lvl); | ||
1469 | abx500_chargalg_state_to(di, STATE_MAINTENANCE_B); | ||
1470 | power_supply_changed(&di->chargalg_psy); | ||
1471 | /* Intentional fallthrough*/ | ||
1472 | |||
1473 | case STATE_MAINTENANCE_B: | ||
1474 | if (di->events.maintenance_timer_expired) { | ||
1475 | abx500_chargalg_stop_maintenance_timer(di); | ||
1476 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1477 | } | ||
1478 | break; | ||
1479 | |||
1480 | case STATE_TEMP_LOWHIGH_INIT: | ||
1481 | abx500_chargalg_start_charging(di, | ||
1482 | di->bat->bat_type[ | ||
1483 | di->bat->batt_id].low_high_vol_lvl, | ||
1484 | di->bat->bat_type[ | ||
1485 | di->bat->batt_id].low_high_cur_lvl); | ||
1486 | abx500_chargalg_stop_maintenance_timer(di); | ||
1487 | di->charge_status = POWER_SUPPLY_STATUS_CHARGING; | ||
1488 | abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH); | ||
1489 | power_supply_changed(&di->chargalg_psy); | ||
1490 | /* Intentional fallthrough */ | ||
1491 | |||
1492 | case STATE_TEMP_LOWHIGH: | ||
1493 | if (!di->events.btemp_lowhigh) | ||
1494 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1495 | break; | ||
1496 | |||
1497 | case STATE_WD_EXPIRED_INIT: | ||
1498 | abx500_chargalg_stop_charging(di); | ||
1499 | abx500_chargalg_state_to(di, STATE_WD_EXPIRED); | ||
1500 | /* Intentional fallthrough */ | ||
1501 | |||
1502 | case STATE_WD_EXPIRED: | ||
1503 | if (!di->events.ac_wd_expired && | ||
1504 | !di->events.usb_wd_expired) | ||
1505 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1506 | break; | ||
1507 | |||
1508 | case STATE_TEMP_UNDEROVER_INIT: | ||
1509 | abx500_chargalg_stop_charging(di); | ||
1510 | abx500_chargalg_state_to(di, STATE_TEMP_UNDEROVER); | ||
1511 | /* Intentional fallthrough */ | ||
1512 | |||
1513 | case STATE_TEMP_UNDEROVER: | ||
1514 | if (!di->events.btemp_underover) | ||
1515 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | ||
1516 | break; | ||
1517 | } | ||
1518 | |||
1519 | /* Start charging directly if the new state is a charge state */ | ||
1520 | if (di->charge_state == STATE_NORMAL_INIT || | ||
1521 | di->charge_state == STATE_MAINTENANCE_A_INIT || | ||
1522 | di->charge_state == STATE_MAINTENANCE_B_INIT) | ||
1523 | queue_work(di->chargalg_wq, &di->chargalg_work); | ||
1524 | } | ||
1525 | |||
1526 | /** | ||
1527 | * abx500_chargalg_periodic_work() - Periodic work for the algorithm | ||
1528 | * @work: pointer to the work_struct structure | ||
1529 | * | ||
1530 | * Work queue function for the charging algorithm | ||
1531 | */ | ||
1532 | static void abx500_chargalg_periodic_work(struct work_struct *work) | ||
1533 | { | ||
1534 | struct abx500_chargalg *di = container_of(work, | ||
1535 | struct abx500_chargalg, chargalg_periodic_work.work); | ||
1536 | |||
1537 | abx500_chargalg_algorithm(di); | ||
1538 | |||
1539 | /* | ||
1540 | * If a charger is connected then the battery has to be monitored | ||
1541 | * frequently, else the work can be delayed. | ||
1542 | */ | ||
1543 | if (di->chg_info.conn_chg) | ||
1544 | queue_delayed_work(di->chargalg_wq, | ||
1545 | &di->chargalg_periodic_work, | ||
1546 | di->bat->interval_charging * HZ); | ||
1547 | else | ||
1548 | queue_delayed_work(di->chargalg_wq, | ||
1549 | &di->chargalg_periodic_work, | ||
1550 | di->bat->interval_not_charging * HZ); | ||
1551 | } | ||
1552 | |||
1553 | /** | ||
1554 | * abx500_chargalg_wd_work() - periodic work to kick the charger watchdog | ||
1555 | * @work: pointer to the work_struct structure | ||
1556 | * | ||
1557 | * Work queue function for kicking the charger watchdog | ||
1558 | */ | ||
1559 | static void abx500_chargalg_wd_work(struct work_struct *work) | ||
1560 | { | ||
1561 | int ret; | ||
1562 | struct abx500_chargalg *di = container_of(work, | ||
1563 | struct abx500_chargalg, chargalg_wd_work.work); | ||
1564 | |||
1565 | dev_dbg(di->dev, "abx500_chargalg_wd_work\n"); | ||
1566 | |||
1567 | ret = abx500_chargalg_kick_watchdog(di); | ||
1568 | if (ret < 0) | ||
1569 | dev_err(di->dev, "failed to kick watchdog\n"); | ||
1570 | |||
1571 | queue_delayed_work(di->chargalg_wq, | ||
1572 | &di->chargalg_wd_work, CHG_WD_INTERVAL); | ||
1573 | } | ||
1574 | |||
1575 | /** | ||
1576 | * abx500_chargalg_work() - Work to run the charging algorithm instantly | ||
1577 | * @work: pointer to the work_struct structure | ||
1578 | * | ||
1579 | * Work queue function for calling the charging algorithm | ||
1580 | */ | ||
1581 | static void abx500_chargalg_work(struct work_struct *work) | ||
1582 | { | ||
1583 | struct abx500_chargalg *di = container_of(work, | ||
1584 | struct abx500_chargalg, chargalg_work); | ||
1585 | |||
1586 | abx500_chargalg_algorithm(di); | ||
1587 | } | ||
1588 | |||
1589 | /** | ||
1590 | * abx500_chargalg_get_property() - get the chargalg properties | ||
1591 | * @psy: pointer to the power_supply structure | ||
1592 | * @psp: pointer to the power_supply_property structure | ||
1593 | * @val: pointer to the power_supply_propval union | ||
1594 | * | ||
1595 | * This function gets called when an application tries to get the | ||
1596 | * chargalg properties by reading the sysfs files. | ||
1597 | * status: charging/discharging/full/unknown | ||
1598 | * health: health of the battery | ||
1599 | * Returns error code in case of failure else 0 on success | ||
1600 | */ | ||
1601 | static int abx500_chargalg_get_property(struct power_supply *psy, | ||
1602 | enum power_supply_property psp, | ||
1603 | union power_supply_propval *val) | ||
1604 | { | ||
1605 | struct abx500_chargalg *di; | ||
1606 | |||
1607 | di = to_abx500_chargalg_device_info(psy); | ||
1608 | |||
1609 | switch (psp) { | ||
1610 | case POWER_SUPPLY_PROP_STATUS: | ||
1611 | val->intval = di->charge_status; | ||
1612 | break; | ||
1613 | case POWER_SUPPLY_PROP_HEALTH: | ||
1614 | if (di->events.batt_ovv) { | ||
1615 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
1616 | } else if (di->events.btemp_underover) { | ||
1617 | if (di->batt_data.temp <= di->bat->temp_under) | ||
1618 | val->intval = POWER_SUPPLY_HEALTH_COLD; | ||
1619 | else | ||
1620 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
1621 | } else { | ||
1622 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
1623 | } | ||
1624 | break; | ||
1625 | default: | ||
1626 | return -EINVAL; | ||
1627 | } | ||
1628 | return 0; | ||
1629 | } | ||
1630 | |||
1631 | /* Exposure to the sysfs interface */ | ||
1632 | |||
1633 | /** | ||
1634 | * abx500_chargalg_sysfs_charger() - sysfs store operations | ||
1635 | * @kobj: pointer to the struct kobject | ||
1636 | * @attr: pointer to the struct attribute | ||
1637 | * @buf: buffer that holds the parameter passed from userspace | ||
1638 | * @length: length of the parameter passed | ||
1639 | * | ||
1640 | * Returns length of the buffer(input taken from user space) on success | ||
1641 | * else error code on failure | ||
1642 | * The operation to be performed on passing the parameters from the user space. | ||
1643 | */ | ||
1644 | static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj, | ||
1645 | struct attribute *attr, const char *buf, size_t length) | ||
1646 | { | ||
1647 | struct abx500_chargalg *di = container_of(kobj, | ||
1648 | struct abx500_chargalg, chargalg_kobject); | ||
1649 | long int param; | ||
1650 | int ac_usb; | ||
1651 | int ret; | ||
1652 | char entry = *attr->name; | ||
1653 | |||
1654 | switch (entry) { | ||
1655 | case 'c': | ||
1656 | ret = strict_strtol(buf, 10, ¶m); | ||
1657 | if (ret < 0) | ||
1658 | return ret; | ||
1659 | |||
1660 | ac_usb = param; | ||
1661 | switch (ac_usb) { | ||
1662 | case 0: | ||
1663 | /* Disable charging */ | ||
1664 | di->susp_status.ac_suspended = true; | ||
1665 | di->susp_status.usb_suspended = true; | ||
1666 | di->susp_status.suspended_change = true; | ||
1667 | /* Trigger a state change */ | ||
1668 | queue_work(di->chargalg_wq, | ||
1669 | &di->chargalg_work); | ||
1670 | break; | ||
1671 | case 1: | ||
1672 | /* Enable AC Charging */ | ||
1673 | di->susp_status.ac_suspended = false; | ||
1674 | di->susp_status.suspended_change = true; | ||
1675 | /* Trigger a state change */ | ||
1676 | queue_work(di->chargalg_wq, | ||
1677 | &di->chargalg_work); | ||
1678 | break; | ||
1679 | case 2: | ||
1680 | /* Enable USB charging */ | ||
1681 | di->susp_status.usb_suspended = false; | ||
1682 | di->susp_status.suspended_change = true; | ||
1683 | /* Trigger a state change */ | ||
1684 | queue_work(di->chargalg_wq, | ||
1685 | &di->chargalg_work); | ||
1686 | break; | ||
1687 | default: | ||
1688 | dev_info(di->dev, "Wrong input\n" | ||
1689 | "Enter 0. Disable AC/USB Charging\n" | ||
1690 | "1. Enable AC charging\n" | ||
1691 | "2. Enable USB Charging\n"); | ||
1692 | }; | ||
1693 | break; | ||
1694 | }; | ||
1695 | return strlen(buf); | ||
1696 | } | ||
1697 | |||
1698 | static struct attribute abx500_chargalg_en_charger = \ | ||
1699 | { | ||
1700 | .name = "chargalg", | ||
1701 | .mode = S_IWUGO, | ||
1702 | }; | ||
1703 | |||
1704 | static struct attribute *abx500_chargalg_chg[] = { | ||
1705 | &abx500_chargalg_en_charger, | ||
1706 | NULL | ||
1707 | }; | ||
1708 | |||
1709 | static const struct sysfs_ops abx500_chargalg_sysfs_ops = { | ||
1710 | .store = abx500_chargalg_sysfs_charger, | ||
1711 | }; | ||
1712 | |||
1713 | static struct kobj_type abx500_chargalg_ktype = { | ||
1714 | .sysfs_ops = &abx500_chargalg_sysfs_ops, | ||
1715 | .default_attrs = abx500_chargalg_chg, | ||
1716 | }; | ||
1717 | |||
1718 | /** | ||
1719 | * abx500_chargalg_sysfs_exit() - de-init of sysfs entry | ||
1720 | * @di: pointer to the struct abx500_chargalg | ||
1721 | * | ||
1722 | * This function removes the entry in sysfs. | ||
1723 | */ | ||
1724 | static void abx500_chargalg_sysfs_exit(struct abx500_chargalg *di) | ||
1725 | { | ||
1726 | kobject_del(&di->chargalg_kobject); | ||
1727 | } | ||
1728 | |||
1729 | /** | ||
1730 | * abx500_chargalg_sysfs_init() - init of sysfs entry | ||
1731 | * @di: pointer to the struct abx500_chargalg | ||
1732 | * | ||
1733 | * This function adds an entry in sysfs. | ||
1734 | * Returns error code in case of failure else 0(on success) | ||
1735 | */ | ||
1736 | static int abx500_chargalg_sysfs_init(struct abx500_chargalg *di) | ||
1737 | { | ||
1738 | int ret = 0; | ||
1739 | |||
1740 | ret = kobject_init_and_add(&di->chargalg_kobject, | ||
1741 | &abx500_chargalg_ktype, | ||
1742 | NULL, "abx500_chargalg"); | ||
1743 | if (ret < 0) | ||
1744 | dev_err(di->dev, "failed to create sysfs entry\n"); | ||
1745 | |||
1746 | return ret; | ||
1747 | } | ||
1748 | /* Exposure to the sysfs interface <<END>> */ | ||
1749 | |||
1750 | #if defined(CONFIG_PM) | ||
1751 | static int abx500_chargalg_resume(struct platform_device *pdev) | ||
1752 | { | ||
1753 | struct abx500_chargalg *di = platform_get_drvdata(pdev); | ||
1754 | |||
1755 | /* Kick charger watchdog if charging (any charger online) */ | ||
1756 | if (di->chg_info.online_chg) | ||
1757 | queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0); | ||
1758 | |||
1759 | /* | ||
1760 | * Run the charging algorithm directly to be sure we don't | ||
1761 | * do it too seldom | ||
1762 | */ | ||
1763 | queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0); | ||
1764 | |||
1765 | return 0; | ||
1766 | } | ||
1767 | |||
1768 | static int abx500_chargalg_suspend(struct platform_device *pdev, | ||
1769 | pm_message_t state) | ||
1770 | { | ||
1771 | struct abx500_chargalg *di = platform_get_drvdata(pdev); | ||
1772 | |||
1773 | if (di->chg_info.online_chg) | ||
1774 | cancel_delayed_work_sync(&di->chargalg_wd_work); | ||
1775 | |||
1776 | cancel_delayed_work_sync(&di->chargalg_periodic_work); | ||
1777 | |||
1778 | return 0; | ||
1779 | } | ||
1780 | #else | ||
1781 | #define abx500_chargalg_suspend NULL | ||
1782 | #define abx500_chargalg_resume NULL | ||
1783 | #endif | ||
1784 | |||
1785 | static int abx500_chargalg_remove(struct platform_device *pdev) | ||
1786 | { | ||
1787 | struct abx500_chargalg *di = platform_get_drvdata(pdev); | ||
1788 | |||
1789 | /* sysfs interface to enable/disbale charging from user space */ | ||
1790 | abx500_chargalg_sysfs_exit(di); | ||
1791 | |||
1792 | /* Delete the work queue */ | ||
1793 | destroy_workqueue(di->chargalg_wq); | ||
1794 | |||
1795 | flush_scheduled_work(); | ||
1796 | power_supply_unregister(&di->chargalg_psy); | ||
1797 | platform_set_drvdata(pdev, NULL); | ||
1798 | |||
1799 | return 0; | ||
1800 | } | ||
1801 | |||
1802 | static char *supply_interface[] = { | ||
1803 | "ab8500_fg", | ||
1804 | }; | ||
1805 | |||
1806 | static int abx500_chargalg_probe(struct platform_device *pdev) | ||
1807 | { | ||
1808 | struct device_node *np = pdev->dev.of_node; | ||
1809 | struct abx500_chargalg *di; | ||
1810 | int ret = 0; | ||
1811 | |||
1812 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); | ||
1813 | if (!di) { | ||
1814 | dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__); | ||
1815 | return -ENOMEM; | ||
1816 | } | ||
1817 | di->bat = pdev->mfd_cell->platform_data; | ||
1818 | if (!di->bat) { | ||
1819 | if (np) { | ||
1820 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | ||
1821 | if (ret) { | ||
1822 | dev_err(&pdev->dev, | ||
1823 | "failed to get battery information\n"); | ||
1824 | return ret; | ||
1825 | } | ||
1826 | } else { | ||
1827 | dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n"); | ||
1828 | return -EINVAL; | ||
1829 | } | ||
1830 | } else { | ||
1831 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
1832 | } | ||
1833 | |||
1834 | /* get device struct */ | ||
1835 | di->dev = &pdev->dev; | ||
1836 | |||
1837 | /* chargalg supply */ | ||
1838 | di->chargalg_psy.name = "abx500_chargalg"; | ||
1839 | di->chargalg_psy.type = POWER_SUPPLY_TYPE_BATTERY; | ||
1840 | di->chargalg_psy.properties = abx500_chargalg_props; | ||
1841 | di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props); | ||
1842 | di->chargalg_psy.get_property = abx500_chargalg_get_property; | ||
1843 | di->chargalg_psy.supplied_to = supply_interface; | ||
1844 | di->chargalg_psy.num_supplicants = ARRAY_SIZE(supply_interface), | ||
1845 | di->chargalg_psy.external_power_changed = | ||
1846 | abx500_chargalg_external_power_changed; | ||
1847 | |||
1848 | /* Initilialize safety timer */ | ||
1849 | init_timer(&di->safety_timer); | ||
1850 | di->safety_timer.function = abx500_chargalg_safety_timer_expired; | ||
1851 | di->safety_timer.data = (unsigned long) di; | ||
1852 | |||
1853 | /* Initilialize maintenance timer */ | ||
1854 | init_timer(&di->maintenance_timer); | ||
1855 | di->maintenance_timer.function = | ||
1856 | abx500_chargalg_maintenance_timer_expired; | ||
1857 | di->maintenance_timer.data = (unsigned long) di; | ||
1858 | |||
1859 | /* Create a work queue for the chargalg */ | ||
1860 | di->chargalg_wq = | ||
1861 | create_singlethread_workqueue("abx500_chargalg_wq"); | ||
1862 | if (di->chargalg_wq == NULL) { | ||
1863 | dev_err(di->dev, "failed to create work queue\n"); | ||
1864 | return -ENOMEM; | ||
1865 | } | ||
1866 | |||
1867 | /* Init work for chargalg */ | ||
1868 | INIT_DEFERRABLE_WORK(&di->chargalg_periodic_work, | ||
1869 | abx500_chargalg_periodic_work); | ||
1870 | INIT_DEFERRABLE_WORK(&di->chargalg_wd_work, | ||
1871 | abx500_chargalg_wd_work); | ||
1872 | |||
1873 | /* Init work for chargalg */ | ||
1874 | INIT_WORK(&di->chargalg_work, abx500_chargalg_work); | ||
1875 | |||
1876 | /* To detect charger at startup */ | ||
1877 | di->chg_info.prev_conn_chg = -1; | ||
1878 | |||
1879 | /* Register chargalg power supply class */ | ||
1880 | ret = power_supply_register(di->dev, &di->chargalg_psy); | ||
1881 | if (ret) { | ||
1882 | dev_err(di->dev, "failed to register chargalg psy\n"); | ||
1883 | goto free_chargalg_wq; | ||
1884 | } | ||
1885 | |||
1886 | platform_set_drvdata(pdev, di); | ||
1887 | |||
1888 | /* sysfs interface to enable/disable charging from user space */ | ||
1889 | ret = abx500_chargalg_sysfs_init(di); | ||
1890 | if (ret) { | ||
1891 | dev_err(di->dev, "failed to create sysfs entry\n"); | ||
1892 | goto free_psy; | ||
1893 | } | ||
1894 | |||
1895 | /* Run the charging algorithm */ | ||
1896 | queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0); | ||
1897 | |||
1898 | dev_info(di->dev, "probe success\n"); | ||
1899 | return ret; | ||
1900 | |||
1901 | free_psy: | ||
1902 | power_supply_unregister(&di->chargalg_psy); | ||
1903 | free_chargalg_wq: | ||
1904 | destroy_workqueue(di->chargalg_wq); | ||
1905 | return ret; | ||
1906 | } | ||
1907 | |||
1908 | static const struct of_device_id ab8500_chargalg_match[] = { | ||
1909 | { .compatible = "stericsson,ab8500-chargalg", }, | ||
1910 | { }, | ||
1911 | }; | ||
1912 | |||
1913 | static struct platform_driver abx500_chargalg_driver = { | ||
1914 | .probe = abx500_chargalg_probe, | ||
1915 | .remove = abx500_chargalg_remove, | ||
1916 | .suspend = abx500_chargalg_suspend, | ||
1917 | .resume = abx500_chargalg_resume, | ||
1918 | .driver = { | ||
1919 | .name = "ab8500-chargalg", | ||
1920 | .owner = THIS_MODULE, | ||
1921 | .of_match_table = ab8500_chargalg_match, | ||
1922 | }, | ||
1923 | }; | ||
1924 | |||
1925 | static int __init abx500_chargalg_init(void) | ||
1926 | { | ||
1927 | return platform_driver_register(&abx500_chargalg_driver); | ||
1928 | } | ||
1929 | |||
1930 | static void __exit abx500_chargalg_exit(void) | ||
1931 | { | ||
1932 | platform_driver_unregister(&abx500_chargalg_driver); | ||
1933 | } | ||
1934 | |||
1935 | module_init(abx500_chargalg_init); | ||
1936 | module_exit(abx500_chargalg_exit); | ||
1937 | |||
1938 | MODULE_LICENSE("GPL v2"); | ||
1939 | MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); | ||
1940 | MODULE_ALIAS("platform:abx500-chargalg"); | ||
1941 | MODULE_DESCRIPTION("abx500 battery charging algorithm"); | ||
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index 39763015b36..8a612dec913 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c | |||
@@ -10,7 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/device.h> | ||
14 | #include <linux/power_supply.h> | 13 | #include <linux/power_supply.h> |
15 | #include <linux/apm-emulation.h> | 14 | #include <linux/apm-emulation.h> |
16 | 15 | ||
diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig deleted file mode 100644 index 2a1008b6112..00000000000 --- a/drivers/power/avs/Kconfig +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | menuconfig POWER_AVS | ||
2 | bool "Adaptive Voltage Scaling class support" | ||
3 | help | ||
4 | AVS is a power management technique which finely controls the | ||
5 | operating voltage of a device in order to optimize (i.e. reduce) | ||
6 | its power consumption. | ||
7 | At a given operating point the voltage is adapted depending on | ||
8 | static factors (chip manufacturing process) and dynamic factors | ||
9 | (temperature depending performance). | ||
10 | AVS is also called SmartReflex on OMAP devices. | ||
11 | |||
12 | Say Y here to enable Adaptive Voltage Scaling class support. | ||
diff --git a/drivers/power/avs/Makefile b/drivers/power/avs/Makefile deleted file mode 100644 index 0843386a6c1..00000000000 --- a/drivers/power/avs/Makefile +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | obj-$(CONFIG_POWER_AVS_OMAP) += smartreflex.o | ||
diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c deleted file mode 100644 index 6b2238bb6a8..00000000000 --- a/drivers/power/avs/smartreflex.c +++ /dev/null | |||
@@ -1,1106 +0,0 @@ | |||
1 | /* | ||
2 | * OMAP SmartReflex Voltage Control | ||
3 | * | ||
4 | * Author: Thara Gopinath <thara@ti.com> | ||
5 | * | ||
6 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
7 | * Thara Gopinath <thara@ti.com> | ||
8 | * | ||
9 | * Copyright (C) 2008 Nokia Corporation | ||
10 | * Kalle Jokiniemi | ||
11 | * | ||
12 | * Copyright (C) 2007 Texas Instruments, Inc. | ||
13 | * Lesly A M <x0080970@ti.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License version 2 as | ||
17 | * published by the Free Software Foundation. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/debugfs.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/pm_runtime.h> | ||
28 | #include <linux/power/smartreflex.h> | ||
29 | |||
30 | #define SMARTREFLEX_NAME_LEN 16 | ||
31 | #define NVALUE_NAME_LEN 40 | ||
32 | #define SR_DISABLE_TIMEOUT 200 | ||
33 | |||
34 | /* sr_list contains all the instances of smartreflex module */ | ||
35 | static LIST_HEAD(sr_list); | ||
36 | |||
37 | static struct omap_sr_class_data *sr_class; | ||
38 | static struct omap_sr_pmic_data *sr_pmic_data; | ||
39 | static struct dentry *sr_dbg_dir; | ||
40 | |||
41 | static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value) | ||
42 | { | ||
43 | __raw_writel(value, (sr->base + offset)); | ||
44 | } | ||
45 | |||
46 | static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask, | ||
47 | u32 value) | ||
48 | { | ||
49 | u32 reg_val; | ||
50 | |||
51 | /* | ||
52 | * Smartreflex error config register is special as it contains | ||
53 | * certain status bits which if written a 1 into means a clear | ||
54 | * of those bits. So in order to make sure no accidental write of | ||
55 | * 1 happens to those status bits, do a clear of them in the read | ||
56 | * value. This mean this API doesn't rewrite values in these bits | ||
57 | * if they are currently set, but does allow the caller to write | ||
58 | * those bits. | ||
59 | */ | ||
60 | if (sr->ip_type == SR_TYPE_V1 && offset == ERRCONFIG_V1) | ||
61 | mask |= ERRCONFIG_STATUS_V1_MASK; | ||
62 | else if (sr->ip_type == SR_TYPE_V2 && offset == ERRCONFIG_V2) | ||
63 | mask |= ERRCONFIG_VPBOUNDINTST_V2; | ||
64 | |||
65 | reg_val = __raw_readl(sr->base + offset); | ||
66 | reg_val &= ~mask; | ||
67 | |||
68 | value &= mask; | ||
69 | |||
70 | reg_val |= value; | ||
71 | |||
72 | __raw_writel(reg_val, (sr->base + offset)); | ||
73 | } | ||
74 | |||
75 | static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset) | ||
76 | { | ||
77 | return __raw_readl(sr->base + offset); | ||
78 | } | ||
79 | |||
80 | static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm) | ||
81 | { | ||
82 | struct omap_sr *sr_info; | ||
83 | |||
84 | if (!voltdm) { | ||
85 | pr_err("%s: Null voltage domain passed!\n", __func__); | ||
86 | return ERR_PTR(-EINVAL); | ||
87 | } | ||
88 | |||
89 | list_for_each_entry(sr_info, &sr_list, node) { | ||
90 | if (voltdm == sr_info->voltdm) | ||
91 | return sr_info; | ||
92 | } | ||
93 | |||
94 | return ERR_PTR(-ENODATA); | ||
95 | } | ||
96 | |||
97 | static irqreturn_t sr_interrupt(int irq, void *data) | ||
98 | { | ||
99 | struct omap_sr *sr_info = data; | ||
100 | u32 status = 0; | ||
101 | |||
102 | switch (sr_info->ip_type) { | ||
103 | case SR_TYPE_V1: | ||
104 | /* Read the status bits */ | ||
105 | status = sr_read_reg(sr_info, ERRCONFIG_V1); | ||
106 | |||
107 | /* Clear them by writing back */ | ||
108 | sr_write_reg(sr_info, ERRCONFIG_V1, status); | ||
109 | break; | ||
110 | case SR_TYPE_V2: | ||
111 | /* Read the status bits */ | ||
112 | status = sr_read_reg(sr_info, IRQSTATUS); | ||
113 | |||
114 | /* Clear them by writing back */ | ||
115 | sr_write_reg(sr_info, IRQSTATUS, status); | ||
116 | break; | ||
117 | default: | ||
118 | dev_err(&sr_info->pdev->dev, "UNKNOWN IP type %d\n", | ||
119 | sr_info->ip_type); | ||
120 | return IRQ_NONE; | ||
121 | } | ||
122 | |||
123 | if (sr_class->notify) | ||
124 | sr_class->notify(sr_info, status); | ||
125 | |||
126 | return IRQ_HANDLED; | ||
127 | } | ||
128 | |||
129 | static void sr_set_clk_length(struct omap_sr *sr) | ||
130 | { | ||
131 | struct clk *fck; | ||
132 | u32 fclk_speed; | ||
133 | |||
134 | fck = clk_get(&sr->pdev->dev, "fck"); | ||
135 | |||
136 | if (IS_ERR(fck)) { | ||
137 | dev_err(&sr->pdev->dev, "%s: unable to get fck for device %s\n", | ||
138 | __func__, dev_name(&sr->pdev->dev)); | ||
139 | return; | ||
140 | } | ||
141 | |||
142 | fclk_speed = clk_get_rate(fck); | ||
143 | clk_put(fck); | ||
144 | |||
145 | switch (fclk_speed) { | ||
146 | case 12000000: | ||
147 | sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK; | ||
148 | break; | ||
149 | case 13000000: | ||
150 | sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK; | ||
151 | break; | ||
152 | case 19200000: | ||
153 | sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK; | ||
154 | break; | ||
155 | case 26000000: | ||
156 | sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK; | ||
157 | break; | ||
158 | case 38400000: | ||
159 | sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK; | ||
160 | break; | ||
161 | default: | ||
162 | dev_err(&sr->pdev->dev, "%s: Invalid fclk rate: %d\n", | ||
163 | __func__, fclk_speed); | ||
164 | break; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static void sr_start_vddautocomp(struct omap_sr *sr) | ||
169 | { | ||
170 | if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { | ||
171 | dev_warn(&sr->pdev->dev, | ||
172 | "%s: smartreflex class driver not registered\n", | ||
173 | __func__); | ||
174 | return; | ||
175 | } | ||
176 | |||
177 | if (!sr_class->enable(sr)) | ||
178 | sr->autocomp_active = true; | ||
179 | } | ||
180 | |||
181 | static void sr_stop_vddautocomp(struct omap_sr *sr) | ||
182 | { | ||
183 | if (!sr_class || !(sr_class->disable)) { | ||
184 | dev_warn(&sr->pdev->dev, | ||
185 | "%s: smartreflex class driver not registered\n", | ||
186 | __func__); | ||
187 | return; | ||
188 | } | ||
189 | |||
190 | if (sr->autocomp_active) { | ||
191 | sr_class->disable(sr, 1); | ||
192 | sr->autocomp_active = false; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * This function handles the intializations which have to be done | ||
198 | * only when both sr device and class driver regiter has | ||
199 | * completed. This will be attempted to be called from both sr class | ||
200 | * driver register and sr device intializtion API's. Only one call | ||
201 | * will ultimately succeed. | ||
202 | * | ||
203 | * Currently this function registers interrupt handler for a particular SR | ||
204 | * if smartreflex class driver is already registered and has | ||
205 | * requested for interrupts and the SR interrupt line in present. | ||
206 | */ | ||
207 | static int sr_late_init(struct omap_sr *sr_info) | ||
208 | { | ||
209 | struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data; | ||
210 | struct resource *mem; | ||
211 | int ret = 0; | ||
212 | |||
213 | if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { | ||
214 | ret = request_irq(sr_info->irq, sr_interrupt, | ||
215 | 0, sr_info->name, sr_info); | ||
216 | if (ret) | ||
217 | goto error; | ||
218 | disable_irq(sr_info->irq); | ||
219 | } | ||
220 | |||
221 | if (pdata && pdata->enable_on_init) | ||
222 | sr_start_vddautocomp(sr_info); | ||
223 | |||
224 | return ret; | ||
225 | |||
226 | error: | ||
227 | iounmap(sr_info->base); | ||
228 | mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0); | ||
229 | release_mem_region(mem->start, resource_size(mem)); | ||
230 | list_del(&sr_info->node); | ||
231 | dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" | ||
232 | "interrupt handler. Smartreflex will" | ||
233 | "not function as desired\n", __func__); | ||
234 | kfree(sr_info); | ||
235 | |||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static void sr_v1_disable(struct omap_sr *sr) | ||
240 | { | ||
241 | int timeout = 0; | ||
242 | int errconf_val = ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST | | ||
243 | ERRCONFIG_MCUBOUNDINTST; | ||
244 | |||
245 | /* Enable MCUDisableAcknowledge interrupt */ | ||
246 | sr_modify_reg(sr, ERRCONFIG_V1, | ||
247 | ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN); | ||
248 | |||
249 | /* SRCONFIG - disable SR */ | ||
250 | sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0); | ||
251 | |||
252 | /* Disable all other SR interrupts and clear the status as needed */ | ||
253 | if (sr_read_reg(sr, ERRCONFIG_V1) & ERRCONFIG_VPBOUNDINTST_V1) | ||
254 | errconf_val |= ERRCONFIG_VPBOUNDINTST_V1; | ||
255 | sr_modify_reg(sr, ERRCONFIG_V1, | ||
256 | (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN | | ||
257 | ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1), | ||
258 | errconf_val); | ||
259 | |||
260 | /* | ||
261 | * Wait for SR to be disabled. | ||
262 | * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us. | ||
263 | */ | ||
264 | sr_test_cond_timeout((sr_read_reg(sr, ERRCONFIG_V1) & | ||
265 | ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT, | ||
266 | timeout); | ||
267 | |||
268 | if (timeout >= SR_DISABLE_TIMEOUT) | ||
269 | dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", | ||
270 | __func__); | ||
271 | |||
272 | /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */ | ||
273 | sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN, | ||
274 | ERRCONFIG_MCUDISACKINTST); | ||
275 | } | ||
276 | |||
277 | static void sr_v2_disable(struct omap_sr *sr) | ||
278 | { | ||
279 | int timeout = 0; | ||
280 | |||
281 | /* Enable MCUDisableAcknowledge interrupt */ | ||
282 | sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT); | ||
283 | |||
284 | /* SRCONFIG - disable SR */ | ||
285 | sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0); | ||
286 | |||
287 | /* | ||
288 | * Disable all other SR interrupts and clear the status | ||
289 | * write to status register ONLY on need basis - only if status | ||
290 | * is set. | ||
291 | */ | ||
292 | if (sr_read_reg(sr, ERRCONFIG_V2) & ERRCONFIG_VPBOUNDINTST_V2) | ||
293 | sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2, | ||
294 | ERRCONFIG_VPBOUNDINTST_V2); | ||
295 | else | ||
296 | sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2, | ||
297 | 0x0); | ||
298 | sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT | | ||
299 | IRQENABLE_MCUVALIDINT | | ||
300 | IRQENABLE_MCUBOUNDSINT)); | ||
301 | sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT | | ||
302 | IRQSTATUS_MCVALIDINT | | ||
303 | IRQSTATUS_MCBOUNDSINT)); | ||
304 | |||
305 | /* | ||
306 | * Wait for SR to be disabled. | ||
307 | * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us. | ||
308 | */ | ||
309 | sr_test_cond_timeout((sr_read_reg(sr, IRQSTATUS) & | ||
310 | IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT, | ||
311 | timeout); | ||
312 | |||
313 | if (timeout >= SR_DISABLE_TIMEOUT) | ||
314 | dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", | ||
315 | __func__); | ||
316 | |||
317 | /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */ | ||
318 | sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT); | ||
319 | sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT); | ||
320 | } | ||
321 | |||
322 | static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row( | ||
323 | struct omap_sr *sr, u32 efuse_offs) | ||
324 | { | ||
325 | int i; | ||
326 | |||
327 | if (!sr->nvalue_table) { | ||
328 | dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n", | ||
329 | __func__); | ||
330 | return NULL; | ||
331 | } | ||
332 | |||
333 | for (i = 0; i < sr->nvalue_count; i++) { | ||
334 | if (sr->nvalue_table[i].efuse_offs == efuse_offs) | ||
335 | return &sr->nvalue_table[i]; | ||
336 | } | ||
337 | |||
338 | return NULL; | ||
339 | } | ||
340 | |||
341 | /* Public Functions */ | ||
342 | |||
343 | /** | ||
344 | * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the | ||
345 | * error generator module. | ||
346 | * @voltdm: VDD pointer to which the SR module to be configured belongs to. | ||
347 | * | ||
348 | * This API is to be called from the smartreflex class driver to | ||
349 | * configure the error generator module inside the smartreflex module. | ||
350 | * SR settings if using the ERROR module inside Smartreflex. | ||
351 | * SR CLASS 3 by default uses only the ERROR module where as | ||
352 | * SR CLASS 2 can choose between ERROR module and MINMAXAVG | ||
353 | * module. Returns 0 on success and error value in case of failure. | ||
354 | */ | ||
355 | int sr_configure_errgen(struct voltagedomain *voltdm) | ||
356 | { | ||
357 | u32 sr_config, sr_errconfig, errconfig_offs; | ||
358 | u32 vpboundint_en, vpboundint_st; | ||
359 | u32 senp_en = 0, senn_en = 0; | ||
360 | u8 senp_shift, senn_shift; | ||
361 | struct omap_sr *sr = _sr_lookup(voltdm); | ||
362 | |||
363 | if (IS_ERR(sr)) { | ||
364 | pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); | ||
365 | return PTR_ERR(sr); | ||
366 | } | ||
367 | |||
368 | if (!sr->clk_length) | ||
369 | sr_set_clk_length(sr); | ||
370 | |||
371 | senp_en = sr->senp_mod; | ||
372 | senn_en = sr->senn_mod; | ||
373 | |||
374 | sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) | | ||
375 | SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN; | ||
376 | |||
377 | switch (sr->ip_type) { | ||
378 | case SR_TYPE_V1: | ||
379 | sr_config |= SRCONFIG_DELAYCTRL; | ||
380 | senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT; | ||
381 | senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT; | ||
382 | errconfig_offs = ERRCONFIG_V1; | ||
383 | vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1; | ||
384 | vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1; | ||
385 | break; | ||
386 | case SR_TYPE_V2: | ||
387 | senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT; | ||
388 | senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT; | ||
389 | errconfig_offs = ERRCONFIG_V2; | ||
390 | vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2; | ||
391 | vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2; | ||
392 | break; | ||
393 | default: | ||
394 | dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" | ||
395 | "module without specifying the ip\n", __func__); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | |||
399 | sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift)); | ||
400 | sr_write_reg(sr, SRCONFIG, sr_config); | ||
401 | sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) | | ||
402 | (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) | | ||
403 | (sr->err_minlimit << ERRCONFIG_ERRMINLIMIT_SHIFT); | ||
404 | sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK | | ||
405 | SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK), | ||
406 | sr_errconfig); | ||
407 | |||
408 | /* Enabling the interrupts if the ERROR module is used */ | ||
409 | sr_modify_reg(sr, errconfig_offs, (vpboundint_en | vpboundint_st), | ||
410 | vpboundint_en); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * sr_disable_errgen() - Disables SmartReflex AVS module's errgen component | ||
417 | * @voltdm: VDD pointer to which the SR module to be configured belongs to. | ||
418 | * | ||
419 | * This API is to be called from the smartreflex class driver to | ||
420 | * disable the error generator module inside the smartreflex module. | ||
421 | * | ||
422 | * Returns 0 on success and error value in case of failure. | ||
423 | */ | ||
424 | int sr_disable_errgen(struct voltagedomain *voltdm) | ||
425 | { | ||
426 | u32 errconfig_offs; | ||
427 | u32 vpboundint_en, vpboundint_st; | ||
428 | struct omap_sr *sr = _sr_lookup(voltdm); | ||
429 | |||
430 | if (IS_ERR(sr)) { | ||
431 | pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); | ||
432 | return PTR_ERR(sr); | ||
433 | } | ||
434 | |||
435 | switch (sr->ip_type) { | ||
436 | case SR_TYPE_V1: | ||
437 | errconfig_offs = ERRCONFIG_V1; | ||
438 | vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1; | ||
439 | vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1; | ||
440 | break; | ||
441 | case SR_TYPE_V2: | ||
442 | errconfig_offs = ERRCONFIG_V2; | ||
443 | vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2; | ||
444 | vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2; | ||
445 | break; | ||
446 | default: | ||
447 | dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" | ||
448 | "module without specifying the ip\n", __func__); | ||
449 | return -EINVAL; | ||
450 | } | ||
451 | |||
452 | /* Disable the interrupts of ERROR module */ | ||
453 | sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0); | ||
454 | |||
455 | /* Disable the Sensor and errorgen */ | ||
456 | sr_modify_reg(sr, SRCONFIG, SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN, 0); | ||
457 | |||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | /** | ||
462 | * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the | ||
463 | * minmaxavg module. | ||
464 | * @voltdm: VDD pointer to which the SR module to be configured belongs to. | ||
465 | * | ||
466 | * This API is to be called from the smartreflex class driver to | ||
467 | * configure the minmaxavg module inside the smartreflex module. | ||
468 | * SR settings if using the ERROR module inside Smartreflex. | ||
469 | * SR CLASS 3 by default uses only the ERROR module where as | ||
470 | * SR CLASS 2 can choose between ERROR module and MINMAXAVG | ||
471 | * module. Returns 0 on success and error value in case of failure. | ||
472 | */ | ||
473 | int sr_configure_minmax(struct voltagedomain *voltdm) | ||
474 | { | ||
475 | u32 sr_config, sr_avgwt; | ||
476 | u32 senp_en = 0, senn_en = 0; | ||
477 | u8 senp_shift, senn_shift; | ||
478 | struct omap_sr *sr = _sr_lookup(voltdm); | ||
479 | |||
480 | if (IS_ERR(sr)) { | ||
481 | pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); | ||
482 | return PTR_ERR(sr); | ||
483 | } | ||
484 | |||
485 | if (!sr->clk_length) | ||
486 | sr_set_clk_length(sr); | ||
487 | |||
488 | senp_en = sr->senp_mod; | ||
489 | senn_en = sr->senn_mod; | ||
490 | |||
491 | sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) | | ||
492 | SRCONFIG_SENENABLE | | ||
493 | (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT); | ||
494 | |||
495 | switch (sr->ip_type) { | ||
496 | case SR_TYPE_V1: | ||
497 | sr_config |= SRCONFIG_DELAYCTRL; | ||
498 | senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT; | ||
499 | senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT; | ||
500 | break; | ||
501 | case SR_TYPE_V2: | ||
502 | senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT; | ||
503 | senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT; | ||
504 | break; | ||
505 | default: | ||
506 | dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" | ||
507 | "module without specifying the ip\n", __func__); | ||
508 | return -EINVAL; | ||
509 | } | ||
510 | |||
511 | sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift)); | ||
512 | sr_write_reg(sr, SRCONFIG, sr_config); | ||
513 | sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) | | ||
514 | (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT); | ||
515 | sr_write_reg(sr, AVGWEIGHT, sr_avgwt); | ||
516 | |||
517 | /* | ||
518 | * Enabling the interrupts if MINMAXAVG module is used. | ||
519 | * TODO: check if all the interrupts are mandatory | ||
520 | */ | ||
521 | switch (sr->ip_type) { | ||
522 | case SR_TYPE_V1: | ||
523 | sr_modify_reg(sr, ERRCONFIG_V1, | ||
524 | (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN | | ||
525 | ERRCONFIG_MCUBOUNDINTEN), | ||
526 | (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST | | ||
527 | ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST | | ||
528 | ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST)); | ||
529 | break; | ||
530 | case SR_TYPE_V2: | ||
531 | sr_write_reg(sr, IRQSTATUS, | ||
532 | IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT | | ||
533 | IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT); | ||
534 | sr_write_reg(sr, IRQENABLE_SET, | ||
535 | IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT | | ||
536 | IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT); | ||
537 | break; | ||
538 | default: | ||
539 | dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" | ||
540 | "module without specifying the ip\n", __func__); | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | /** | ||
548 | * sr_enable() - Enables the smartreflex module. | ||
549 | * @voltdm: VDD pointer to which the SR module to be configured belongs to. | ||
550 | * @volt: The voltage at which the Voltage domain associated with | ||
551 | * the smartreflex module is operating at. | ||
552 | * This is required only to program the correct Ntarget value. | ||
553 | * | ||
554 | * This API is to be called from the smartreflex class driver to | ||
555 | * enable a smartreflex module. Returns 0 on success. Returns error | ||
556 | * value if the voltage passed is wrong or if ntarget value is wrong. | ||
557 | */ | ||
558 | int sr_enable(struct voltagedomain *voltdm, unsigned long volt) | ||
559 | { | ||
560 | struct omap_volt_data *volt_data; | ||
561 | struct omap_sr *sr = _sr_lookup(voltdm); | ||
562 | struct omap_sr_nvalue_table *nvalue_row; | ||
563 | int ret; | ||
564 | |||
565 | if (IS_ERR(sr)) { | ||
566 | pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); | ||
567 | return PTR_ERR(sr); | ||
568 | } | ||
569 | |||
570 | volt_data = omap_voltage_get_voltdata(sr->voltdm, volt); | ||
571 | |||
572 | if (IS_ERR(volt_data)) { | ||
573 | dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table" | ||
574 | "for nominal voltage %ld\n", __func__, volt); | ||
575 | return PTR_ERR(volt_data); | ||
576 | } | ||
577 | |||
578 | nvalue_row = sr_retrieve_nvalue_row(sr, volt_data->sr_efuse_offs); | ||
579 | |||
580 | if (!nvalue_row) { | ||
581 | dev_warn(&sr->pdev->dev, "%s: failure getting SR data for this voltage %ld\n", | ||
582 | __func__, volt); | ||
583 | return -ENODATA; | ||
584 | } | ||
585 | |||
586 | /* errminlimit is opp dependent and hence linked to voltage */ | ||
587 | sr->err_minlimit = nvalue_row->errminlimit; | ||
588 | |||
589 | pm_runtime_get_sync(&sr->pdev->dev); | ||
590 | |||
591 | /* Check if SR is already enabled. If yes do nothing */ | ||
592 | if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) | ||
593 | return 0; | ||
594 | |||
595 | /* Configure SR */ | ||
596 | ret = sr_class->configure(sr); | ||
597 | if (ret) | ||
598 | return ret; | ||
599 | |||
600 | sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue); | ||
601 | |||
602 | /* SRCONFIG - enable SR */ | ||
603 | sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE); | ||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | /** | ||
608 | * sr_disable() - Disables the smartreflex module. | ||
609 | * @voltdm: VDD pointer to which the SR module to be configured belongs to. | ||
610 | * | ||
611 | * This API is to be called from the smartreflex class driver to | ||
612 | * disable a smartreflex module. | ||
613 | */ | ||
614 | void sr_disable(struct voltagedomain *voltdm) | ||
615 | { | ||
616 | struct omap_sr *sr = _sr_lookup(voltdm); | ||
617 | |||
618 | if (IS_ERR(sr)) { | ||
619 | pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); | ||
620 | return; | ||
621 | } | ||
622 | |||
623 | /* Check if SR clocks are already disabled. If yes do nothing */ | ||
624 | if (pm_runtime_suspended(&sr->pdev->dev)) | ||
625 | return; | ||
626 | |||
627 | /* | ||
628 | * Disable SR if only it is indeed enabled. Else just | ||
629 | * disable the clocks. | ||
630 | */ | ||
631 | if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) { | ||
632 | switch (sr->ip_type) { | ||
633 | case SR_TYPE_V1: | ||
634 | sr_v1_disable(sr); | ||
635 | break; | ||
636 | case SR_TYPE_V2: | ||
637 | sr_v2_disable(sr); | ||
638 | break; | ||
639 | default: | ||
640 | dev_err(&sr->pdev->dev, "UNKNOWN IP type %d\n", | ||
641 | sr->ip_type); | ||
642 | } | ||
643 | } | ||
644 | |||
645 | pm_runtime_put_sync_suspend(&sr->pdev->dev); | ||
646 | } | ||
647 | |||
648 | /** | ||
649 | * sr_register_class() - API to register a smartreflex class parameters. | ||
650 | * @class_data: The structure containing various sr class specific data. | ||
651 | * | ||
652 | * This API is to be called by the smartreflex class driver to register itself | ||
653 | * with the smartreflex driver during init. Returns 0 on success else the | ||
654 | * error value. | ||
655 | */ | ||
656 | int sr_register_class(struct omap_sr_class_data *class_data) | ||
657 | { | ||
658 | struct omap_sr *sr_info; | ||
659 | |||
660 | if (!class_data) { | ||
661 | pr_warning("%s:, Smartreflex class data passed is NULL\n", | ||
662 | __func__); | ||
663 | return -EINVAL; | ||
664 | } | ||
665 | |||
666 | if (sr_class) { | ||
667 | pr_warning("%s: Smartreflex class driver already registered\n", | ||
668 | __func__); | ||
669 | return -EBUSY; | ||
670 | } | ||
671 | |||
672 | sr_class = class_data; | ||
673 | |||
674 | /* | ||
675 | * Call into late init to do intializations that require | ||
676 | * both sr driver and sr class driver to be initiallized. | ||
677 | */ | ||
678 | list_for_each_entry(sr_info, &sr_list, node) | ||
679 | sr_late_init(sr_info); | ||
680 | |||
681 | return 0; | ||
682 | } | ||
683 | |||
684 | /** | ||
685 | * omap_sr_enable() - API to enable SR clocks and to call into the | ||
686 | * registered smartreflex class enable API. | ||
687 | * @voltdm: VDD pointer to which the SR module to be configured belongs to. | ||
688 | * | ||
689 | * This API is to be called from the kernel in order to enable | ||
690 | * a particular smartreflex module. This API will do the initial | ||
691 | * configurations to turn on the smartreflex module and in turn call | ||
692 | * into the registered smartreflex class enable API. | ||
693 | */ | ||
694 | void omap_sr_enable(struct voltagedomain *voltdm) | ||
695 | { | ||
696 | struct omap_sr *sr = _sr_lookup(voltdm); | ||
697 | |||
698 | if (IS_ERR(sr)) { | ||
699 | pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); | ||
700 | return; | ||
701 | } | ||
702 | |||
703 | if (!sr->autocomp_active) | ||
704 | return; | ||
705 | |||
706 | if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { | ||
707 | dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" | ||
708 | "registered\n", __func__); | ||
709 | return; | ||
710 | } | ||
711 | |||
712 | sr_class->enable(sr); | ||
713 | } | ||
714 | |||
715 | /** | ||
716 | * omap_sr_disable() - API to disable SR without resetting the voltage | ||
717 | * processor voltage | ||
718 | * @voltdm: VDD pointer to which the SR module to be configured belongs to. | ||
719 | * | ||
720 | * This API is to be called from the kernel in order to disable | ||
721 | * a particular smartreflex module. This API will in turn call | ||
722 | * into the registered smartreflex class disable API. This API will tell | ||
723 | * the smartreflex class disable not to reset the VP voltage after | ||
724 | * disabling smartreflex. | ||
725 | */ | ||
726 | void omap_sr_disable(struct voltagedomain *voltdm) | ||
727 | { | ||
728 | struct omap_sr *sr = _sr_lookup(voltdm); | ||
729 | |||
730 | if (IS_ERR(sr)) { | ||
731 | pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); | ||
732 | return; | ||
733 | } | ||
734 | |||
735 | if (!sr->autocomp_active) | ||
736 | return; | ||
737 | |||
738 | if (!sr_class || !(sr_class->disable)) { | ||
739 | dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" | ||
740 | "registered\n", __func__); | ||
741 | return; | ||
742 | } | ||
743 | |||
744 | sr_class->disable(sr, 0); | ||
745 | } | ||
746 | |||
747 | /** | ||
748 | * omap_sr_disable_reset_volt() - API to disable SR and reset the | ||
749 | * voltage processor voltage | ||
750 | * @voltdm: VDD pointer to which the SR module to be configured belongs to. | ||
751 | * | ||
752 | * This API is to be called from the kernel in order to disable | ||
753 | * a particular smartreflex module. This API will in turn call | ||
754 | * into the registered smartreflex class disable API. This API will tell | ||
755 | * the smartreflex class disable to reset the VP voltage after | ||
756 | * disabling smartreflex. | ||
757 | */ | ||
758 | void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) | ||
759 | { | ||
760 | struct omap_sr *sr = _sr_lookup(voltdm); | ||
761 | |||
762 | if (IS_ERR(sr)) { | ||
763 | pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); | ||
764 | return; | ||
765 | } | ||
766 | |||
767 | if (!sr->autocomp_active) | ||
768 | return; | ||
769 | |||
770 | if (!sr_class || !(sr_class->disable)) { | ||
771 | dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" | ||
772 | "registered\n", __func__); | ||
773 | return; | ||
774 | } | ||
775 | |||
776 | sr_class->disable(sr, 1); | ||
777 | } | ||
778 | |||
779 | /** | ||
780 | * omap_sr_register_pmic() - API to register pmic specific info. | ||
781 | * @pmic_data: The structure containing pmic specific data. | ||
782 | * | ||
783 | * This API is to be called from the PMIC specific code to register with | ||
784 | * smartreflex driver pmic specific info. Currently the only info required | ||
785 | * is the smartreflex init on the PMIC side. | ||
786 | */ | ||
787 | void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data) | ||
788 | { | ||
789 | if (!pmic_data) { | ||
790 | pr_warning("%s: Trying to register NULL PMIC data structure" | ||
791 | "with smartreflex\n", __func__); | ||
792 | return; | ||
793 | } | ||
794 | |||
795 | sr_pmic_data = pmic_data; | ||
796 | } | ||
797 | |||
798 | /* PM Debug FS entries to enable and disable smartreflex. */ | ||
799 | static int omap_sr_autocomp_show(void *data, u64 *val) | ||
800 | { | ||
801 | struct omap_sr *sr_info = data; | ||
802 | |||
803 | if (!sr_info) { | ||
804 | pr_warning("%s: omap_sr struct not found\n", __func__); | ||
805 | return -EINVAL; | ||
806 | } | ||
807 | |||
808 | *val = sr_info->autocomp_active; | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static int omap_sr_autocomp_store(void *data, u64 val) | ||
814 | { | ||
815 | struct omap_sr *sr_info = data; | ||
816 | |||
817 | if (!sr_info) { | ||
818 | pr_warning("%s: omap_sr struct not found\n", __func__); | ||
819 | return -EINVAL; | ||
820 | } | ||
821 | |||
822 | /* Sanity check */ | ||
823 | if (val > 1) { | ||
824 | pr_warning("%s: Invalid argument %lld\n", __func__, val); | ||
825 | return -EINVAL; | ||
826 | } | ||
827 | |||
828 | /* control enable/disable only if there is a delta in value */ | ||
829 | if (sr_info->autocomp_active != val) { | ||
830 | if (!val) | ||
831 | sr_stop_vddautocomp(sr_info); | ||
832 | else | ||
833 | sr_start_vddautocomp(sr_info); | ||
834 | } | ||
835 | |||
836 | return 0; | ||
837 | } | ||
838 | |||
839 | DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show, | ||
840 | omap_sr_autocomp_store, "%llu\n"); | ||
841 | |||
842 | static int __init omap_sr_probe(struct platform_device *pdev) | ||
843 | { | ||
844 | struct omap_sr *sr_info; | ||
845 | struct omap_sr_data *pdata = pdev->dev.platform_data; | ||
846 | struct resource *mem, *irq; | ||
847 | struct dentry *nvalue_dir; | ||
848 | int i, ret = 0; | ||
849 | |||
850 | sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL); | ||
851 | if (!sr_info) { | ||
852 | dev_err(&pdev->dev, "%s: unable to allocate sr_info\n", | ||
853 | __func__); | ||
854 | return -ENOMEM; | ||
855 | } | ||
856 | |||
857 | platform_set_drvdata(pdev, sr_info); | ||
858 | |||
859 | if (!pdata) { | ||
860 | dev_err(&pdev->dev, "%s: platform data missing\n", __func__); | ||
861 | ret = -EINVAL; | ||
862 | goto err_free_devinfo; | ||
863 | } | ||
864 | |||
865 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
866 | if (!mem) { | ||
867 | dev_err(&pdev->dev, "%s: no mem resource\n", __func__); | ||
868 | ret = -ENODEV; | ||
869 | goto err_free_devinfo; | ||
870 | } | ||
871 | |||
872 | mem = request_mem_region(mem->start, resource_size(mem), | ||
873 | dev_name(&pdev->dev)); | ||
874 | if (!mem) { | ||
875 | dev_err(&pdev->dev, "%s: no mem region\n", __func__); | ||
876 | ret = -EBUSY; | ||
877 | goto err_free_devinfo; | ||
878 | } | ||
879 | |||
880 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
881 | |||
882 | pm_runtime_enable(&pdev->dev); | ||
883 | pm_runtime_irq_safe(&pdev->dev); | ||
884 | |||
885 | sr_info->name = kasprintf(GFP_KERNEL, "%s", pdata->name); | ||
886 | if (!sr_info->name) { | ||
887 | dev_err(&pdev->dev, "%s: Unable to alloc SR instance name\n", | ||
888 | __func__); | ||
889 | ret = -ENOMEM; | ||
890 | goto err_release_region; | ||
891 | } | ||
892 | |||
893 | sr_info->pdev = pdev; | ||
894 | sr_info->srid = pdev->id; | ||
895 | sr_info->voltdm = pdata->voltdm; | ||
896 | sr_info->nvalue_table = pdata->nvalue_table; | ||
897 | sr_info->nvalue_count = pdata->nvalue_count; | ||
898 | sr_info->senn_mod = pdata->senn_mod; | ||
899 | sr_info->senp_mod = pdata->senp_mod; | ||
900 | sr_info->err_weight = pdata->err_weight; | ||
901 | sr_info->err_maxlimit = pdata->err_maxlimit; | ||
902 | sr_info->accum_data = pdata->accum_data; | ||
903 | sr_info->senn_avgweight = pdata->senn_avgweight; | ||
904 | sr_info->senp_avgweight = pdata->senp_avgweight; | ||
905 | sr_info->autocomp_active = false; | ||
906 | sr_info->ip_type = pdata->ip_type; | ||
907 | |||
908 | sr_info->base = ioremap(mem->start, resource_size(mem)); | ||
909 | if (!sr_info->base) { | ||
910 | dev_err(&pdev->dev, "%s: ioremap fail\n", __func__); | ||
911 | ret = -ENOMEM; | ||
912 | goto err_free_name; | ||
913 | } | ||
914 | |||
915 | if (irq) | ||
916 | sr_info->irq = irq->start; | ||
917 | |||
918 | sr_set_clk_length(sr_info); | ||
919 | |||
920 | list_add(&sr_info->node, &sr_list); | ||
921 | |||
922 | /* | ||
923 | * Call into late init to do intializations that require | ||
924 | * both sr driver and sr class driver to be initiallized. | ||
925 | */ | ||
926 | if (sr_class) { | ||
927 | ret = sr_late_init(sr_info); | ||
928 | if (ret) { | ||
929 | pr_warning("%s: Error in SR late init\n", __func__); | ||
930 | goto err_iounmap; | ||
931 | } | ||
932 | } | ||
933 | |||
934 | dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__); | ||
935 | if (!sr_dbg_dir) { | ||
936 | sr_dbg_dir = debugfs_create_dir("smartreflex", NULL); | ||
937 | if (IS_ERR_OR_NULL(sr_dbg_dir)) { | ||
938 | ret = PTR_ERR(sr_dbg_dir); | ||
939 | pr_err("%s:sr debugfs dir creation failed(%d)\n", | ||
940 | __func__, ret); | ||
941 | goto err_iounmap; | ||
942 | } | ||
943 | } | ||
944 | |||
945 | sr_info->dbg_dir = debugfs_create_dir(sr_info->name, sr_dbg_dir); | ||
946 | if (IS_ERR_OR_NULL(sr_info->dbg_dir)) { | ||
947 | dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", | ||
948 | __func__); | ||
949 | ret = PTR_ERR(sr_info->dbg_dir); | ||
950 | goto err_debugfs; | ||
951 | } | ||
952 | |||
953 | (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, | ||
954 | sr_info->dbg_dir, (void *)sr_info, &pm_sr_fops); | ||
955 | (void) debugfs_create_x32("errweight", S_IRUGO, sr_info->dbg_dir, | ||
956 | &sr_info->err_weight); | ||
957 | (void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir, | ||
958 | &sr_info->err_maxlimit); | ||
959 | |||
960 | nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir); | ||
961 | if (IS_ERR_OR_NULL(nvalue_dir)) { | ||
962 | dev_err(&pdev->dev, "%s: Unable to create debugfs directory" | ||
963 | "for n-values\n", __func__); | ||
964 | ret = PTR_ERR(nvalue_dir); | ||
965 | goto err_debugfs; | ||
966 | } | ||
967 | |||
968 | if (sr_info->nvalue_count == 0 || !sr_info->nvalue_table) { | ||
969 | dev_warn(&pdev->dev, "%s: %s: No Voltage table for the corresponding vdd. Cannot create debugfs entries for n-values\n", | ||
970 | __func__, sr_info->name); | ||
971 | |||
972 | ret = -ENODATA; | ||
973 | goto err_debugfs; | ||
974 | } | ||
975 | |||
976 | for (i = 0; i < sr_info->nvalue_count; i++) { | ||
977 | char name[NVALUE_NAME_LEN + 1]; | ||
978 | |||
979 | snprintf(name, sizeof(name), "volt_%lu", | ||
980 | sr_info->nvalue_table[i].volt_nominal); | ||
981 | (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, | ||
982 | &(sr_info->nvalue_table[i].nvalue)); | ||
983 | snprintf(name, sizeof(name), "errminlimit_%lu", | ||
984 | sr_info->nvalue_table[i].volt_nominal); | ||
985 | (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, | ||
986 | &(sr_info->nvalue_table[i].errminlimit)); | ||
987 | |||
988 | } | ||
989 | |||
990 | return ret; | ||
991 | |||
992 | err_debugfs: | ||
993 | debugfs_remove_recursive(sr_info->dbg_dir); | ||
994 | err_iounmap: | ||
995 | list_del(&sr_info->node); | ||
996 | iounmap(sr_info->base); | ||
997 | err_free_name: | ||
998 | kfree(sr_info->name); | ||
999 | err_release_region: | ||
1000 | release_mem_region(mem->start, resource_size(mem)); | ||
1001 | err_free_devinfo: | ||
1002 | kfree(sr_info); | ||
1003 | |||
1004 | return ret; | ||
1005 | } | ||
1006 | |||
1007 | static int omap_sr_remove(struct platform_device *pdev) | ||
1008 | { | ||
1009 | struct omap_sr_data *pdata = pdev->dev.platform_data; | ||
1010 | struct omap_sr *sr_info; | ||
1011 | struct resource *mem; | ||
1012 | |||
1013 | if (!pdata) { | ||
1014 | dev_err(&pdev->dev, "%s: platform data missing\n", __func__); | ||
1015 | return -EINVAL; | ||
1016 | } | ||
1017 | |||
1018 | sr_info = _sr_lookup(pdata->voltdm); | ||
1019 | if (IS_ERR(sr_info)) { | ||
1020 | dev_warn(&pdev->dev, "%s: omap_sr struct not found\n", | ||
1021 | __func__); | ||
1022 | return PTR_ERR(sr_info); | ||
1023 | } | ||
1024 | |||
1025 | if (sr_info->autocomp_active) | ||
1026 | sr_stop_vddautocomp(sr_info); | ||
1027 | if (sr_info->dbg_dir) | ||
1028 | debugfs_remove_recursive(sr_info->dbg_dir); | ||
1029 | |||
1030 | list_del(&sr_info->node); | ||
1031 | iounmap(sr_info->base); | ||
1032 | kfree(sr_info->name); | ||
1033 | kfree(sr_info); | ||
1034 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1035 | release_mem_region(mem->start, resource_size(mem)); | ||
1036 | |||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | static void omap_sr_shutdown(struct platform_device *pdev) | ||
1041 | { | ||
1042 | struct omap_sr_data *pdata = pdev->dev.platform_data; | ||
1043 | struct omap_sr *sr_info; | ||
1044 | |||
1045 | if (!pdata) { | ||
1046 | dev_err(&pdev->dev, "%s: platform data missing\n", __func__); | ||
1047 | return; | ||
1048 | } | ||
1049 | |||
1050 | sr_info = _sr_lookup(pdata->voltdm); | ||
1051 | if (IS_ERR(sr_info)) { | ||
1052 | dev_warn(&pdev->dev, "%s: omap_sr struct not found\n", | ||
1053 | __func__); | ||
1054 | return; | ||
1055 | } | ||
1056 | |||
1057 | if (sr_info->autocomp_active) | ||
1058 | sr_stop_vddautocomp(sr_info); | ||
1059 | |||
1060 | return; | ||
1061 | } | ||
1062 | |||
1063 | static struct platform_driver smartreflex_driver = { | ||
1064 | .remove = omap_sr_remove, | ||
1065 | .shutdown = omap_sr_shutdown, | ||
1066 | .driver = { | ||
1067 | .name = "smartreflex", | ||
1068 | }, | ||
1069 | }; | ||
1070 | |||
1071 | static int __init sr_init(void) | ||
1072 | { | ||
1073 | int ret = 0; | ||
1074 | |||
1075 | /* | ||
1076 | * sr_init is a late init. If by then a pmic specific API is not | ||
1077 | * registered either there is no need for anything to be done on | ||
1078 | * the PMIC side or somebody has forgotten to register a PMIC | ||
1079 | * handler. Warn for the second condition. | ||
1080 | */ | ||
1081 | if (sr_pmic_data && sr_pmic_data->sr_pmic_init) | ||
1082 | sr_pmic_data->sr_pmic_init(); | ||
1083 | else | ||
1084 | pr_warning("%s: No PMIC hook to init smartreflex\n", __func__); | ||
1085 | |||
1086 | ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe); | ||
1087 | if (ret) { | ||
1088 | pr_err("%s: platform driver register failed for SR\n", | ||
1089 | __func__); | ||
1090 | return ret; | ||
1091 | } | ||
1092 | |||
1093 | return 0; | ||
1094 | } | ||
1095 | late_initcall(sr_init); | ||
1096 | |||
1097 | static void __exit sr_exit(void) | ||
1098 | { | ||
1099 | platform_driver_unregister(&smartreflex_driver); | ||
1100 | } | ||
1101 | module_exit(sr_exit); | ||
1102 | |||
1103 | MODULE_DESCRIPTION("OMAP Smartreflex Driver"); | ||
1104 | MODULE_LICENSE("GPL"); | ||
1105 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
1106 | MODULE_AUTHOR("Texas Instruments Inc"); | ||
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c deleted file mode 100644 index ee842b37f46..00000000000 --- a/drivers/power/bq2415x_charger.c +++ /dev/null | |||
@@ -1,1670 +0,0 @@ | |||
1 | /* | ||
2 | * bq2415x charger driver | ||
3 | * | ||
4 | * Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * Datasheets: | ||
23 | * http://www.ti.com/product/bq24150 | ||
24 | * http://www.ti.com/product/bq24150a | ||
25 | * http://www.ti.com/product/bq24152 | ||
26 | * http://www.ti.com/product/bq24153 | ||
27 | * http://www.ti.com/product/bq24153a | ||
28 | * http://www.ti.com/product/bq24155 | ||
29 | */ | ||
30 | |||
31 | #include <linux/version.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/param.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/workqueue.h> | ||
37 | #include <linux/sysfs.h> | ||
38 | #include <linux/platform_device.h> | ||
39 | #include <linux/power_supply.h> | ||
40 | #include <linux/idr.h> | ||
41 | #include <linux/i2c.h> | ||
42 | #include <linux/slab.h> | ||
43 | |||
44 | #include <linux/power/bq2415x_charger.h> | ||
45 | |||
46 | /* timeout for resetting chip timer */ | ||
47 | #define BQ2415X_TIMER_TIMEOUT 10 | ||
48 | |||
49 | #define BQ2415X_REG_STATUS 0x00 | ||
50 | #define BQ2415X_REG_CONTROL 0x01 | ||
51 | #define BQ2415X_REG_VOLTAGE 0x02 | ||
52 | #define BQ2415X_REG_VENDER 0x03 | ||
53 | #define BQ2415X_REG_CURRENT 0x04 | ||
54 | |||
55 | /* reset state for all registers */ | ||
56 | #define BQ2415X_RESET_STATUS BIT(6) | ||
57 | #define BQ2415X_RESET_CONTROL (BIT(4)|BIT(5)) | ||
58 | #define BQ2415X_RESET_VOLTAGE (BIT(1)|BIT(3)) | ||
59 | #define BQ2415X_RESET_CURRENT (BIT(0)|BIT(3)|BIT(7)) | ||
60 | |||
61 | /* status register */ | ||
62 | #define BQ2415X_BIT_TMR_RST 7 | ||
63 | #define BQ2415X_BIT_OTG 7 | ||
64 | #define BQ2415X_BIT_EN_STAT 6 | ||
65 | #define BQ2415X_MASK_STAT (BIT(4)|BIT(5)) | ||
66 | #define BQ2415X_SHIFT_STAT 4 | ||
67 | #define BQ2415X_BIT_BOOST 3 | ||
68 | #define BQ2415X_MASK_FAULT (BIT(0)|BIT(1)|BIT(2)) | ||
69 | #define BQ2415X_SHIFT_FAULT 0 | ||
70 | |||
71 | /* control register */ | ||
72 | #define BQ2415X_MASK_LIMIT (BIT(6)|BIT(7)) | ||
73 | #define BQ2415X_SHIFT_LIMIT 6 | ||
74 | #define BQ2415X_MASK_VLOWV (BIT(4)|BIT(5)) | ||
75 | #define BQ2415X_SHIFT_VLOWV 4 | ||
76 | #define BQ2415X_BIT_TE 3 | ||
77 | #define BQ2415X_BIT_CE 2 | ||
78 | #define BQ2415X_BIT_HZ_MODE 1 | ||
79 | #define BQ2415X_BIT_OPA_MODE 0 | ||
80 | |||
81 | /* voltage register */ | ||
82 | #define BQ2415X_MASK_VO (BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)) | ||
83 | #define BQ2415X_SHIFT_VO 2 | ||
84 | #define BQ2415X_BIT_OTG_PL 1 | ||
85 | #define BQ2415X_BIT_OTG_EN 0 | ||
86 | |||
87 | /* vender register */ | ||
88 | #define BQ2415X_MASK_VENDER (BIT(5)|BIT(6)|BIT(7)) | ||
89 | #define BQ2415X_SHIFT_VENDER 5 | ||
90 | #define BQ2415X_MASK_PN (BIT(3)|BIT(4)) | ||
91 | #define BQ2415X_SHIFT_PN 3 | ||
92 | #define BQ2415X_MASK_REVISION (BIT(0)|BIT(1)|BIT(2)) | ||
93 | #define BQ2415X_SHIFT_REVISION 0 | ||
94 | |||
95 | /* current register */ | ||
96 | #define BQ2415X_MASK_RESET BIT(7) | ||
97 | #define BQ2415X_MASK_VI_CHRG (BIT(4)|BIT(5)|BIT(6)) | ||
98 | #define BQ2415X_SHIFT_VI_CHRG 4 | ||
99 | /* N/A BIT(3) */ | ||
100 | #define BQ2415X_MASK_VI_TERM (BIT(0)|BIT(1)|BIT(2)) | ||
101 | #define BQ2415X_SHIFT_VI_TERM 0 | ||
102 | |||
103 | |||
104 | enum bq2415x_command { | ||
105 | BQ2415X_TIMER_RESET, | ||
106 | BQ2415X_OTG_STATUS, | ||
107 | BQ2415X_STAT_PIN_STATUS, | ||
108 | BQ2415X_STAT_PIN_ENABLE, | ||
109 | BQ2415X_STAT_PIN_DISABLE, | ||
110 | BQ2415X_CHARGE_STATUS, | ||
111 | BQ2415X_BOOST_STATUS, | ||
112 | BQ2415X_FAULT_STATUS, | ||
113 | |||
114 | BQ2415X_CHARGE_TERMINATION_STATUS, | ||
115 | BQ2415X_CHARGE_TERMINATION_ENABLE, | ||
116 | BQ2415X_CHARGE_TERMINATION_DISABLE, | ||
117 | BQ2415X_CHARGER_STATUS, | ||
118 | BQ2415X_CHARGER_ENABLE, | ||
119 | BQ2415X_CHARGER_DISABLE, | ||
120 | BQ2415X_HIGH_IMPEDANCE_STATUS, | ||
121 | BQ2415X_HIGH_IMPEDANCE_ENABLE, | ||
122 | BQ2415X_HIGH_IMPEDANCE_DISABLE, | ||
123 | BQ2415X_BOOST_MODE_STATUS, | ||
124 | BQ2415X_BOOST_MODE_ENABLE, | ||
125 | BQ2415X_BOOST_MODE_DISABLE, | ||
126 | |||
127 | BQ2415X_OTG_LEVEL, | ||
128 | BQ2415X_OTG_ACTIVATE_HIGH, | ||
129 | BQ2415X_OTG_ACTIVATE_LOW, | ||
130 | BQ2415X_OTG_PIN_STATUS, | ||
131 | BQ2415X_OTG_PIN_ENABLE, | ||
132 | BQ2415X_OTG_PIN_DISABLE, | ||
133 | |||
134 | BQ2415X_VENDER_CODE, | ||
135 | BQ2415X_PART_NUMBER, | ||
136 | BQ2415X_REVISION, | ||
137 | }; | ||
138 | |||
139 | enum bq2415x_chip { | ||
140 | BQUNKNOWN, | ||
141 | BQ24150, | ||
142 | BQ24150A, | ||
143 | BQ24151, | ||
144 | BQ24151A, | ||
145 | BQ24152, | ||
146 | BQ24153, | ||
147 | BQ24153A, | ||
148 | BQ24155, | ||
149 | BQ24156, | ||
150 | BQ24156A, | ||
151 | BQ24158, | ||
152 | }; | ||
153 | |||
154 | static char *bq2415x_chip_name[] = { | ||
155 | "unknown", | ||
156 | "bq24150", | ||
157 | "bq24150a", | ||
158 | "bq24151", | ||
159 | "bq24151a", | ||
160 | "bq24152", | ||
161 | "bq24153", | ||
162 | "bq24153a", | ||
163 | "bq24155", | ||
164 | "bq24156", | ||
165 | "bq24156a", | ||
166 | "bq24158", | ||
167 | }; | ||
168 | |||
169 | struct bq2415x_device { | ||
170 | struct device *dev; | ||
171 | struct bq2415x_platform_data init_data; | ||
172 | struct power_supply charger; | ||
173 | struct delayed_work work; | ||
174 | enum bq2415x_mode reported_mode;/* mode reported by hook function */ | ||
175 | enum bq2415x_mode mode; /* current configured mode */ | ||
176 | enum bq2415x_chip chip; | ||
177 | const char *timer_error; | ||
178 | char *model; | ||
179 | char *name; | ||
180 | int autotimer; /* 1 - if driver automatically reset timer, 0 - not */ | ||
181 | int automode; /* 1 - enabled, 0 - disabled; -1 - not supported */ | ||
182 | int id; | ||
183 | }; | ||
184 | |||
185 | /* each registered chip must have unique id */ | ||
186 | static DEFINE_IDR(bq2415x_id); | ||
187 | |||
188 | static DEFINE_MUTEX(bq2415x_id_mutex); | ||
189 | static DEFINE_MUTEX(bq2415x_timer_mutex); | ||
190 | static DEFINE_MUTEX(bq2415x_i2c_mutex); | ||
191 | |||
192 | /**** i2c read functions ****/ | ||
193 | |||
194 | /* read value from register */ | ||
195 | static int bq2415x_i2c_read(struct bq2415x_device *bq, u8 reg) | ||
196 | { | ||
197 | struct i2c_client *client = to_i2c_client(bq->dev); | ||
198 | struct i2c_msg msg[2]; | ||
199 | u8 val; | ||
200 | int ret; | ||
201 | |||
202 | if (!client->adapter) | ||
203 | return -ENODEV; | ||
204 | |||
205 | msg[0].addr = client->addr; | ||
206 | msg[0].flags = 0; | ||
207 | msg[0].buf = ® | ||
208 | msg[0].len = sizeof(reg); | ||
209 | msg[1].addr = client->addr; | ||
210 | msg[1].flags = I2C_M_RD; | ||
211 | msg[1].buf = &val; | ||
212 | msg[1].len = sizeof(val); | ||
213 | |||
214 | mutex_lock(&bq2415x_i2c_mutex); | ||
215 | ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); | ||
216 | mutex_unlock(&bq2415x_i2c_mutex); | ||
217 | |||
218 | if (ret < 0) | ||
219 | return ret; | ||
220 | |||
221 | return val; | ||
222 | } | ||
223 | |||
224 | /* read value from register, apply mask and right shift it */ | ||
225 | static int bq2415x_i2c_read_mask(struct bq2415x_device *bq, u8 reg, | ||
226 | u8 mask, u8 shift) | ||
227 | { | ||
228 | int ret; | ||
229 | |||
230 | if (shift > 8) | ||
231 | return -EINVAL; | ||
232 | |||
233 | ret = bq2415x_i2c_read(bq, reg); | ||
234 | if (ret < 0) | ||
235 | return ret; | ||
236 | return (ret & mask) >> shift; | ||
237 | } | ||
238 | |||
239 | /* read value from register and return one specified bit */ | ||
240 | static int bq2415x_i2c_read_bit(struct bq2415x_device *bq, u8 reg, u8 bit) | ||
241 | { | ||
242 | if (bit > 8) | ||
243 | return -EINVAL; | ||
244 | return bq2415x_i2c_read_mask(bq, reg, BIT(bit), bit); | ||
245 | } | ||
246 | |||
247 | /**** i2c write functions ****/ | ||
248 | |||
249 | /* write value to register */ | ||
250 | static int bq2415x_i2c_write(struct bq2415x_device *bq, u8 reg, u8 val) | ||
251 | { | ||
252 | struct i2c_client *client = to_i2c_client(bq->dev); | ||
253 | struct i2c_msg msg[1]; | ||
254 | u8 data[2]; | ||
255 | int ret; | ||
256 | |||
257 | data[0] = reg; | ||
258 | data[1] = val; | ||
259 | |||
260 | msg[0].addr = client->addr; | ||
261 | msg[0].flags = 0; | ||
262 | msg[0].buf = data; | ||
263 | msg[0].len = ARRAY_SIZE(data); | ||
264 | |||
265 | mutex_lock(&bq2415x_i2c_mutex); | ||
266 | ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); | ||
267 | mutex_unlock(&bq2415x_i2c_mutex); | ||
268 | |||
269 | /* i2c_transfer returns number of messages transferred */ | ||
270 | if (ret < 0) | ||
271 | return ret; | ||
272 | else if (ret != 1) | ||
273 | return -EIO; | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /* read value from register, change it with mask left shifted and write back */ | ||
279 | static int bq2415x_i2c_write_mask(struct bq2415x_device *bq, u8 reg, u8 val, | ||
280 | u8 mask, u8 shift) | ||
281 | { | ||
282 | int ret; | ||
283 | |||
284 | if (shift > 8) | ||
285 | return -EINVAL; | ||
286 | |||
287 | ret = bq2415x_i2c_read(bq, reg); | ||
288 | if (ret < 0) | ||
289 | return ret; | ||
290 | |||
291 | ret &= ~mask; | ||
292 | ret |= val << shift; | ||
293 | |||
294 | return bq2415x_i2c_write(bq, reg, ret); | ||
295 | } | ||
296 | |||
297 | /* change only one bit in register */ | ||
298 | static int bq2415x_i2c_write_bit(struct bq2415x_device *bq, u8 reg, | ||
299 | bool val, u8 bit) | ||
300 | { | ||
301 | if (bit > 8) | ||
302 | return -EINVAL; | ||
303 | return bq2415x_i2c_write_mask(bq, reg, val, BIT(bit), bit); | ||
304 | } | ||
305 | |||
306 | /**** global functions ****/ | ||
307 | |||
308 | /* exec command function */ | ||
309 | static int bq2415x_exec_command(struct bq2415x_device *bq, | ||
310 | enum bq2415x_command command) | ||
311 | { | ||
312 | int ret; | ||
313 | |||
314 | switch (command) { | ||
315 | case BQ2415X_TIMER_RESET: | ||
316 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, | ||
317 | 1, BQ2415X_BIT_TMR_RST); | ||
318 | case BQ2415X_OTG_STATUS: | ||
319 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS, | ||
320 | BQ2415X_BIT_OTG); | ||
321 | case BQ2415X_STAT_PIN_STATUS: | ||
322 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS, | ||
323 | BQ2415X_BIT_EN_STAT); | ||
324 | case BQ2415X_STAT_PIN_ENABLE: | ||
325 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 1, | ||
326 | BQ2415X_BIT_EN_STAT); | ||
327 | case BQ2415X_STAT_PIN_DISABLE: | ||
328 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 0, | ||
329 | BQ2415X_BIT_EN_STAT); | ||
330 | case BQ2415X_CHARGE_STATUS: | ||
331 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS, | ||
332 | BQ2415X_MASK_STAT, BQ2415X_SHIFT_STAT); | ||
333 | case BQ2415X_BOOST_STATUS: | ||
334 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS, | ||
335 | BQ2415X_BIT_BOOST); | ||
336 | case BQ2415X_FAULT_STATUS: | ||
337 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS, | ||
338 | BQ2415X_MASK_FAULT, BQ2415X_SHIFT_FAULT); | ||
339 | |||
340 | case BQ2415X_CHARGE_TERMINATION_STATUS: | ||
341 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL, | ||
342 | BQ2415X_BIT_TE); | ||
343 | case BQ2415X_CHARGE_TERMINATION_ENABLE: | ||
344 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
345 | 1, BQ2415X_BIT_TE); | ||
346 | case BQ2415X_CHARGE_TERMINATION_DISABLE: | ||
347 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
348 | 0, BQ2415X_BIT_TE); | ||
349 | case BQ2415X_CHARGER_STATUS: | ||
350 | ret = bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL, | ||
351 | BQ2415X_BIT_CE); | ||
352 | if (ret < 0) | ||
353 | return ret; | ||
354 | else | ||
355 | return ret > 0 ? 0 : 1; | ||
356 | case BQ2415X_CHARGER_ENABLE: | ||
357 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
358 | 0, BQ2415X_BIT_CE); | ||
359 | case BQ2415X_CHARGER_DISABLE: | ||
360 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
361 | 1, BQ2415X_BIT_CE); | ||
362 | case BQ2415X_HIGH_IMPEDANCE_STATUS: | ||
363 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL, | ||
364 | BQ2415X_BIT_HZ_MODE); | ||
365 | case BQ2415X_HIGH_IMPEDANCE_ENABLE: | ||
366 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
367 | 1, BQ2415X_BIT_HZ_MODE); | ||
368 | case BQ2415X_HIGH_IMPEDANCE_DISABLE: | ||
369 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
370 | 0, BQ2415X_BIT_HZ_MODE); | ||
371 | case BQ2415X_BOOST_MODE_STATUS: | ||
372 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL, | ||
373 | BQ2415X_BIT_OPA_MODE); | ||
374 | case BQ2415X_BOOST_MODE_ENABLE: | ||
375 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
376 | 1, BQ2415X_BIT_OPA_MODE); | ||
377 | case BQ2415X_BOOST_MODE_DISABLE: | ||
378 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
379 | 0, BQ2415X_BIT_OPA_MODE); | ||
380 | |||
381 | case BQ2415X_OTG_LEVEL: | ||
382 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE, | ||
383 | BQ2415X_BIT_OTG_PL); | ||
384 | case BQ2415X_OTG_ACTIVATE_HIGH: | ||
385 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE, | ||
386 | 1, BQ2415X_BIT_OTG_PL); | ||
387 | case BQ2415X_OTG_ACTIVATE_LOW: | ||
388 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE, | ||
389 | 0, BQ2415X_BIT_OTG_PL); | ||
390 | case BQ2415X_OTG_PIN_STATUS: | ||
391 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE, | ||
392 | BQ2415X_BIT_OTG_EN); | ||
393 | case BQ2415X_OTG_PIN_ENABLE: | ||
394 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE, | ||
395 | 1, BQ2415X_BIT_OTG_EN); | ||
396 | case BQ2415X_OTG_PIN_DISABLE: | ||
397 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE, | ||
398 | 0, BQ2415X_BIT_OTG_EN); | ||
399 | |||
400 | case BQ2415X_VENDER_CODE: | ||
401 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER, | ||
402 | BQ2415X_MASK_VENDER, BQ2415X_SHIFT_VENDER); | ||
403 | case BQ2415X_PART_NUMBER: | ||
404 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER, | ||
405 | BQ2415X_MASK_PN, BQ2415X_SHIFT_PN); | ||
406 | case BQ2415X_REVISION: | ||
407 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER, | ||
408 | BQ2415X_MASK_REVISION, BQ2415X_SHIFT_REVISION); | ||
409 | } | ||
410 | return -EINVAL; | ||
411 | } | ||
412 | |||
413 | /* detect chip type */ | ||
414 | static enum bq2415x_chip bq2415x_detect_chip(struct bq2415x_device *bq) | ||
415 | { | ||
416 | struct i2c_client *client = to_i2c_client(bq->dev); | ||
417 | int ret = bq2415x_exec_command(bq, BQ2415X_PART_NUMBER); | ||
418 | |||
419 | if (ret < 0) | ||
420 | return ret; | ||
421 | |||
422 | switch (client->addr) { | ||
423 | case 0x6b: | ||
424 | switch (ret) { | ||
425 | case 0: | ||
426 | if (bq->chip == BQ24151A) | ||
427 | return bq->chip; | ||
428 | else | ||
429 | return BQ24151; | ||
430 | case 1: | ||
431 | if (bq->chip == BQ24150A || | ||
432 | bq->chip == BQ24152 || | ||
433 | bq->chip == BQ24155) | ||
434 | return bq->chip; | ||
435 | else | ||
436 | return BQ24150; | ||
437 | case 2: | ||
438 | if (bq->chip == BQ24153A) | ||
439 | return bq->chip; | ||
440 | else | ||
441 | return BQ24153; | ||
442 | default: | ||
443 | return BQUNKNOWN; | ||
444 | } | ||
445 | break; | ||
446 | |||
447 | case 0x6a: | ||
448 | switch (ret) { | ||
449 | case 0: | ||
450 | if (bq->chip == BQ24156A) | ||
451 | return bq->chip; | ||
452 | else | ||
453 | return BQ24156; | ||
454 | case 2: | ||
455 | return BQ24158; | ||
456 | default: | ||
457 | return BQUNKNOWN; | ||
458 | } | ||
459 | break; | ||
460 | } | ||
461 | |||
462 | return BQUNKNOWN; | ||
463 | } | ||
464 | |||
465 | /* detect chip revision */ | ||
466 | static int bq2415x_detect_revision(struct bq2415x_device *bq) | ||
467 | { | ||
468 | int ret = bq2415x_exec_command(bq, BQ2415X_REVISION); | ||
469 | int chip = bq2415x_detect_chip(bq); | ||
470 | |||
471 | if (ret < 0 || chip < 0) | ||
472 | return -1; | ||
473 | |||
474 | switch (chip) { | ||
475 | case BQ24150: | ||
476 | case BQ24150A: | ||
477 | case BQ24151: | ||
478 | case BQ24151A: | ||
479 | case BQ24152: | ||
480 | if (ret >= 0 && ret <= 3) | ||
481 | return ret; | ||
482 | else | ||
483 | return -1; | ||
484 | case BQ24153: | ||
485 | case BQ24153A: | ||
486 | case BQ24156: | ||
487 | case BQ24156A: | ||
488 | case BQ24158: | ||
489 | if (ret == 3) | ||
490 | return 0; | ||
491 | else if (ret == 1) | ||
492 | return 1; | ||
493 | else | ||
494 | return -1; | ||
495 | case BQ24155: | ||
496 | if (ret == 3) | ||
497 | return 3; | ||
498 | else | ||
499 | return -1; | ||
500 | case BQUNKNOWN: | ||
501 | return -1; | ||
502 | } | ||
503 | |||
504 | return -1; | ||
505 | } | ||
506 | |||
507 | /* return chip vender code */ | ||
508 | static int bq2415x_get_vender_code(struct bq2415x_device *bq) | ||
509 | { | ||
510 | int ret; | ||
511 | |||
512 | ret = bq2415x_exec_command(bq, BQ2415X_VENDER_CODE); | ||
513 | if (ret < 0) | ||
514 | return 0; | ||
515 | |||
516 | /* convert to binary */ | ||
517 | return (ret & 0x1) + | ||
518 | ((ret >> 1) & 0x1) * 10 + | ||
519 | ((ret >> 2) & 0x1) * 100; | ||
520 | } | ||
521 | |||
522 | /* reset all chip registers to default state */ | ||
523 | static void bq2415x_reset_chip(struct bq2415x_device *bq) | ||
524 | { | ||
525 | bq2415x_i2c_write(bq, BQ2415X_REG_CURRENT, BQ2415X_RESET_CURRENT); | ||
526 | bq2415x_i2c_write(bq, BQ2415X_REG_VOLTAGE, BQ2415X_RESET_VOLTAGE); | ||
527 | bq2415x_i2c_write(bq, BQ2415X_REG_CONTROL, BQ2415X_RESET_CONTROL); | ||
528 | bq2415x_i2c_write(bq, BQ2415X_REG_STATUS, BQ2415X_RESET_STATUS); | ||
529 | bq->timer_error = NULL; | ||
530 | } | ||
531 | |||
532 | /**** properties functions ****/ | ||
533 | |||
534 | /* set current limit in mA */ | ||
535 | static int bq2415x_set_current_limit(struct bq2415x_device *bq, int mA) | ||
536 | { | ||
537 | int val; | ||
538 | |||
539 | if (mA <= 100) | ||
540 | val = 0; | ||
541 | else if (mA <= 500) | ||
542 | val = 1; | ||
543 | else if (mA <= 800) | ||
544 | val = 2; | ||
545 | else | ||
546 | val = 3; | ||
547 | |||
548 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val, | ||
549 | BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT); | ||
550 | } | ||
551 | |||
552 | /* get current limit in mA */ | ||
553 | static int bq2415x_get_current_limit(struct bq2415x_device *bq) | ||
554 | { | ||
555 | int ret; | ||
556 | |||
557 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL, | ||
558 | BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT); | ||
559 | if (ret < 0) | ||
560 | return ret; | ||
561 | else if (ret == 0) | ||
562 | return 100; | ||
563 | else if (ret == 1) | ||
564 | return 500; | ||
565 | else if (ret == 2) | ||
566 | return 800; | ||
567 | else if (ret == 3) | ||
568 | return 1800; | ||
569 | return -EINVAL; | ||
570 | } | ||
571 | |||
572 | /* set weak battery voltage in mV */ | ||
573 | static int bq2415x_set_weak_battery_voltage(struct bq2415x_device *bq, int mV) | ||
574 | { | ||
575 | int val; | ||
576 | |||
577 | /* round to 100mV */ | ||
578 | if (mV <= 3400 + 50) | ||
579 | val = 0; | ||
580 | else if (mV <= 3500 + 50) | ||
581 | val = 1; | ||
582 | else if (mV <= 3600 + 50) | ||
583 | val = 2; | ||
584 | else | ||
585 | val = 3; | ||
586 | |||
587 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val, | ||
588 | BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV); | ||
589 | } | ||
590 | |||
591 | /* get weak battery voltage in mV */ | ||
592 | static int bq2415x_get_weak_battery_voltage(struct bq2415x_device *bq) | ||
593 | { | ||
594 | int ret; | ||
595 | |||
596 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL, | ||
597 | BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV); | ||
598 | if (ret < 0) | ||
599 | return ret; | ||
600 | return 100 * (34 + ret); | ||
601 | } | ||
602 | |||
603 | /* set battery regulation voltage in mV */ | ||
604 | static int bq2415x_set_battery_regulation_voltage(struct bq2415x_device *bq, | ||
605 | int mV) | ||
606 | { | ||
607 | int val = (mV/10 - 350) / 2; | ||
608 | |||
609 | if (val < 0) | ||
610 | val = 0; | ||
611 | else if (val > 94) /* FIXME: Max is 94 or 122 ? Set max value ? */ | ||
612 | return -EINVAL; | ||
613 | |||
614 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_VOLTAGE, val, | ||
615 | BQ2415X_MASK_VO, BQ2415X_SHIFT_VO); | ||
616 | } | ||
617 | |||
618 | /* get battery regulation voltage in mV */ | ||
619 | static int bq2415x_get_battery_regulation_voltage(struct bq2415x_device *bq) | ||
620 | { | ||
621 | int ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_VOLTAGE, | ||
622 | BQ2415X_MASK_VO, BQ2415X_SHIFT_VO); | ||
623 | |||
624 | if (ret < 0) | ||
625 | return ret; | ||
626 | return 10 * (350 + 2*ret); | ||
627 | } | ||
628 | |||
629 | /* set charge current in mA (platform data must provide resistor sense) */ | ||
630 | static int bq2415x_set_charge_current(struct bq2415x_device *bq, int mA) | ||
631 | { | ||
632 | int val; | ||
633 | |||
634 | if (bq->init_data.resistor_sense <= 0) | ||
635 | return -ENOSYS; | ||
636 | |||
637 | val = (mA * bq->init_data.resistor_sense - 37400) / 6800; | ||
638 | if (val < 0) | ||
639 | val = 0; | ||
640 | else if (val > 7) | ||
641 | val = 7; | ||
642 | |||
643 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val, | ||
644 | BQ2415X_MASK_VI_CHRG | BQ2415X_MASK_RESET, | ||
645 | BQ2415X_SHIFT_VI_CHRG); | ||
646 | } | ||
647 | |||
648 | /* get charge current in mA (platform data must provide resistor sense) */ | ||
649 | static int bq2415x_get_charge_current(struct bq2415x_device *bq) | ||
650 | { | ||
651 | int ret; | ||
652 | |||
653 | if (bq->init_data.resistor_sense <= 0) | ||
654 | return -ENOSYS; | ||
655 | |||
656 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT, | ||
657 | BQ2415X_MASK_VI_CHRG, BQ2415X_SHIFT_VI_CHRG); | ||
658 | if (ret < 0) | ||
659 | return ret; | ||
660 | return (37400 + 6800*ret) / bq->init_data.resistor_sense; | ||
661 | } | ||
662 | |||
663 | /* set termination current in mA (platform data must provide resistor sense) */ | ||
664 | static int bq2415x_set_termination_current(struct bq2415x_device *bq, int mA) | ||
665 | { | ||
666 | int val; | ||
667 | |||
668 | if (bq->init_data.resistor_sense <= 0) | ||
669 | return -ENOSYS; | ||
670 | |||
671 | val = (mA * bq->init_data.resistor_sense - 3400) / 3400; | ||
672 | if (val < 0) | ||
673 | val = 0; | ||
674 | else if (val > 7) | ||
675 | val = 7; | ||
676 | |||
677 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val, | ||
678 | BQ2415X_MASK_VI_TERM | BQ2415X_MASK_RESET, | ||
679 | BQ2415X_SHIFT_VI_TERM); | ||
680 | } | ||
681 | |||
682 | /* get termination current in mA (platform data must provide resistor sense) */ | ||
683 | static int bq2415x_get_termination_current(struct bq2415x_device *bq) | ||
684 | { | ||
685 | int ret; | ||
686 | |||
687 | if (bq->init_data.resistor_sense <= 0) | ||
688 | return -ENOSYS; | ||
689 | |||
690 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT, | ||
691 | BQ2415X_MASK_VI_TERM, BQ2415X_SHIFT_VI_TERM); | ||
692 | if (ret < 0) | ||
693 | return ret; | ||
694 | return (3400 + 3400*ret) / bq->init_data.resistor_sense; | ||
695 | } | ||
696 | |||
697 | /* set default value of property */ | ||
698 | #define bq2415x_set_default_value(bq, prop) \ | ||
699 | do { \ | ||
700 | int ret = 0; \ | ||
701 | if (bq->init_data.prop != -1) \ | ||
702 | ret = bq2415x_set_##prop(bq, bq->init_data.prop); \ | ||
703 | if (ret < 0) \ | ||
704 | return ret; \ | ||
705 | } while (0) | ||
706 | |||
707 | /* set default values of all properties */ | ||
708 | static int bq2415x_set_defaults(struct bq2415x_device *bq) | ||
709 | { | ||
710 | bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE); | ||
711 | bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE); | ||
712 | bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_DISABLE); | ||
713 | |||
714 | bq2415x_set_default_value(bq, current_limit); | ||
715 | bq2415x_set_default_value(bq, weak_battery_voltage); | ||
716 | bq2415x_set_default_value(bq, battery_regulation_voltage); | ||
717 | |||
718 | if (bq->init_data.resistor_sense > 0) { | ||
719 | bq2415x_set_default_value(bq, charge_current); | ||
720 | bq2415x_set_default_value(bq, termination_current); | ||
721 | bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_ENABLE); | ||
722 | } | ||
723 | |||
724 | bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE); | ||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | /**** charger mode functions ****/ | ||
729 | |||
730 | /* set charger mode */ | ||
731 | static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode) | ||
732 | { | ||
733 | int ret = 0; | ||
734 | int charger = 0; | ||
735 | int boost = 0; | ||
736 | |||
737 | if (mode == BQ2415X_MODE_HOST_CHARGER || | ||
738 | mode == BQ2415X_MODE_DEDICATED_CHARGER) | ||
739 | charger = 1; | ||
740 | |||
741 | if (mode == BQ2415X_MODE_BOOST) | ||
742 | boost = 1; | ||
743 | |||
744 | if (!charger) | ||
745 | ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE); | ||
746 | |||
747 | if (!boost) | ||
748 | ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE); | ||
749 | |||
750 | if (ret < 0) | ||
751 | return ret; | ||
752 | |||
753 | switch (mode) { | ||
754 | case BQ2415X_MODE_NONE: | ||
755 | dev_dbg(bq->dev, "changing mode to: N/A\n"); | ||
756 | ret = bq2415x_set_current_limit(bq, 100); | ||
757 | break; | ||
758 | case BQ2415X_MODE_HOST_CHARGER: | ||
759 | dev_dbg(bq->dev, "changing mode to: Host/HUB charger\n"); | ||
760 | ret = bq2415x_set_current_limit(bq, 500); | ||
761 | break; | ||
762 | case BQ2415X_MODE_DEDICATED_CHARGER: | ||
763 | dev_dbg(bq->dev, "changing mode to: Dedicated charger\n"); | ||
764 | ret = bq2415x_set_current_limit(bq, 1800); | ||
765 | break; | ||
766 | case BQ2415X_MODE_BOOST: /* Boost mode */ | ||
767 | dev_dbg(bq->dev, "changing mode to: Boost\n"); | ||
768 | ret = bq2415x_set_current_limit(bq, 100); | ||
769 | break; | ||
770 | } | ||
771 | |||
772 | if (ret < 0) | ||
773 | return ret; | ||
774 | |||
775 | if (charger) | ||
776 | ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE); | ||
777 | else if (boost) | ||
778 | ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_ENABLE); | ||
779 | |||
780 | if (ret < 0) | ||
781 | return ret; | ||
782 | |||
783 | bq2415x_set_default_value(bq, weak_battery_voltage); | ||
784 | bq2415x_set_default_value(bq, battery_regulation_voltage); | ||
785 | |||
786 | bq->mode = mode; | ||
787 | sysfs_notify(&bq->charger.dev->kobj, NULL, "mode"); | ||
788 | |||
789 | return 0; | ||
790 | |||
791 | } | ||
792 | |||
793 | /* hook function called by other driver which set reported mode */ | ||
794 | static void bq2415x_hook_function(enum bq2415x_mode mode, void *data) | ||
795 | { | ||
796 | struct bq2415x_device *bq = data; | ||
797 | |||
798 | if (!bq) | ||
799 | return; | ||
800 | |||
801 | dev_dbg(bq->dev, "hook function was called\n"); | ||
802 | bq->reported_mode = mode; | ||
803 | |||
804 | /* if automode is not enabled do not tell about reported_mode */ | ||
805 | if (bq->automode < 1) | ||
806 | return; | ||
807 | |||
808 | sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode"); | ||
809 | bq2415x_set_mode(bq, bq->reported_mode); | ||
810 | |||
811 | } | ||
812 | |||
813 | /**** timer functions ****/ | ||
814 | |||
815 | /* enable/disable auto resetting chip timer */ | ||
816 | static void bq2415x_set_autotimer(struct bq2415x_device *bq, int state) | ||
817 | { | ||
818 | mutex_lock(&bq2415x_timer_mutex); | ||
819 | |||
820 | if (bq->autotimer == state) { | ||
821 | mutex_unlock(&bq2415x_timer_mutex); | ||
822 | return; | ||
823 | } | ||
824 | |||
825 | bq->autotimer = state; | ||
826 | |||
827 | if (state) { | ||
828 | schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ); | ||
829 | bq2415x_exec_command(bq, BQ2415X_TIMER_RESET); | ||
830 | bq->timer_error = NULL; | ||
831 | } else { | ||
832 | cancel_delayed_work_sync(&bq->work); | ||
833 | } | ||
834 | |||
835 | mutex_unlock(&bq2415x_timer_mutex); | ||
836 | } | ||
837 | |||
838 | /* called by bq2415x_timer_work on timer error */ | ||
839 | static void bq2415x_timer_error(struct bq2415x_device *bq, const char *msg) | ||
840 | { | ||
841 | bq->timer_error = msg; | ||
842 | sysfs_notify(&bq->charger.dev->kobj, NULL, "timer"); | ||
843 | dev_err(bq->dev, "%s\n", msg); | ||
844 | if (bq->automode > 0) | ||
845 | bq->automode = 0; | ||
846 | bq2415x_set_mode(bq, BQ2415X_MODE_NONE); | ||
847 | bq2415x_set_autotimer(bq, 0); | ||
848 | } | ||
849 | |||
850 | /* delayed work function for auto resetting chip timer */ | ||
851 | static void bq2415x_timer_work(struct work_struct *work) | ||
852 | { | ||
853 | struct bq2415x_device *bq = container_of(work, struct bq2415x_device, | ||
854 | work.work); | ||
855 | int ret; | ||
856 | int error; | ||
857 | int boost; | ||
858 | |||
859 | if (!bq->autotimer) | ||
860 | return; | ||
861 | |||
862 | ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET); | ||
863 | if (ret < 0) { | ||
864 | bq2415x_timer_error(bq, "Resetting timer failed"); | ||
865 | return; | ||
866 | } | ||
867 | |||
868 | boost = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_STATUS); | ||
869 | if (boost < 0) { | ||
870 | bq2415x_timer_error(bq, "Unknown error"); | ||
871 | return; | ||
872 | } | ||
873 | |||
874 | error = bq2415x_exec_command(bq, BQ2415X_FAULT_STATUS); | ||
875 | if (error < 0) { | ||
876 | bq2415x_timer_error(bq, "Unknown error"); | ||
877 | return; | ||
878 | } | ||
879 | |||
880 | if (boost) { | ||
881 | switch (error) { | ||
882 | /* Non fatal errors, chip is OK */ | ||
883 | case 0: /* No error */ | ||
884 | break; | ||
885 | case 6: /* Timer expired */ | ||
886 | dev_err(bq->dev, "Timer expired\n"); | ||
887 | break; | ||
888 | case 3: /* Battery voltage too low */ | ||
889 | dev_err(bq->dev, "Battery voltage to low\n"); | ||
890 | break; | ||
891 | |||
892 | /* Fatal errors, disable and reset chip */ | ||
893 | case 1: /* Overvoltage protection (chip fried) */ | ||
894 | bq2415x_timer_error(bq, | ||
895 | "Overvoltage protection (chip fried)"); | ||
896 | return; | ||
897 | case 2: /* Overload */ | ||
898 | bq2415x_timer_error(bq, "Overload"); | ||
899 | return; | ||
900 | case 4: /* Battery overvoltage protection */ | ||
901 | bq2415x_timer_error(bq, | ||
902 | "Battery overvoltage protection"); | ||
903 | return; | ||
904 | case 5: /* Thermal shutdown (too hot) */ | ||
905 | bq2415x_timer_error(bq, | ||
906 | "Thermal shutdown (too hot)"); | ||
907 | return; | ||
908 | case 7: /* N/A */ | ||
909 | bq2415x_timer_error(bq, "Unknown error"); | ||
910 | return; | ||
911 | } | ||
912 | } else { | ||
913 | switch (error) { | ||
914 | /* Non fatal errors, chip is OK */ | ||
915 | case 0: /* No error */ | ||
916 | break; | ||
917 | case 2: /* Sleep mode */ | ||
918 | dev_err(bq->dev, "Sleep mode\n"); | ||
919 | break; | ||
920 | case 3: /* Poor input source */ | ||
921 | dev_err(bq->dev, "Poor input source\n"); | ||
922 | break; | ||
923 | case 6: /* Timer expired */ | ||
924 | dev_err(bq->dev, "Timer expired\n"); | ||
925 | break; | ||
926 | case 7: /* No battery */ | ||
927 | dev_err(bq->dev, "No battery\n"); | ||
928 | break; | ||
929 | |||
930 | /* Fatal errors, disable and reset chip */ | ||
931 | case 1: /* Overvoltage protection (chip fried) */ | ||
932 | bq2415x_timer_error(bq, | ||
933 | "Overvoltage protection (chip fried)"); | ||
934 | return; | ||
935 | case 4: /* Battery overvoltage protection */ | ||
936 | bq2415x_timer_error(bq, | ||
937 | "Battery overvoltage protection"); | ||
938 | return; | ||
939 | case 5: /* Thermal shutdown (too hot) */ | ||
940 | bq2415x_timer_error(bq, | ||
941 | "Thermal shutdown (too hot)"); | ||
942 | return; | ||
943 | } | ||
944 | } | ||
945 | |||
946 | schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ); | ||
947 | } | ||
948 | |||
949 | /**** power supply interface code ****/ | ||
950 | |||
951 | static enum power_supply_property bq2415x_power_supply_props[] = { | ||
952 | /* TODO: maybe add more power supply properties */ | ||
953 | POWER_SUPPLY_PROP_STATUS, | ||
954 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
955 | }; | ||
956 | |||
957 | static int bq2415x_power_supply_get_property(struct power_supply *psy, | ||
958 | enum power_supply_property psp, | ||
959 | union power_supply_propval *val) | ||
960 | { | ||
961 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
962 | charger); | ||
963 | int ret; | ||
964 | |||
965 | switch (psp) { | ||
966 | case POWER_SUPPLY_PROP_STATUS: | ||
967 | ret = bq2415x_exec_command(bq, BQ2415X_CHARGE_STATUS); | ||
968 | if (ret < 0) | ||
969 | return ret; | ||
970 | else if (ret == 0) /* Ready */ | ||
971 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
972 | else if (ret == 1) /* Charge in progress */ | ||
973 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
974 | else if (ret == 2) /* Charge done */ | ||
975 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
976 | else | ||
977 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
978 | break; | ||
979 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
980 | val->strval = bq->model; | ||
981 | break; | ||
982 | default: | ||
983 | return -EINVAL; | ||
984 | } | ||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | static int bq2415x_power_supply_init(struct bq2415x_device *bq) | ||
989 | { | ||
990 | int ret; | ||
991 | int chip; | ||
992 | char revstr[8]; | ||
993 | |||
994 | bq->charger.name = bq->name; | ||
995 | bq->charger.type = POWER_SUPPLY_TYPE_USB; | ||
996 | bq->charger.properties = bq2415x_power_supply_props; | ||
997 | bq->charger.num_properties = ARRAY_SIZE(bq2415x_power_supply_props); | ||
998 | bq->charger.get_property = bq2415x_power_supply_get_property; | ||
999 | |||
1000 | ret = bq2415x_detect_chip(bq); | ||
1001 | if (ret < 0) | ||
1002 | chip = BQUNKNOWN; | ||
1003 | else | ||
1004 | chip = ret; | ||
1005 | |||
1006 | ret = bq2415x_detect_revision(bq); | ||
1007 | if (ret < 0) | ||
1008 | strcpy(revstr, "unknown"); | ||
1009 | else | ||
1010 | sprintf(revstr, "1.%d", ret); | ||
1011 | |||
1012 | bq->model = kasprintf(GFP_KERNEL, | ||
1013 | "chip %s, revision %s, vender code %.3d", | ||
1014 | bq2415x_chip_name[chip], revstr, | ||
1015 | bq2415x_get_vender_code(bq)); | ||
1016 | if (!bq->model) { | ||
1017 | dev_err(bq->dev, "failed to allocate model name\n"); | ||
1018 | return -ENOMEM; | ||
1019 | } | ||
1020 | |||
1021 | ret = power_supply_register(bq->dev, &bq->charger); | ||
1022 | if (ret) { | ||
1023 | kfree(bq->model); | ||
1024 | return ret; | ||
1025 | } | ||
1026 | |||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static void bq2415x_power_supply_exit(struct bq2415x_device *bq) | ||
1031 | { | ||
1032 | bq->autotimer = 0; | ||
1033 | if (bq->automode > 0) | ||
1034 | bq->automode = 0; | ||
1035 | cancel_delayed_work_sync(&bq->work); | ||
1036 | power_supply_unregister(&bq->charger); | ||
1037 | kfree(bq->model); | ||
1038 | } | ||
1039 | |||
1040 | /**** additional sysfs entries for power supply interface ****/ | ||
1041 | |||
1042 | /* show *_status entries */ | ||
1043 | static ssize_t bq2415x_sysfs_show_status(struct device *dev, | ||
1044 | struct device_attribute *attr, | ||
1045 | char *buf) | ||
1046 | { | ||
1047 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1048 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1049 | charger); | ||
1050 | enum bq2415x_command command; | ||
1051 | int ret; | ||
1052 | |||
1053 | if (strcmp(attr->attr.name, "otg_status") == 0) | ||
1054 | command = BQ2415X_OTG_STATUS; | ||
1055 | else if (strcmp(attr->attr.name, "charge_status") == 0) | ||
1056 | command = BQ2415X_CHARGE_STATUS; | ||
1057 | else if (strcmp(attr->attr.name, "boost_status") == 0) | ||
1058 | command = BQ2415X_BOOST_STATUS; | ||
1059 | else if (strcmp(attr->attr.name, "fault_status") == 0) | ||
1060 | command = BQ2415X_FAULT_STATUS; | ||
1061 | else | ||
1062 | return -EINVAL; | ||
1063 | |||
1064 | ret = bq2415x_exec_command(bq, command); | ||
1065 | if (ret < 0) | ||
1066 | return ret; | ||
1067 | return sprintf(buf, "%d\n", ret); | ||
1068 | } | ||
1069 | |||
1070 | /* | ||
1071 | * set timer entry: | ||
1072 | * auto - enable auto mode | ||
1073 | * off - disable auto mode | ||
1074 | * (other values) - reset chip timer | ||
1075 | */ | ||
1076 | static ssize_t bq2415x_sysfs_set_timer(struct device *dev, | ||
1077 | struct device_attribute *attr, | ||
1078 | const char *buf, | ||
1079 | size_t count) | ||
1080 | { | ||
1081 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1082 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1083 | charger); | ||
1084 | int ret = 0; | ||
1085 | |||
1086 | if (strncmp(buf, "auto", 4) == 0) | ||
1087 | bq2415x_set_autotimer(bq, 1); | ||
1088 | else if (strncmp(buf, "off", 3) == 0) | ||
1089 | bq2415x_set_autotimer(bq, 0); | ||
1090 | else | ||
1091 | ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET); | ||
1092 | |||
1093 | if (ret < 0) | ||
1094 | return ret; | ||
1095 | return count; | ||
1096 | } | ||
1097 | |||
1098 | /* show timer entry (auto or off) */ | ||
1099 | static ssize_t bq2415x_sysfs_show_timer(struct device *dev, | ||
1100 | struct device_attribute *attr, | ||
1101 | char *buf) | ||
1102 | { | ||
1103 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1104 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1105 | charger); | ||
1106 | |||
1107 | if (bq->timer_error) | ||
1108 | return sprintf(buf, "%s\n", bq->timer_error); | ||
1109 | |||
1110 | if (bq->autotimer) | ||
1111 | return sprintf(buf, "auto\n"); | ||
1112 | return sprintf(buf, "off\n"); | ||
1113 | } | ||
1114 | |||
1115 | /* | ||
1116 | * set mode entry: | ||
1117 | * auto - if automode is supported, enable it and set mode to reported | ||
1118 | * none - disable charger and boost mode | ||
1119 | * host - charging mode for host/hub chargers (current limit 500mA) | ||
1120 | * dedicated - charging mode for dedicated chargers (unlimited current limit) | ||
1121 | * boost - disable charger and enable boost mode | ||
1122 | */ | ||
1123 | static ssize_t bq2415x_sysfs_set_mode(struct device *dev, | ||
1124 | struct device_attribute *attr, | ||
1125 | const char *buf, | ||
1126 | size_t count) | ||
1127 | { | ||
1128 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1129 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1130 | charger); | ||
1131 | enum bq2415x_mode mode; | ||
1132 | int ret = 0; | ||
1133 | |||
1134 | if (strncmp(buf, "auto", 4) == 0) { | ||
1135 | if (bq->automode < 0) | ||
1136 | return -ENOSYS; | ||
1137 | bq->automode = 1; | ||
1138 | mode = bq->reported_mode; | ||
1139 | } else if (strncmp(buf, "none", 4) == 0) { | ||
1140 | if (bq->automode > 0) | ||
1141 | bq->automode = 0; | ||
1142 | mode = BQ2415X_MODE_NONE; | ||
1143 | } else if (strncmp(buf, "host", 4) == 0) { | ||
1144 | if (bq->automode > 0) | ||
1145 | bq->automode = 0; | ||
1146 | mode = BQ2415X_MODE_HOST_CHARGER; | ||
1147 | } else if (strncmp(buf, "dedicated", 9) == 0) { | ||
1148 | if (bq->automode > 0) | ||
1149 | bq->automode = 0; | ||
1150 | mode = BQ2415X_MODE_DEDICATED_CHARGER; | ||
1151 | } else if (strncmp(buf, "boost", 5) == 0) { | ||
1152 | if (bq->automode > 0) | ||
1153 | bq->automode = 0; | ||
1154 | mode = BQ2415X_MODE_BOOST; | ||
1155 | } else if (strncmp(buf, "reset", 5) == 0) { | ||
1156 | bq2415x_reset_chip(bq); | ||
1157 | bq2415x_set_defaults(bq); | ||
1158 | if (bq->automode <= 0) | ||
1159 | return count; | ||
1160 | bq->automode = 1; | ||
1161 | mode = bq->reported_mode; | ||
1162 | } else { | ||
1163 | return -EINVAL; | ||
1164 | } | ||
1165 | |||
1166 | ret = bq2415x_set_mode(bq, mode); | ||
1167 | if (ret < 0) | ||
1168 | return ret; | ||
1169 | return count; | ||
1170 | } | ||
1171 | |||
1172 | /* show mode entry (auto, none, host, dedicated or boost) */ | ||
1173 | static ssize_t bq2415x_sysfs_show_mode(struct device *dev, | ||
1174 | struct device_attribute *attr, | ||
1175 | char *buf) | ||
1176 | { | ||
1177 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1178 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1179 | charger); | ||
1180 | ssize_t ret = 0; | ||
1181 | |||
1182 | if (bq->automode > 0) | ||
1183 | ret += sprintf(buf+ret, "auto ("); | ||
1184 | |||
1185 | switch (bq->mode) { | ||
1186 | case BQ2415X_MODE_NONE: | ||
1187 | ret += sprintf(buf+ret, "none"); | ||
1188 | break; | ||
1189 | case BQ2415X_MODE_HOST_CHARGER: | ||
1190 | ret += sprintf(buf+ret, "host"); | ||
1191 | break; | ||
1192 | case BQ2415X_MODE_DEDICATED_CHARGER: | ||
1193 | ret += sprintf(buf+ret, "dedicated"); | ||
1194 | break; | ||
1195 | case BQ2415X_MODE_BOOST: | ||
1196 | ret += sprintf(buf+ret, "boost"); | ||
1197 | break; | ||
1198 | } | ||
1199 | |||
1200 | if (bq->automode > 0) | ||
1201 | ret += sprintf(buf+ret, ")"); | ||
1202 | |||
1203 | ret += sprintf(buf+ret, "\n"); | ||
1204 | return ret; | ||
1205 | } | ||
1206 | |||
1207 | /* show reported_mode entry (none, host, dedicated or boost) */ | ||
1208 | static ssize_t bq2415x_sysfs_show_reported_mode(struct device *dev, | ||
1209 | struct device_attribute *attr, | ||
1210 | char *buf) | ||
1211 | { | ||
1212 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1213 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1214 | charger); | ||
1215 | |||
1216 | if (bq->automode < 0) | ||
1217 | return -EINVAL; | ||
1218 | |||
1219 | switch (bq->reported_mode) { | ||
1220 | case BQ2415X_MODE_NONE: | ||
1221 | return sprintf(buf, "none\n"); | ||
1222 | case BQ2415X_MODE_HOST_CHARGER: | ||
1223 | return sprintf(buf, "host\n"); | ||
1224 | case BQ2415X_MODE_DEDICATED_CHARGER: | ||
1225 | return sprintf(buf, "dedicated\n"); | ||
1226 | case BQ2415X_MODE_BOOST: | ||
1227 | return sprintf(buf, "boost\n"); | ||
1228 | } | ||
1229 | |||
1230 | return -EINVAL; | ||
1231 | } | ||
1232 | |||
1233 | /* directly set raw value to chip register, format: 'register value' */ | ||
1234 | static ssize_t bq2415x_sysfs_set_registers(struct device *dev, | ||
1235 | struct device_attribute *attr, | ||
1236 | const char *buf, | ||
1237 | size_t count) | ||
1238 | { | ||
1239 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1240 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1241 | charger); | ||
1242 | ssize_t ret = 0; | ||
1243 | unsigned int reg; | ||
1244 | unsigned int val; | ||
1245 | |||
1246 | if (sscanf(buf, "%x %x", ®, &val) != 2) | ||
1247 | return -EINVAL; | ||
1248 | |||
1249 | if (reg > 4 || val > 255) | ||
1250 | return -EINVAL; | ||
1251 | |||
1252 | ret = bq2415x_i2c_write(bq, reg, val); | ||
1253 | if (ret < 0) | ||
1254 | return ret; | ||
1255 | return count; | ||
1256 | } | ||
1257 | |||
1258 | /* print value of chip register, format: 'register=value' */ | ||
1259 | static ssize_t bq2415x_sysfs_print_reg(struct bq2415x_device *bq, | ||
1260 | u8 reg, | ||
1261 | char *buf) | ||
1262 | { | ||
1263 | int ret = bq2415x_i2c_read(bq, reg); | ||
1264 | |||
1265 | if (ret < 0) | ||
1266 | return sprintf(buf, "%#.2x=error %d\n", reg, ret); | ||
1267 | return sprintf(buf, "%#.2x=%#.2x\n", reg, ret); | ||
1268 | } | ||
1269 | |||
1270 | /* show all raw values of chip register, format per line: 'register=value' */ | ||
1271 | static ssize_t bq2415x_sysfs_show_registers(struct device *dev, | ||
1272 | struct device_attribute *attr, | ||
1273 | char *buf) | ||
1274 | { | ||
1275 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1276 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1277 | charger); | ||
1278 | ssize_t ret = 0; | ||
1279 | |||
1280 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_STATUS, buf+ret); | ||
1281 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CONTROL, buf+ret); | ||
1282 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VOLTAGE, buf+ret); | ||
1283 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VENDER, buf+ret); | ||
1284 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CURRENT, buf+ret); | ||
1285 | return ret; | ||
1286 | } | ||
1287 | |||
1288 | /* set current and voltage limit entries (in mA or mV) */ | ||
1289 | static ssize_t bq2415x_sysfs_set_limit(struct device *dev, | ||
1290 | struct device_attribute *attr, | ||
1291 | const char *buf, | ||
1292 | size_t count) | ||
1293 | { | ||
1294 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1295 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1296 | charger); | ||
1297 | long val; | ||
1298 | int ret; | ||
1299 | |||
1300 | if (kstrtol(buf, 10, &val) < 0) | ||
1301 | return -EINVAL; | ||
1302 | |||
1303 | if (strcmp(attr->attr.name, "current_limit") == 0) | ||
1304 | ret = bq2415x_set_current_limit(bq, val); | ||
1305 | else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0) | ||
1306 | ret = bq2415x_set_weak_battery_voltage(bq, val); | ||
1307 | else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0) | ||
1308 | ret = bq2415x_set_battery_regulation_voltage(bq, val); | ||
1309 | else if (strcmp(attr->attr.name, "charge_current") == 0) | ||
1310 | ret = bq2415x_set_charge_current(bq, val); | ||
1311 | else if (strcmp(attr->attr.name, "termination_current") == 0) | ||
1312 | ret = bq2415x_set_termination_current(bq, val); | ||
1313 | else | ||
1314 | return -EINVAL; | ||
1315 | |||
1316 | if (ret < 0) | ||
1317 | return ret; | ||
1318 | return count; | ||
1319 | } | ||
1320 | |||
1321 | /* show current and voltage limit entries (in mA or mV) */ | ||
1322 | static ssize_t bq2415x_sysfs_show_limit(struct device *dev, | ||
1323 | struct device_attribute *attr, | ||
1324 | char *buf) | ||
1325 | { | ||
1326 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1327 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1328 | charger); | ||
1329 | int ret; | ||
1330 | |||
1331 | if (strcmp(attr->attr.name, "current_limit") == 0) | ||
1332 | ret = bq2415x_get_current_limit(bq); | ||
1333 | else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0) | ||
1334 | ret = bq2415x_get_weak_battery_voltage(bq); | ||
1335 | else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0) | ||
1336 | ret = bq2415x_get_battery_regulation_voltage(bq); | ||
1337 | else if (strcmp(attr->attr.name, "charge_current") == 0) | ||
1338 | ret = bq2415x_get_charge_current(bq); | ||
1339 | else if (strcmp(attr->attr.name, "termination_current") == 0) | ||
1340 | ret = bq2415x_get_termination_current(bq); | ||
1341 | else | ||
1342 | return -EINVAL; | ||
1343 | |||
1344 | if (ret < 0) | ||
1345 | return ret; | ||
1346 | return sprintf(buf, "%d\n", ret); | ||
1347 | } | ||
1348 | |||
1349 | /* set *_enable entries */ | ||
1350 | static ssize_t bq2415x_sysfs_set_enable(struct device *dev, | ||
1351 | struct device_attribute *attr, | ||
1352 | const char *buf, | ||
1353 | size_t count) | ||
1354 | { | ||
1355 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1356 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1357 | charger); | ||
1358 | enum bq2415x_command command; | ||
1359 | long val; | ||
1360 | int ret; | ||
1361 | |||
1362 | if (kstrtol(buf, 10, &val) < 0) | ||
1363 | return -EINVAL; | ||
1364 | |||
1365 | if (strcmp(attr->attr.name, "charge_termination_enable") == 0) | ||
1366 | command = val ? BQ2415X_CHARGE_TERMINATION_ENABLE : | ||
1367 | BQ2415X_CHARGE_TERMINATION_DISABLE; | ||
1368 | else if (strcmp(attr->attr.name, "high_impedance_enable") == 0) | ||
1369 | command = val ? BQ2415X_HIGH_IMPEDANCE_ENABLE : | ||
1370 | BQ2415X_HIGH_IMPEDANCE_DISABLE; | ||
1371 | else if (strcmp(attr->attr.name, "otg_pin_enable") == 0) | ||
1372 | command = val ? BQ2415X_OTG_PIN_ENABLE : | ||
1373 | BQ2415X_OTG_PIN_DISABLE; | ||
1374 | else if (strcmp(attr->attr.name, "stat_pin_enable") == 0) | ||
1375 | command = val ? BQ2415X_STAT_PIN_ENABLE : | ||
1376 | BQ2415X_STAT_PIN_DISABLE; | ||
1377 | else | ||
1378 | return -EINVAL; | ||
1379 | |||
1380 | ret = bq2415x_exec_command(bq, command); | ||
1381 | if (ret < 0) | ||
1382 | return ret; | ||
1383 | return count; | ||
1384 | } | ||
1385 | |||
1386 | /* show *_enable entries */ | ||
1387 | static ssize_t bq2415x_sysfs_show_enable(struct device *dev, | ||
1388 | struct device_attribute *attr, | ||
1389 | char *buf) | ||
1390 | { | ||
1391 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1392 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1393 | charger); | ||
1394 | enum bq2415x_command command; | ||
1395 | int ret; | ||
1396 | |||
1397 | if (strcmp(attr->attr.name, "charge_termination_enable") == 0) | ||
1398 | command = BQ2415X_CHARGE_TERMINATION_STATUS; | ||
1399 | else if (strcmp(attr->attr.name, "high_impedance_enable") == 0) | ||
1400 | command = BQ2415X_HIGH_IMPEDANCE_STATUS; | ||
1401 | else if (strcmp(attr->attr.name, "otg_pin_enable") == 0) | ||
1402 | command = BQ2415X_OTG_PIN_STATUS; | ||
1403 | else if (strcmp(attr->attr.name, "stat_pin_enable") == 0) | ||
1404 | command = BQ2415X_STAT_PIN_STATUS; | ||
1405 | else | ||
1406 | return -EINVAL; | ||
1407 | |||
1408 | ret = bq2415x_exec_command(bq, command); | ||
1409 | if (ret < 0) | ||
1410 | return ret; | ||
1411 | return sprintf(buf, "%d\n", ret); | ||
1412 | } | ||
1413 | |||
1414 | static DEVICE_ATTR(current_limit, S_IWUSR | S_IRUGO, | ||
1415 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1416 | static DEVICE_ATTR(weak_battery_voltage, S_IWUSR | S_IRUGO, | ||
1417 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1418 | static DEVICE_ATTR(battery_regulation_voltage, S_IWUSR | S_IRUGO, | ||
1419 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1420 | static DEVICE_ATTR(charge_current, S_IWUSR | S_IRUGO, | ||
1421 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1422 | static DEVICE_ATTR(termination_current, S_IWUSR | S_IRUGO, | ||
1423 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1424 | |||
1425 | static DEVICE_ATTR(charge_termination_enable, S_IWUSR | S_IRUGO, | ||
1426 | bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable); | ||
1427 | static DEVICE_ATTR(high_impedance_enable, S_IWUSR | S_IRUGO, | ||
1428 | bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable); | ||
1429 | static DEVICE_ATTR(otg_pin_enable, S_IWUSR | S_IRUGO, | ||
1430 | bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable); | ||
1431 | static DEVICE_ATTR(stat_pin_enable, S_IWUSR | S_IRUGO, | ||
1432 | bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable); | ||
1433 | |||
1434 | static DEVICE_ATTR(reported_mode, S_IRUGO, | ||
1435 | bq2415x_sysfs_show_reported_mode, NULL); | ||
1436 | static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, | ||
1437 | bq2415x_sysfs_show_mode, bq2415x_sysfs_set_mode); | ||
1438 | static DEVICE_ATTR(timer, S_IWUSR | S_IRUGO, | ||
1439 | bq2415x_sysfs_show_timer, bq2415x_sysfs_set_timer); | ||
1440 | |||
1441 | static DEVICE_ATTR(registers, S_IWUSR | S_IRUGO, | ||
1442 | bq2415x_sysfs_show_registers, bq2415x_sysfs_set_registers); | ||
1443 | |||
1444 | static DEVICE_ATTR(otg_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); | ||
1445 | static DEVICE_ATTR(charge_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); | ||
1446 | static DEVICE_ATTR(boost_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); | ||
1447 | static DEVICE_ATTR(fault_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); | ||
1448 | |||
1449 | static struct attribute *bq2415x_sysfs_attributes[] = { | ||
1450 | /* | ||
1451 | * TODO: some (appropriate) of these attrs should be switched to | ||
1452 | * use power supply class props. | ||
1453 | */ | ||
1454 | &dev_attr_current_limit.attr, | ||
1455 | &dev_attr_weak_battery_voltage.attr, | ||
1456 | &dev_attr_battery_regulation_voltage.attr, | ||
1457 | &dev_attr_charge_current.attr, | ||
1458 | &dev_attr_termination_current.attr, | ||
1459 | |||
1460 | &dev_attr_charge_termination_enable.attr, | ||
1461 | &dev_attr_high_impedance_enable.attr, | ||
1462 | &dev_attr_otg_pin_enable.attr, | ||
1463 | &dev_attr_stat_pin_enable.attr, | ||
1464 | |||
1465 | &dev_attr_reported_mode.attr, | ||
1466 | &dev_attr_mode.attr, | ||
1467 | &dev_attr_timer.attr, | ||
1468 | |||
1469 | &dev_attr_registers.attr, | ||
1470 | |||
1471 | &dev_attr_otg_status.attr, | ||
1472 | &dev_attr_charge_status.attr, | ||
1473 | &dev_attr_boost_status.attr, | ||
1474 | &dev_attr_fault_status.attr, | ||
1475 | NULL, | ||
1476 | }; | ||
1477 | |||
1478 | static const struct attribute_group bq2415x_sysfs_attr_group = { | ||
1479 | .attrs = bq2415x_sysfs_attributes, | ||
1480 | }; | ||
1481 | |||
1482 | static int bq2415x_sysfs_init(struct bq2415x_device *bq) | ||
1483 | { | ||
1484 | return sysfs_create_group(&bq->charger.dev->kobj, | ||
1485 | &bq2415x_sysfs_attr_group); | ||
1486 | } | ||
1487 | |||
1488 | static void bq2415x_sysfs_exit(struct bq2415x_device *bq) | ||
1489 | { | ||
1490 | sysfs_remove_group(&bq->charger.dev->kobj, &bq2415x_sysfs_attr_group); | ||
1491 | } | ||
1492 | |||
1493 | /* main bq2415x probe function */ | ||
1494 | static int bq2415x_probe(struct i2c_client *client, | ||
1495 | const struct i2c_device_id *id) | ||
1496 | { | ||
1497 | int ret; | ||
1498 | int num; | ||
1499 | char *name; | ||
1500 | struct bq2415x_device *bq; | ||
1501 | |||
1502 | if (!client->dev.platform_data) { | ||
1503 | dev_err(&client->dev, "platform data not set\n"); | ||
1504 | return -ENODEV; | ||
1505 | } | ||
1506 | |||
1507 | /* Get new ID for the new device */ | ||
1508 | ret = idr_pre_get(&bq2415x_id, GFP_KERNEL); | ||
1509 | if (ret == 0) | ||
1510 | return -ENOMEM; | ||
1511 | |||
1512 | mutex_lock(&bq2415x_id_mutex); | ||
1513 | ret = idr_get_new(&bq2415x_id, client, &num); | ||
1514 | mutex_unlock(&bq2415x_id_mutex); | ||
1515 | |||
1516 | if (ret < 0) | ||
1517 | return ret; | ||
1518 | |||
1519 | name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num); | ||
1520 | if (!name) { | ||
1521 | dev_err(&client->dev, "failed to allocate device name\n"); | ||
1522 | ret = -ENOMEM; | ||
1523 | goto error_1; | ||
1524 | } | ||
1525 | |||
1526 | bq = kzalloc(sizeof(*bq), GFP_KERNEL); | ||
1527 | if (!bq) { | ||
1528 | dev_err(&client->dev, "failed to allocate device data\n"); | ||
1529 | ret = -ENOMEM; | ||
1530 | goto error_2; | ||
1531 | } | ||
1532 | |||
1533 | i2c_set_clientdata(client, bq); | ||
1534 | |||
1535 | bq->id = num; | ||
1536 | bq->dev = &client->dev; | ||
1537 | bq->chip = id->driver_data; | ||
1538 | bq->name = name; | ||
1539 | bq->mode = BQ2415X_MODE_NONE; | ||
1540 | bq->reported_mode = BQ2415X_MODE_NONE; | ||
1541 | bq->autotimer = 0; | ||
1542 | bq->automode = 0; | ||
1543 | |||
1544 | memcpy(&bq->init_data, client->dev.platform_data, | ||
1545 | sizeof(bq->init_data)); | ||
1546 | |||
1547 | bq2415x_reset_chip(bq); | ||
1548 | |||
1549 | ret = bq2415x_power_supply_init(bq); | ||
1550 | if (ret) { | ||
1551 | dev_err(bq->dev, "failed to register power supply: %d\n", ret); | ||
1552 | goto error_3; | ||
1553 | } | ||
1554 | |||
1555 | ret = bq2415x_sysfs_init(bq); | ||
1556 | if (ret) { | ||
1557 | dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret); | ||
1558 | goto error_4; | ||
1559 | } | ||
1560 | |||
1561 | ret = bq2415x_set_defaults(bq); | ||
1562 | if (ret) { | ||
1563 | dev_err(bq->dev, "failed to set default values: %d\n", ret); | ||
1564 | goto error_5; | ||
1565 | } | ||
1566 | |||
1567 | if (bq->init_data.set_mode_hook) { | ||
1568 | if (bq->init_data.set_mode_hook( | ||
1569 | bq2415x_hook_function, bq)) { | ||
1570 | bq->automode = 1; | ||
1571 | bq2415x_set_mode(bq, bq->reported_mode); | ||
1572 | dev_info(bq->dev, "automode enabled\n"); | ||
1573 | } else { | ||
1574 | bq->automode = -1; | ||
1575 | dev_info(bq->dev, "automode failed\n"); | ||
1576 | } | ||
1577 | } else { | ||
1578 | bq->automode = -1; | ||
1579 | dev_info(bq->dev, "automode not supported\n"); | ||
1580 | } | ||
1581 | |||
1582 | INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work); | ||
1583 | bq2415x_set_autotimer(bq, 1); | ||
1584 | |||
1585 | dev_info(bq->dev, "driver registered\n"); | ||
1586 | return 0; | ||
1587 | |||
1588 | error_5: | ||
1589 | bq2415x_sysfs_exit(bq); | ||
1590 | error_4: | ||
1591 | bq2415x_power_supply_exit(bq); | ||
1592 | error_3: | ||
1593 | kfree(bq); | ||
1594 | error_2: | ||
1595 | kfree(name); | ||
1596 | error_1: | ||
1597 | mutex_lock(&bq2415x_id_mutex); | ||
1598 | idr_remove(&bq2415x_id, num); | ||
1599 | mutex_unlock(&bq2415x_id_mutex); | ||
1600 | |||
1601 | return ret; | ||
1602 | } | ||
1603 | |||
1604 | /* main bq2415x remove function */ | ||
1605 | |||
1606 | static int bq2415x_remove(struct i2c_client *client) | ||
1607 | { | ||
1608 | struct bq2415x_device *bq = i2c_get_clientdata(client); | ||
1609 | |||
1610 | if (bq->init_data.set_mode_hook) | ||
1611 | bq->init_data.set_mode_hook(NULL, NULL); | ||
1612 | |||
1613 | bq2415x_sysfs_exit(bq); | ||
1614 | bq2415x_power_supply_exit(bq); | ||
1615 | |||
1616 | bq2415x_reset_chip(bq); | ||
1617 | |||
1618 | mutex_lock(&bq2415x_id_mutex); | ||
1619 | idr_remove(&bq2415x_id, bq->id); | ||
1620 | mutex_unlock(&bq2415x_id_mutex); | ||
1621 | |||
1622 | dev_info(bq->dev, "driver unregistered\n"); | ||
1623 | |||
1624 | kfree(bq->name); | ||
1625 | kfree(bq); | ||
1626 | |||
1627 | return 0; | ||
1628 | } | ||
1629 | |||
1630 | static const struct i2c_device_id bq2415x_i2c_id_table[] = { | ||
1631 | { "bq2415x", BQUNKNOWN }, | ||
1632 | { "bq24150", BQ24150 }, | ||
1633 | { "bq24150a", BQ24150A }, | ||
1634 | { "bq24151", BQ24151 }, | ||
1635 | { "bq24151a", BQ24151A }, | ||
1636 | { "bq24152", BQ24152 }, | ||
1637 | { "bq24153", BQ24153 }, | ||
1638 | { "bq24153a", BQ24153A }, | ||
1639 | { "bq24155", BQ24155 }, | ||
1640 | { "bq24156", BQ24156 }, | ||
1641 | { "bq24156a", BQ24156A }, | ||
1642 | { "bq24158", BQ24158 }, | ||
1643 | {}, | ||
1644 | }; | ||
1645 | MODULE_DEVICE_TABLE(i2c, bq2415x_i2c_id_table); | ||
1646 | |||
1647 | static struct i2c_driver bq2415x_driver = { | ||
1648 | .driver = { | ||
1649 | .name = "bq2415x-charger", | ||
1650 | }, | ||
1651 | .probe = bq2415x_probe, | ||
1652 | .remove = bq2415x_remove, | ||
1653 | .id_table = bq2415x_i2c_id_table, | ||
1654 | }; | ||
1655 | |||
1656 | static int __init bq2415x_init(void) | ||
1657 | { | ||
1658 | return i2c_add_driver(&bq2415x_driver); | ||
1659 | } | ||
1660 | module_init(bq2415x_init); | ||
1661 | |||
1662 | static void __exit bq2415x_exit(void) | ||
1663 | { | ||
1664 | i2c_del_driver(&bq2415x_driver); | ||
1665 | } | ||
1666 | module_exit(bq2415x_exit); | ||
1667 | |||
1668 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); | ||
1669 | MODULE_DESCRIPTION("bq2415x charger driver"); | ||
1670 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 36b34efdafc..e392f4dc77d 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> | 5 | * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> |
6 | * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> | 6 | * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> |
7 | * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com> | 7 | * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com> |
8 | * Copyright (C) 2011 NVIDIA Corporation. | ||
8 | * | 9 | * |
9 | * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. | 10 | * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. |
10 | * | 11 | * |
@@ -22,7 +23,6 @@ | |||
22 | * Datasheets: | 23 | * Datasheets: |
23 | * http://focus.ti.com/docs/prod/folders/print/bq27000.html | 24 | * http://focus.ti.com/docs/prod/folders/print/bq27000.html |
24 | * http://focus.ti.com/docs/prod/folders/print/bq27500.html | 25 | * http://focus.ti.com/docs/prod/folders/print/bq27500.html |
25 | * http://www.ti.com/product/bq27425-g1 | ||
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
@@ -48,41 +48,49 @@ | |||
48 | #define BQ27x00_REG_TTE 0x16 | 48 | #define BQ27x00_REG_TTE 0x16 |
49 | #define BQ27x00_REG_TTF 0x18 | 49 | #define BQ27x00_REG_TTF 0x18 |
50 | #define BQ27x00_REG_TTECP 0x26 | 50 | #define BQ27x00_REG_TTECP 0x26 |
51 | #define BQ27x00_REG_NAC 0x0C /* Nominal available capacity */ | 51 | #define BQ27x00_REG_NAC 0x0C /* Nominal available capaciy */ |
52 | #define BQ27x00_REG_LMD 0x12 /* Last measured discharge */ | 52 | #define BQ27x00_REG_LMD 0x12 /* Last measured discharge */ |
53 | #define BQ27x00_REG_CYCT 0x2A /* Cycle count total */ | 53 | #define BQ27x00_REG_CYCT 0x2A /* Cycle count total */ |
54 | #define BQ27x00_REG_AE 0x22 /* Available energy */ | 54 | #define BQ27x00_REG_AE 0x22 /* Available enery */ |
55 | #define BQ27x00_POWER_AVG 0x24 | ||
56 | 55 | ||
57 | #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ | 56 | #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ |
58 | #define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ | 57 | #define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ |
59 | #define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */ | 58 | #define BQ27000_FLAG_CHGS BIT(7) |
60 | #define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */ | ||
61 | #define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */ | ||
62 | #define BQ27000_FLAG_FC BIT(5) | 59 | #define BQ27000_FLAG_FC BIT(5) |
63 | #define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */ | ||
64 | 60 | ||
65 | #define BQ27500_REG_SOC 0x2C | 61 | #define BQ27500_REG_SOC 0x2C |
66 | #define BQ27500_REG_DCAP 0x3C /* Design capacity */ | 62 | #define BQ27500_REG_DCAP 0x3C /* Design capacity */ |
67 | #define BQ27500_FLAG_DSC BIT(0) | 63 | #define BQ27500_FLAG_DSC BIT(0) |
68 | #define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ | 64 | #define BQ27500_FLAG_SOCF BIT(1) |
69 | #define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ | 65 | #define BQ27500_FLAG_BAT_DET BIT(3) |
70 | #define BQ27500_FLAG_FC BIT(9) | 66 | #define BQ27500_FLAG_FC BIT(9) |
71 | #define BQ27500_FLAG_OTC BIT(15) | 67 | #define BQ27500_FLAG_OTC BIT(15) |
72 | 68 | ||
73 | /* bq27425 register addresses are same as bq27x00 addresses minus 4 */ | ||
74 | #define BQ27425_REG_OFFSET 0x04 | ||
75 | #define BQ27425_REG_SOC 0x18 /* Register address plus offset */ | ||
76 | |||
77 | #define BQ27000_RS 20 /* Resistor sense */ | 69 | #define BQ27000_RS 20 /* Resistor sense */ |
78 | #define BQ27x00_POWER_CONSTANT (256 * 29200 / 1000) | 70 | |
71 | #define BQ27510_CNTL 0x00 | ||
72 | #define BQ27510_ATRATE 0x02 | ||
73 | #define BQ27510_ENERGY_AVAIL 0x22 | ||
74 | #define BQ27510_POWER_AVG 0x24 | ||
75 | |||
76 | /* bq27510-g2 control register sub-commands*/ | ||
77 | #define BQ27510_CNTL_DEVICE_TYPE 0x0001 | ||
78 | #define BQ27510_CNTL_SET_SLEEP 0x0013 | ||
79 | #define BQ27510_CNTL_CLEAR_SLEEP 0x0014 | ||
80 | |||
81 | /* bq27x00 requires 3 to 4 second to update charging status */ | ||
82 | #define CHARGING_STATUS_UPDATE_DELAY_SECS 4 | ||
79 | 83 | ||
80 | struct bq27x00_device_info; | 84 | struct bq27x00_device_info; |
81 | struct bq27x00_access_methods { | 85 | struct bq27x00_access_methods { |
82 | int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); | 86 | int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); |
87 | int (*ctrl_read)(struct bq27x00_device_info *di, u8 ctrl_reg, | ||
88 | u16 ctrl_func_reg); | ||
89 | int (*write)(struct bq27x00_device_info *di, u8 reg, u16 val, | ||
90 | bool single); | ||
83 | }; | 91 | }; |
84 | 92 | ||
85 | enum bq27x00_chip { BQ27000, BQ27500, BQ27425}; | 93 | enum bq27x00_chip { BQ27000, BQ27500, BQ27510 }; |
86 | 94 | ||
87 | struct bq27x00_reg_cache { | 95 | struct bq27x00_reg_cache { |
88 | int temperature; | 96 | int temperature; |
@@ -92,10 +100,9 @@ struct bq27x00_reg_cache { | |||
92 | int charge_full; | 100 | int charge_full; |
93 | int cycle_count; | 101 | int cycle_count; |
94 | int capacity; | 102 | int capacity; |
95 | int energy; | ||
96 | int flags; | 103 | int flags; |
97 | int power_avg; | 104 | |
98 | int health; | 105 | int current_now; |
99 | }; | 106 | }; |
100 | 107 | ||
101 | struct bq27x00_device_info { | 108 | struct bq27x00_device_info { |
@@ -108,12 +115,14 @@ struct bq27x00_device_info { | |||
108 | 115 | ||
109 | unsigned long last_update; | 116 | unsigned long last_update; |
110 | struct delayed_work work; | 117 | struct delayed_work work; |
118 | struct delayed_work external_power_changed_work; | ||
111 | 119 | ||
112 | struct power_supply bat; | 120 | struct power_supply bat; |
113 | 121 | ||
114 | struct bq27x00_access_methods bus; | 122 | struct bq27x00_access_methods bus; |
115 | 123 | ||
116 | struct mutex lock; | 124 | struct mutex lock; |
125 | struct mutex update_lock; | ||
117 | }; | 126 | }; |
118 | 127 | ||
119 | static enum power_supply_property bq27x00_battery_props[] = { | 128 | static enum power_supply_property bq27x00_battery_props[] = { |
@@ -122,7 +131,6 @@ static enum power_supply_property bq27x00_battery_props[] = { | |||
122 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 131 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
123 | POWER_SUPPLY_PROP_CURRENT_NOW, | 132 | POWER_SUPPLY_PROP_CURRENT_NOW, |
124 | POWER_SUPPLY_PROP_CAPACITY, | 133 | POWER_SUPPLY_PROP_CAPACITY, |
125 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
126 | POWER_SUPPLY_PROP_TEMP, | 134 | POWER_SUPPLY_PROP_TEMP, |
127 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | 135 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, |
128 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, | 136 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, |
@@ -134,23 +142,10 @@ static enum power_supply_property bq27x00_battery_props[] = { | |||
134 | POWER_SUPPLY_PROP_CYCLE_COUNT, | 142 | POWER_SUPPLY_PROP_CYCLE_COUNT, |
135 | POWER_SUPPLY_PROP_ENERGY_NOW, | 143 | POWER_SUPPLY_PROP_ENERGY_NOW, |
136 | POWER_SUPPLY_PROP_POWER_AVG, | 144 | POWER_SUPPLY_PROP_POWER_AVG, |
145 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | ||
137 | POWER_SUPPLY_PROP_HEALTH, | 146 | POWER_SUPPLY_PROP_HEALTH, |
138 | }; | 147 | }; |
139 | 148 | ||
140 | static enum power_supply_property bq27425_battery_props[] = { | ||
141 | POWER_SUPPLY_PROP_STATUS, | ||
142 | POWER_SUPPLY_PROP_PRESENT, | ||
143 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
144 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
145 | POWER_SUPPLY_PROP_CAPACITY, | ||
146 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
147 | POWER_SUPPLY_PROP_TEMP, | ||
148 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
149 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
150 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
151 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
152 | }; | ||
153 | |||
154 | static unsigned int poll_interval = 360; | 149 | static unsigned int poll_interval = 360; |
155 | module_param(poll_interval, uint, 0644); | 150 | module_param(poll_interval, uint, 0644); |
156 | MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ | 151 | MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ |
@@ -163,21 +158,44 @@ MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ | |||
163 | static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, | 158 | static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, |
164 | bool single) | 159 | bool single) |
165 | { | 160 | { |
166 | if (di->chip == BQ27425) | ||
167 | return di->bus.read(di, reg - BQ27425_REG_OFFSET, single); | ||
168 | return di->bus.read(di, reg, single); | 161 | return di->bus.read(di, reg, single); |
169 | } | 162 | } |
170 | 163 | ||
171 | /* | 164 | static inline int bq27x00_ctrl_read(struct bq27x00_device_info *di, |
172 | * Higher versions of the chip like BQ27425 and BQ27500 | 165 | u8 ctrl_reg, u16 ctrl_func_reg) |
173 | * differ from BQ27000 and BQ27200 in calculation of certain | 166 | { |
174 | * parameters. Hence we need to check for the chip type. | 167 | return di->bus.ctrl_read(di, ctrl_reg, ctrl_func_reg); |
175 | */ | 168 | } |
176 | static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di) | 169 | |
170 | static inline int bq27x00_write(struct bq27x00_device_info *di, u8 reg, | ||
171 | u16 val, bool single) | ||
177 | { | 172 | { |
178 | if (di->chip == BQ27425 || di->chip == BQ27500) | 173 | return di->bus.write(di, reg, val, single); |
179 | return true; | 174 | } |
180 | return false; | 175 | |
176 | static int bq27510_battery_health(struct bq27x00_device_info *di, | ||
177 | union power_supply_propval *val) | ||
178 | { | ||
179 | int ret; | ||
180 | |||
181 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) { | ||
182 | ret = bq27x00_read(di, BQ27x00_REG_FLAGS, false); | ||
183 | if (ret < 0) { | ||
184 | dev_err(di->dev, "read failure\n"); | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | if (ret & BQ27500_FLAG_SOCF) | ||
189 | val->intval = POWER_SUPPLY_HEALTH_DEAD; | ||
190 | else if (ret & BQ27500_FLAG_OTC) | ||
191 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
192 | else | ||
193 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | return -1; | ||
181 | } | 199 | } |
182 | 200 | ||
183 | /* | 201 | /* |
@@ -188,15 +206,13 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di) | |||
188 | { | 206 | { |
189 | int rsoc; | 207 | int rsoc; |
190 | 208 | ||
191 | if (di->chip == BQ27500) | 209 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) |
192 | rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); | 210 | rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); |
193 | else if (di->chip == BQ27425) | ||
194 | rsoc = bq27x00_read(di, BQ27425_REG_SOC, false); | ||
195 | else | 211 | else |
196 | rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true); | 212 | rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true); |
197 | 213 | ||
198 | if (rsoc < 0) | 214 | if (rsoc < 0) |
199 | dev_dbg(di->dev, "error reading relative State-of-Charge\n"); | 215 | dev_err(di->dev, "error reading relative State-of-Charge\n"); |
200 | 216 | ||
201 | return rsoc; | 217 | return rsoc; |
202 | } | 218 | } |
@@ -211,12 +227,11 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg) | |||
211 | 227 | ||
212 | charge = bq27x00_read(di, reg, false); | 228 | charge = bq27x00_read(di, reg, false); |
213 | if (charge < 0) { | 229 | if (charge < 0) { |
214 | dev_dbg(di->dev, "error reading charge register %02x: %d\n", | 230 | dev_err(di->dev, "error reading nominal available capacity\n"); |
215 | reg, charge); | ||
216 | return charge; | 231 | return charge; |
217 | } | 232 | } |
218 | 233 | ||
219 | if (bq27xxx_is_chip_version_higher(di)) | 234 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) |
220 | charge *= 1000; | 235 | charge *= 1000; |
221 | else | 236 | else |
222 | charge = charge * 3570 / BQ27000_RS; | 237 | charge = charge * 3570 / BQ27000_RS; |
@@ -230,14 +245,6 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg) | |||
230 | */ | 245 | */ |
231 | static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di) | 246 | static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di) |
232 | { | 247 | { |
233 | int flags; | ||
234 | bool is_bq27500 = di->chip == BQ27500; | ||
235 | bool is_higher = bq27xxx_is_chip_version_higher(di); | ||
236 | |||
237 | flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); | ||
238 | if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI)) | ||
239 | return -ENODATA; | ||
240 | |||
241 | return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC); | 248 | return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC); |
242 | } | 249 | } |
243 | 250 | ||
@@ -258,17 +265,17 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di) | |||
258 | { | 265 | { |
259 | int ilmd; | 266 | int ilmd; |
260 | 267 | ||
261 | if (bq27xxx_is_chip_version_higher(di)) | 268 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) |
262 | ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); | 269 | ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); |
263 | else | 270 | else |
264 | ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true); | 271 | ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true); |
265 | 272 | ||
266 | if (ilmd < 0) { | 273 | if (ilmd < 0) { |
267 | dev_dbg(di->dev, "error reading initial last measured discharge\n"); | 274 | dev_err(di->dev, "error reading initial last measured discharge\n"); |
268 | return ilmd; | 275 | return ilmd; |
269 | } | 276 | } |
270 | 277 | ||
271 | if (bq27xxx_is_chip_version_higher(di)) | 278 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) |
272 | ilmd *= 1000; | 279 | ilmd *= 1000; |
273 | else | 280 | else |
274 | ilmd = ilmd * 256 * 3570 / BQ27000_RS; | 281 | ilmd = ilmd * 256 * 3570 / BQ27000_RS; |
@@ -277,50 +284,6 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di) | |||
277 | } | 284 | } |
278 | 285 | ||
279 | /* | 286 | /* |
280 | * Return the battery Available energy in µWh | ||
281 | * Or < 0 if something fails. | ||
282 | */ | ||
283 | static int bq27x00_battery_read_energy(struct bq27x00_device_info *di) | ||
284 | { | ||
285 | int ae; | ||
286 | |||
287 | ae = bq27x00_read(di, BQ27x00_REG_AE, false); | ||
288 | if (ae < 0) { | ||
289 | dev_dbg(di->dev, "error reading available energy\n"); | ||
290 | return ae; | ||
291 | } | ||
292 | |||
293 | if (di->chip == BQ27500) | ||
294 | ae *= 1000; | ||
295 | else | ||
296 | ae = ae * 29200 / BQ27000_RS; | ||
297 | |||
298 | return ae; | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * Return the battery temperature in tenths of degree Celsius | ||
303 | * Or < 0 if something fails. | ||
304 | */ | ||
305 | static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di) | ||
306 | { | ||
307 | int temp; | ||
308 | |||
309 | temp = bq27x00_read(di, BQ27x00_REG_TEMP, false); | ||
310 | if (temp < 0) { | ||
311 | dev_err(di->dev, "error reading temperature\n"); | ||
312 | return temp; | ||
313 | } | ||
314 | |||
315 | if (bq27xxx_is_chip_version_higher(di)) | ||
316 | temp -= 2731; | ||
317 | else | ||
318 | temp = ((temp * 5) - 5463) / 2; | ||
319 | |||
320 | return temp; | ||
321 | } | ||
322 | |||
323 | /* | ||
324 | * Return the battery Cycle count total | 287 | * Return the battery Cycle count total |
325 | * Or < 0 if something fails. | 288 | * Or < 0 if something fails. |
326 | */ | 289 | */ |
@@ -345,8 +308,7 @@ static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg) | |||
345 | 308 | ||
346 | tval = bq27x00_read(di, reg, false); | 309 | tval = bq27x00_read(di, reg, false); |
347 | if (tval < 0) { | 310 | if (tval < 0) { |
348 | dev_dbg(di->dev, "error reading time register %02x: %d\n", | 311 | dev_err(di->dev, "error reading register %02x: %d\n", reg, tval); |
349 | reg, tval); | ||
350 | return tval; | 312 | return tval; |
351 | } | 313 | } |
352 | 314 | ||
@@ -356,113 +318,39 @@ static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg) | |||
356 | return tval * 60; | 318 | return tval * 60; |
357 | } | 319 | } |
358 | 320 | ||
359 | /* | ||
360 | * Read a power avg register. | ||
361 | * Return < 0 if something fails. | ||
362 | */ | ||
363 | static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg) | ||
364 | { | ||
365 | int tval; | ||
366 | |||
367 | tval = bq27x00_read(di, reg, false); | ||
368 | if (tval < 0) { | ||
369 | dev_err(di->dev, "error reading power avg rgister %02x: %d\n", | ||
370 | reg, tval); | ||
371 | return tval; | ||
372 | } | ||
373 | |||
374 | if (di->chip == BQ27500) | ||
375 | return tval; | ||
376 | else | ||
377 | return (tval * BQ27x00_POWER_CONSTANT) / BQ27000_RS; | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * Read flag register. | ||
382 | * Return < 0 if something fails. | ||
383 | */ | ||
384 | static int bq27x00_battery_read_health(struct bq27x00_device_info *di) | ||
385 | { | ||
386 | int tval; | ||
387 | |||
388 | tval = bq27x00_read(di, BQ27x00_REG_FLAGS, false); | ||
389 | if (tval < 0) { | ||
390 | dev_err(di->dev, "error reading flag register:%d\n", tval); | ||
391 | return tval; | ||
392 | } | ||
393 | |||
394 | if ((di->chip == BQ27500)) { | ||
395 | if (tval & BQ27500_FLAG_SOCF) | ||
396 | tval = POWER_SUPPLY_HEALTH_DEAD; | ||
397 | else if (tval & BQ27500_FLAG_OTC) | ||
398 | tval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
399 | else | ||
400 | tval = POWER_SUPPLY_HEALTH_GOOD; | ||
401 | return tval; | ||
402 | } else { | ||
403 | if (tval & BQ27000_FLAG_EDV1) | ||
404 | tval = POWER_SUPPLY_HEALTH_DEAD; | ||
405 | else | ||
406 | tval = POWER_SUPPLY_HEALTH_GOOD; | ||
407 | return tval; | ||
408 | } | ||
409 | |||
410 | return -1; | ||
411 | } | ||
412 | |||
413 | static void bq27x00_update(struct bq27x00_device_info *di) | 321 | static void bq27x00_update(struct bq27x00_device_info *di) |
414 | { | 322 | { |
415 | struct bq27x00_reg_cache cache = {0, }; | 323 | struct bq27x00_reg_cache cache = {0, }; |
416 | bool is_bq27500 = di->chip == BQ27500; | 324 | bool is_bq27500 = (di->chip == BQ27500 || di->chip == BQ27510); |
417 | bool is_bq27425 = di->chip == BQ27425; | ||
418 | 325 | ||
419 | cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); | 326 | mutex_lock(&di->update_lock); |
327 | cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500); | ||
420 | if (cache.flags >= 0) { | 328 | if (cache.flags >= 0) { |
421 | if (!is_bq27500 && !is_bq27425 | 329 | cache.capacity = bq27x00_battery_read_rsoc(di); |
422 | && (cache.flags & BQ27000_FLAG_CI)) { | 330 | cache.temperature = bq27x00_read(di, BQ27x00_REG_TEMP, false); |
423 | dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); | 331 | cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); |
424 | cache.capacity = -ENODATA; | 332 | cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); |
425 | cache.energy = -ENODATA; | 333 | cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); |
426 | cache.time_to_empty = -ENODATA; | 334 | cache.charge_full = bq27x00_battery_read_lmd(di); |
427 | cache.time_to_empty_avg = -ENODATA; | ||
428 | cache.time_to_full = -ENODATA; | ||
429 | cache.charge_full = -ENODATA; | ||
430 | cache.health = -ENODATA; | ||
431 | } else { | ||
432 | cache.capacity = bq27x00_battery_read_rsoc(di); | ||
433 | if (!is_bq27425) { | ||
434 | cache.energy = bq27x00_battery_read_energy(di); | ||
435 | cache.time_to_empty = | ||
436 | bq27x00_battery_read_time(di, | ||
437 | BQ27x00_REG_TTE); | ||
438 | cache.time_to_empty_avg = | ||
439 | bq27x00_battery_read_time(di, | ||
440 | BQ27x00_REG_TTECP); | ||
441 | cache.time_to_full = | ||
442 | bq27x00_battery_read_time(di, | ||
443 | BQ27x00_REG_TTF); | ||
444 | } | ||
445 | cache.charge_full = bq27x00_battery_read_lmd(di); | ||
446 | cache.health = bq27x00_battery_read_health(di); | ||
447 | } | ||
448 | cache.temperature = bq27x00_battery_read_temperature(di); | ||
449 | if (!is_bq27425) | ||
450 | cache.cycle_count = bq27x00_battery_read_cyct(di); | ||
451 | cache.cycle_count = bq27x00_battery_read_cyct(di); | 335 | cache.cycle_count = bq27x00_battery_read_cyct(di); |
452 | cache.power_avg = | 336 | |
453 | bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG); | 337 | if (!is_bq27500) |
338 | cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false); | ||
454 | 339 | ||
455 | /* We only have to read charge design full once */ | 340 | /* We only have to read charge design full once */ |
456 | if (di->charge_design_full <= 0) | 341 | if (di->charge_design_full <= 0) |
457 | di->charge_design_full = bq27x00_battery_read_ilmd(di); | 342 | di->charge_design_full = bq27x00_battery_read_ilmd(di); |
458 | } | 343 | } |
459 | 344 | ||
460 | if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) { | 345 | /* Ignore current_now which is a snapshot of the current battery state |
346 | * and is likely to be different even between two consecutive reads */ | ||
347 | if (memcmp(&di->cache, &cache, sizeof(cache) - sizeof(int)) != 0) { | ||
461 | di->cache = cache; | 348 | di->cache = cache; |
462 | power_supply_changed(&di->bat); | 349 | power_supply_changed(&di->bat); |
463 | } | 350 | } |
464 | 351 | ||
465 | di->last_update = jiffies; | 352 | di->last_update = jiffies; |
353 | mutex_unlock(&di->update_lock); | ||
466 | } | 354 | } |
467 | 355 | ||
468 | static void bq27x00_battery_poll(struct work_struct *work) | 356 | static void bq27x00_battery_poll(struct work_struct *work) |
@@ -479,6 +367,33 @@ static void bq27x00_battery_poll(struct work_struct *work) | |||
479 | } | 367 | } |
480 | } | 368 | } |
481 | 369 | ||
370 | static void bq27x00_external_power_changed_work(struct work_struct *work) | ||
371 | { | ||
372 | struct bq27x00_device_info *di = | ||
373 | container_of(work, struct bq27x00_device_info, | ||
374 | external_power_changed_work.work); | ||
375 | |||
376 | bq27x00_update(di); | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * Return the battery temperature in tenths of degree Celsius | ||
381 | * Or < 0 if something fails. | ||
382 | */ | ||
383 | static int bq27x00_battery_temperature(struct bq27x00_device_info *di, | ||
384 | union power_supply_propval *val) | ||
385 | { | ||
386 | if (di->cache.temperature < 0) | ||
387 | return di->cache.temperature; | ||
388 | |||
389 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) | ||
390 | val->intval = di->cache.temperature - 2731; | ||
391 | else | ||
392 | val->intval = ((di->cache.temperature * 5) - 5463) / 2; | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
482 | /* | 397 | /* |
483 | * Return the battery average current in µA | 398 | * Return the battery average current in µA |
484 | * Note that current can be negative signed as well | 399 | * Note that current can be negative signed as well |
@@ -488,20 +403,20 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di, | |||
488 | union power_supply_propval *val) | 403 | union power_supply_propval *val) |
489 | { | 404 | { |
490 | int curr; | 405 | int curr; |
491 | int flags; | ||
492 | 406 | ||
493 | curr = bq27x00_read(di, BQ27x00_REG_AI, false); | 407 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) |
494 | if (curr < 0) { | 408 | curr = bq27x00_read(di, BQ27x00_REG_AI, false); |
495 | dev_err(di->dev, "error reading current\n"); | 409 | else |
410 | curr = di->cache.current_now; | ||
411 | |||
412 | if (curr < 0) | ||
496 | return curr; | 413 | return curr; |
497 | } | ||
498 | 414 | ||
499 | if (bq27xxx_is_chip_version_higher(di)) { | 415 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) { |
500 | /* bq27500 returns signed value */ | 416 | /* bq27500 returns signed value */ |
501 | val->intval = (int)((s16)curr) * 1000; | 417 | val->intval = (int)((s16)curr) * 1000; |
502 | } else { | 418 | } else { |
503 | flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false); | 419 | if (di->cache.flags & BQ27000_FLAG_CHGS) { |
504 | if (flags & BQ27000_FLAG_CHGS) { | ||
505 | dev_dbg(di->dev, "negative current!\n"); | 420 | dev_dbg(di->dev, "negative current!\n"); |
506 | curr = -curr; | 421 | curr = -curr; |
507 | } | 422 | } |
@@ -517,7 +432,7 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di, | |||
517 | { | 432 | { |
518 | int status; | 433 | int status; |
519 | 434 | ||
520 | if (bq27xxx_is_chip_version_higher(di)) { | 435 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) { |
521 | if (di->cache.flags & BQ27500_FLAG_FC) | 436 | if (di->cache.flags & BQ27500_FLAG_FC) |
522 | status = POWER_SUPPLY_STATUS_FULL; | 437 | status = POWER_SUPPLY_STATUS_FULL; |
523 | else if (di->cache.flags & BQ27500_FLAG_DSC) | 438 | else if (di->cache.flags & BQ27500_FLAG_DSC) |
@@ -540,56 +455,50 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di, | |||
540 | return 0; | 455 | return 0; |
541 | } | 456 | } |
542 | 457 | ||
543 | static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di, | 458 | /* |
459 | * Return the battery Voltage in milivolts | ||
460 | * Or < 0 if something fails. | ||
461 | */ | ||
462 | static int bq27x00_battery_voltage(struct bq27x00_device_info *di, | ||
544 | union power_supply_propval *val) | 463 | union power_supply_propval *val) |
545 | { | 464 | { |
546 | int level; | 465 | int volt; |
547 | 466 | ||
548 | if (bq27xxx_is_chip_version_higher(di)) { | 467 | volt = bq27x00_read(di, BQ27x00_REG_VOLT, false); |
549 | if (di->cache.flags & BQ27500_FLAG_FC) | 468 | if (volt < 0) |
550 | level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | 469 | return volt; |
551 | else if (di->cache.flags & BQ27500_FLAG_SOC1) | ||
552 | level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | ||
553 | else if (di->cache.flags & BQ27500_FLAG_SOCF) | ||
554 | level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | ||
555 | else | ||
556 | level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | ||
557 | } else { | ||
558 | if (di->cache.flags & BQ27000_FLAG_FC) | ||
559 | level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | ||
560 | else if (di->cache.flags & BQ27000_FLAG_EDV1) | ||
561 | level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | ||
562 | else if (di->cache.flags & BQ27000_FLAG_EDVF) | ||
563 | level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | ||
564 | else | ||
565 | level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | ||
566 | } | ||
567 | 470 | ||
568 | val->intval = level; | 471 | val->intval = volt * 1000; |
569 | 472 | ||
570 | return 0; | 473 | return 0; |
571 | } | 474 | } |
572 | 475 | ||
573 | /* | 476 | /* |
574 | * Return the battery Voltage in millivolts | 477 | * Return the battery Available energy in µWh |
575 | * Or < 0 if something fails. | 478 | * Or < 0 if something fails. |
576 | */ | 479 | */ |
577 | static int bq27x00_battery_voltage(struct bq27x00_device_info *di, | 480 | static int bq27x00_battery_energy(struct bq27x00_device_info *di, |
578 | union power_supply_propval *val) | 481 | union power_supply_propval *val) |
579 | { | 482 | { |
580 | int volt; | 483 | int ae; |
581 | 484 | ||
582 | volt = bq27x00_read(di, BQ27x00_REG_VOLT, false); | 485 | ae = bq27x00_read(di, BQ27x00_REG_AE, false); |
583 | if (volt < 0) { | 486 | if (ae < 0) { |
584 | dev_err(di->dev, "error reading voltage\n"); | 487 | dev_err(di->dev, "error reading available energy\n"); |
585 | return volt; | 488 | return ae; |
586 | } | 489 | } |
587 | 490 | ||
588 | val->intval = volt * 1000; | 491 | if ((di->chip == BQ27500) || (di->chip == BQ27510)) |
492 | ae *= 1000; | ||
493 | else | ||
494 | ae = ae * 29200 / BQ27000_RS; | ||
495 | |||
496 | val->intval = ae; | ||
589 | 497 | ||
590 | return 0; | 498 | return 0; |
591 | } | 499 | } |
592 | 500 | ||
501 | |||
593 | static int bq27x00_simple_value(int value, | 502 | static int bq27x00_simple_value(int value, |
594 | union power_supply_propval *val) | 503 | union power_supply_propval *val) |
595 | { | 504 | { |
@@ -601,6 +510,58 @@ static int bq27x00_simple_value(int value, | |||
601 | return 0; | 510 | return 0; |
602 | } | 511 | } |
603 | 512 | ||
513 | static int bq27510_battery_present(struct bq27x00_device_info *di, | ||
514 | union power_supply_propval *val) | ||
515 | { | ||
516 | int ret; | ||
517 | |||
518 | ret = bq27x00_read(di, BQ27x00_REG_FLAGS, false); | ||
519 | if (ret < 0) { | ||
520 | dev_err(di->dev, "error reading flags\n"); | ||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | if (ret & BQ27500_FLAG_BAT_DET) | ||
525 | val->intval = 1; | ||
526 | else | ||
527 | val->intval = 0; | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | static char bq27510_serial[5]; | ||
533 | static int bq27510_get_battery_serial_number(struct bq27x00_device_info *di, | ||
534 | union power_supply_propval *val) | ||
535 | { | ||
536 | int ret; | ||
537 | |||
538 | if (di->chip == BQ27510) { | ||
539 | ret = bq27x00_ctrl_read(di, BQ27510_CNTL, | ||
540 | BQ27510_CNTL_DEVICE_TYPE); | ||
541 | ret = sprintf(bq27510_serial, "%04x", ret); | ||
542 | val->strval = bq27510_serial; | ||
543 | return 0; | ||
544 | } else { | ||
545 | return 1; | ||
546 | } | ||
547 | } | ||
548 | |||
549 | static int bq27510_battery_power_avg(struct bq27x00_device_info *di, | ||
550 | union power_supply_propval *val) | ||
551 | { | ||
552 | int ret; | ||
553 | if (di->chip == BQ27510) { | ||
554 | ret = bq27x00_read(di, BQ27510_POWER_AVG, false); | ||
555 | if (ret < 0) { | ||
556 | dev_err(di->dev, "read failure\n"); | ||
557 | return ret; | ||
558 | } | ||
559 | val->intval = ret; | ||
560 | return 0; | ||
561 | } | ||
562 | return -1; | ||
563 | } | ||
564 | |||
604 | #define to_bq27x00_device_info(x) container_of((x), \ | 565 | #define to_bq27x00_device_info(x) container_of((x), \ |
605 | struct bq27x00_device_info, bat); | 566 | struct bq27x00_device_info, bat); |
606 | 567 | ||
@@ -629,7 +590,7 @@ static int bq27x00_battery_get_property(struct power_supply *psy, | |||
629 | ret = bq27x00_battery_voltage(di, val); | 590 | ret = bq27x00_battery_voltage(di, val); |
630 | break; | 591 | break; |
631 | case POWER_SUPPLY_PROP_PRESENT: | 592 | case POWER_SUPPLY_PROP_PRESENT: |
632 | val->intval = di->cache.flags < 0 ? 0 : 1; | 593 | ret = bq27510_battery_present(di, val); |
633 | break; | 594 | break; |
634 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 595 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
635 | ret = bq27x00_battery_current(di, val); | 596 | ret = bq27x00_battery_current(di, val); |
@@ -637,11 +598,8 @@ static int bq27x00_battery_get_property(struct power_supply *psy, | |||
637 | case POWER_SUPPLY_PROP_CAPACITY: | 598 | case POWER_SUPPLY_PROP_CAPACITY: |
638 | ret = bq27x00_simple_value(di->cache.capacity, val); | 599 | ret = bq27x00_simple_value(di->cache.capacity, val); |
639 | break; | 600 | break; |
640 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: | ||
641 | ret = bq27x00_battery_capacity_level(di, val); | ||
642 | break; | ||
643 | case POWER_SUPPLY_PROP_TEMP: | 601 | case POWER_SUPPLY_PROP_TEMP: |
644 | ret = bq27x00_simple_value(di->cache.temperature, val); | 602 | ret = bq27x00_battery_temperature(di, val); |
645 | break; | 603 | break; |
646 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: | 604 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: |
647 | ret = bq27x00_simple_value(di->cache.time_to_empty, val); | 605 | ret = bq27x00_simple_value(di->cache.time_to_empty, val); |
@@ -668,13 +626,17 @@ static int bq27x00_battery_get_property(struct power_supply *psy, | |||
668 | ret = bq27x00_simple_value(di->cache.cycle_count, val); | 626 | ret = bq27x00_simple_value(di->cache.cycle_count, val); |
669 | break; | 627 | break; |
670 | case POWER_SUPPLY_PROP_ENERGY_NOW: | 628 | case POWER_SUPPLY_PROP_ENERGY_NOW: |
671 | ret = bq27x00_simple_value(di->cache.energy, val); | 629 | ret = bq27x00_battery_energy(di, val); |
672 | break; | 630 | break; |
673 | case POWER_SUPPLY_PROP_POWER_AVG: | 631 | case POWER_SUPPLY_PROP_POWER_AVG: |
674 | ret = bq27x00_simple_value(di->cache.power_avg, val); | 632 | ret = bq27510_battery_power_avg(di, val); |
633 | break; | ||
634 | case POWER_SUPPLY_PROP_SERIAL_NUMBER: | ||
635 | if (bq27510_get_battery_serial_number(di, val)) | ||
636 | return -EINVAL; | ||
675 | break; | 637 | break; |
676 | case POWER_SUPPLY_PROP_HEALTH: | 638 | case POWER_SUPPLY_PROP_HEALTH: |
677 | ret = bq27x00_simple_value(di->cache.health, val); | 639 | ret = bq27510_battery_health(di, val); |
678 | break; | 640 | break; |
679 | default: | 641 | default: |
680 | return -EINVAL; | 642 | return -EINVAL; |
@@ -683,12 +645,19 @@ static int bq27x00_battery_get_property(struct power_supply *psy, | |||
683 | return ret; | 645 | return ret; |
684 | } | 646 | } |
685 | 647 | ||
648 | static unsigned int charging_update_delay_secs = | ||
649 | CHARGING_STATUS_UPDATE_DELAY_SECS; | ||
650 | module_param(charging_update_delay_secs, uint, 0644); | ||
651 | MODULE_PARM_DESC(charging_update_delay_secs, "battery charging " \ | ||
652 | "status update delay in seconds"); | ||
653 | |||
686 | static void bq27x00_external_power_changed(struct power_supply *psy) | 654 | static void bq27x00_external_power_changed(struct power_supply *psy) |
687 | { | 655 | { |
688 | struct bq27x00_device_info *di = to_bq27x00_device_info(psy); | 656 | struct bq27x00_device_info *di = to_bq27x00_device_info(psy); |
689 | 657 | ||
690 | cancel_delayed_work_sync(&di->work); | 658 | cancel_delayed_work_sync(&di->external_power_changed_work); |
691 | schedule_delayed_work(&di->work, 0); | 659 | schedule_delayed_work(&di->external_power_changed_work, |
660 | charging_update_delay_secs * HZ); | ||
692 | } | 661 | } |
693 | 662 | ||
694 | static int bq27x00_powersupply_init(struct bq27x00_device_info *di) | 663 | static int bq27x00_powersupply_init(struct bq27x00_device_info *di) |
@@ -696,19 +665,16 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di) | |||
696 | int ret; | 665 | int ret; |
697 | 666 | ||
698 | di->bat.type = POWER_SUPPLY_TYPE_BATTERY; | 667 | di->bat.type = POWER_SUPPLY_TYPE_BATTERY; |
699 | di->chip = BQ27425; | 668 | di->bat.properties = bq27x00_battery_props; |
700 | if (di->chip == BQ27425) { | 669 | di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); |
701 | di->bat.properties = bq27425_battery_props; | ||
702 | di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props); | ||
703 | } else { | ||
704 | di->bat.properties = bq27x00_battery_props; | ||
705 | di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); | ||
706 | } | ||
707 | di->bat.get_property = bq27x00_battery_get_property; | 670 | di->bat.get_property = bq27x00_battery_get_property; |
708 | di->bat.external_power_changed = bq27x00_external_power_changed; | 671 | di->bat.external_power_changed = bq27x00_external_power_changed; |
709 | 672 | ||
710 | INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll); | 673 | INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll); |
674 | INIT_DELAYED_WORK(&di->external_power_changed_work, | ||
675 | bq27x00_external_power_changed_work); | ||
711 | mutex_init(&di->lock); | 676 | mutex_init(&di->lock); |
677 | mutex_init(&di->update_lock); | ||
712 | 678 | ||
713 | ret = power_supply_register(di->dev, &di->bat); | 679 | ret = power_supply_register(di->dev, &di->bat); |
714 | if (ret) { | 680 | if (ret) { |
@@ -725,19 +691,12 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di) | |||
725 | 691 | ||
726 | static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di) | 692 | static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di) |
727 | { | 693 | { |
728 | /* | ||
729 | * power_supply_unregister call bq27x00_battery_get_property which | ||
730 | * call bq27x00_battery_poll. | ||
731 | * Make sure that bq27x00_battery_poll will not call | ||
732 | * schedule_delayed_work again after unregister (which cause OOPS). | ||
733 | */ | ||
734 | poll_interval = 0; | ||
735 | |||
736 | cancel_delayed_work_sync(&di->work); | 694 | cancel_delayed_work_sync(&di->work); |
737 | 695 | cancel_delayed_work_sync(&di->external_power_changed_work); | |
738 | power_supply_unregister(&di->bat); | 696 | power_supply_unregister(&di->bat); |
739 | 697 | ||
740 | mutex_destroy(&di->lock); | 698 | mutex_destroy(&di->lock); |
699 | mutex_destroy(&di->update_lock); | ||
741 | } | 700 | } |
742 | 701 | ||
743 | 702 | ||
@@ -784,12 +743,55 @@ static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single) | |||
784 | return ret; | 743 | return ret; |
785 | } | 744 | } |
786 | 745 | ||
746 | static int bq27x00_write_i2c(struct bq27x00_device_info *di, u8 reg, | ||
747 | u16 val, bool single) | ||
748 | { | ||
749 | struct i2c_client *client = to_i2c_client(di->dev); | ||
750 | unsigned char i2c_data[3]; | ||
751 | int ret, len; | ||
752 | |||
753 | i2c_data[0] = reg; | ||
754 | i2c_data[1] = val & 0xff; | ||
755 | |||
756 | if (single) { | ||
757 | len = 2; | ||
758 | } else { | ||
759 | i2c_data[2] = (val >> 8) & 0xff; | ||
760 | len = 3; | ||
761 | } | ||
762 | |||
763 | ret = i2c_master_send(client, i2c_data, len); | ||
764 | if (ret == len) | ||
765 | return 0; | ||
766 | |||
767 | return (ret < 0) ? ret : -EIO; | ||
768 | } | ||
769 | |||
770 | static int bq27x00_ctrl_read_i2c(struct bq27x00_device_info *di, | ||
771 | u8 ctrl_reg, u16 ctrl_func_reg) | ||
772 | { | ||
773 | int ret = bq27x00_write(di, ctrl_reg, ctrl_func_reg, false); | ||
774 | if (ret < 0) { | ||
775 | dev_err(di->dev, "write failure\n"); | ||
776 | return ret; | ||
777 | } | ||
778 | |||
779 | ret = bq27x00_read(di, ctrl_reg, false); | ||
780 | if (ret < 0) { | ||
781 | dev_err(di->dev, "read failure\n"); | ||
782 | return ret; | ||
783 | } | ||
784 | |||
785 | return ret; | ||
786 | } | ||
787 | |||
787 | static int bq27x00_battery_probe(struct i2c_client *client, | 788 | static int bq27x00_battery_probe(struct i2c_client *client, |
788 | const struct i2c_device_id *id) | 789 | const struct i2c_device_id *id) |
789 | { | 790 | { |
790 | char *name; | 791 | char *name; |
791 | struct bq27x00_device_info *di; | 792 | struct bq27x00_device_info *di; |
792 | int num; | 793 | int num; |
794 | u16 read_data; | ||
793 | int retval = 0; | 795 | int retval = 0; |
794 | 796 | ||
795 | /* Get new ID for the new battery device */ | 797 | /* Get new ID for the new battery device */ |
@@ -821,12 +823,29 @@ static int bq27x00_battery_probe(struct i2c_client *client, | |||
821 | di->chip = id->driver_data; | 823 | di->chip = id->driver_data; |
822 | di->bat.name = name; | 824 | di->bat.name = name; |
823 | di->bus.read = &bq27x00_read_i2c; | 825 | di->bus.read = &bq27x00_read_i2c; |
826 | di->bus.ctrl_read = &bq27x00_ctrl_read_i2c; | ||
827 | di->bus.write = &bq27x00_write_i2c; | ||
824 | 828 | ||
825 | retval = bq27x00_powersupply_init(di); | 829 | i2c_set_clientdata(client, di); |
826 | if (retval) | 830 | |
831 | /* Let's see whether this adapter can support what we need. */ | ||
832 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
833 | dev_err(&client->dev, "insufficient functionality!\n"); | ||
834 | retval = -ENODEV; | ||
827 | goto batt_failed_3; | 835 | goto batt_failed_3; |
836 | } | ||
828 | 837 | ||
829 | i2c_set_clientdata(client, di); | 838 | read_data = bq27x00_read(di, BQ27x00_REG_FLAGS, false); |
839 | |||
840 | if (!(read_data & BQ27500_FLAG_BAT_DET)) { | ||
841 | dev_err(&client->dev, "no battery present\n"); | ||
842 | retval = -ENODEV; | ||
843 | goto batt_failed_3; | ||
844 | } | ||
845 | |||
846 | retval = bq27x00_powersupply_init(di); | ||
847 | if (retval < 0) | ||
848 | goto batt_failed_3; | ||
830 | 849 | ||
831 | return 0; | 850 | return 0; |
832 | 851 | ||
@@ -859,21 +878,76 @@ static int bq27x00_battery_remove(struct i2c_client *client) | |||
859 | return 0; | 878 | return 0; |
860 | } | 879 | } |
861 | 880 | ||
881 | #ifdef CONFIG_PM | ||
882 | static int bq27x00_battery_suspend(struct device *dev) | ||
883 | { | ||
884 | int ret; | ||
885 | struct platform_device *pdev = to_platform_device(dev); | ||
886 | struct bq27x00_device_info *di = platform_get_drvdata(pdev); | ||
887 | |||
888 | if (di->chip == BQ27510) { | ||
889 | ret = bq27x00_write(di, BQ27510_CNTL, | ||
890 | BQ27510_CNTL_SET_SLEEP, false); | ||
891 | if (ret < 0) { | ||
892 | dev_err(di->dev, "write failure\n"); | ||
893 | return ret; | ||
894 | } | ||
895 | ret = bq27x00_write(di, BQ27510_CNTL, 0x01, false); | ||
896 | if (ret < 0) { | ||
897 | dev_err(di->dev, "write failure\n"); | ||
898 | return ret; | ||
899 | } | ||
900 | } | ||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | static int bq27x00_battery_resume(struct device *dev) | ||
905 | { | ||
906 | int ret; | ||
907 | struct platform_device *pdev = to_platform_device(dev); | ||
908 | struct bq27x00_device_info *di = platform_get_drvdata(pdev); | ||
909 | |||
910 | if (di->chip == BQ27510) { | ||
911 | ret = bq27x00_write(di, BQ27510_CNTL, | ||
912 | BQ27510_CNTL_CLEAR_SLEEP, false); | ||
913 | if (ret < 0) { | ||
914 | dev_err(di->dev, "write failure\n"); | ||
915 | return ret; | ||
916 | } | ||
917 | ret = bq27x00_write(di, BQ27510_CNTL, 0x01, false); | ||
918 | if (ret < 0) { | ||
919 | dev_err(di->dev, "write failure\n"); | ||
920 | return ret; | ||
921 | } | ||
922 | } | ||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | static const struct dev_pm_ops bq27x00_battery_pm_ops = { | ||
927 | .suspend = bq27x00_battery_suspend, | ||
928 | .resume = bq27x00_battery_resume, | ||
929 | }; | ||
930 | |||
931 | #endif | ||
932 | |||
862 | static const struct i2c_device_id bq27x00_id[] = { | 933 | static const struct i2c_device_id bq27x00_id[] = { |
863 | { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */ | 934 | { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */ |
864 | { "bq27500", BQ27500 }, | 935 | { "bq27500", BQ27500 }, |
865 | { "bq27425", BQ27425 }, | 936 | { "bq27510", BQ27510 }, |
866 | {}, | 937 | {}, |
867 | }; | 938 | }; |
868 | MODULE_DEVICE_TABLE(i2c, bq27x00_id); | 939 | MODULE_DEVICE_TABLE(i2c, bq27x00_id); |
869 | 940 | ||
870 | static struct i2c_driver bq27x00_battery_driver = { | 941 | static struct i2c_driver bq27x00_battery_driver = { |
942 | .probe = bq27x00_battery_probe, | ||
943 | .remove = bq27x00_battery_remove, | ||
944 | .id_table = bq27x00_id, | ||
871 | .driver = { | 945 | .driver = { |
872 | .name = "bq27x00-battery", | 946 | .name = "bq27x00-battery", |
947 | #if defined(CONFIG_PM) | ||
948 | .pm = &bq27x00_battery_pm_ops, | ||
949 | #endif | ||
873 | }, | 950 | }, |
874 | .probe = bq27x00_battery_probe, | ||
875 | .remove = bq27x00_battery_remove, | ||
876 | .id_table = bq27x00_id, | ||
877 | }; | 951 | }; |
878 | 952 | ||
879 | static inline int bq27x00_battery_i2c_init(void) | 953 | static inline int bq27x00_battery_i2c_init(void) |
@@ -934,7 +1008,7 @@ static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg, | |||
934 | return pdata->read(dev, reg); | 1008 | return pdata->read(dev, reg); |
935 | } | 1009 | } |
936 | 1010 | ||
937 | static int bq27000_battery_probe(struct platform_device *pdev) | 1011 | static int __devinit bq27000_battery_probe(struct platform_device *pdev) |
938 | { | 1012 | { |
939 | struct bq27x00_device_info *di; | 1013 | struct bq27x00_device_info *di; |
940 | struct bq27000_platform_data *pdata = pdev->dev.platform_data; | 1014 | struct bq27000_platform_data *pdata = pdev->dev.platform_data; |
@@ -977,7 +1051,7 @@ err_free: | |||
977 | return ret; | 1051 | return ret; |
978 | } | 1052 | } |
979 | 1053 | ||
980 | static int bq27000_battery_remove(struct platform_device *pdev) | 1054 | static int __devexit bq27000_battery_remove(struct platform_device *pdev) |
981 | { | 1055 | { |
982 | struct bq27x00_device_info *di = platform_get_drvdata(pdev); | 1056 | struct bq27x00_device_info *di = platform_get_drvdata(pdev); |
983 | 1057 | ||
@@ -991,7 +1065,7 @@ static int bq27000_battery_remove(struct platform_device *pdev) | |||
991 | 1065 | ||
992 | static struct platform_driver bq27000_battery_driver = { | 1066 | static struct platform_driver bq27000_battery_driver = { |
993 | .probe = bq27000_battery_probe, | 1067 | .probe = bq27000_battery_probe, |
994 | .remove = bq27000_battery_remove, | 1068 | .remove = __devexit_p(bq27000_battery_remove), |
995 | .driver = { | 1069 | .driver = { |
996 | .name = "bq27000-battery", | 1070 | .name = "bq27000-battery", |
997 | .owner = THIS_MODULE, | 1071 | .owner = THIS_MODULE, |
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c deleted file mode 100644 index 6ba047f5ac2..00000000000 --- a/drivers/power/charger-manager.c +++ /dev/null | |||
@@ -1,1902 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
3 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
4 | * | ||
5 | * This driver enables to monitor battery health and control charger | ||
6 | * during suspend-to-mem. | ||
7 | * Charger manager depends on other devices. register this later than | ||
8 | * the depending devices. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | **/ | ||
14 | |||
15 | #include <linux/io.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/power/charger-manager.h> | ||
24 | #include <linux/regulator/consumer.h> | ||
25 | #include <linux/sysfs.h> | ||
26 | |||
27 | static const char * const default_event_names[] = { | ||
28 | [CM_EVENT_UNKNOWN] = "Unknown", | ||
29 | [CM_EVENT_BATT_FULL] = "Battery Full", | ||
30 | [CM_EVENT_BATT_IN] = "Battery Inserted", | ||
31 | [CM_EVENT_BATT_OUT] = "Battery Pulled Out", | ||
32 | [CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach", | ||
33 | [CM_EVENT_CHG_START_STOP] = "Charging Start/Stop", | ||
34 | [CM_EVENT_OTHERS] = "Other battery events" | ||
35 | }; | ||
36 | |||
37 | /* | ||
38 | * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for | ||
39 | * delayed works so that we can run delayed works with CM_JIFFIES_SMALL | ||
40 | * without any delays. | ||
41 | */ | ||
42 | #define CM_JIFFIES_SMALL (2) | ||
43 | |||
44 | /* If y is valid (> 0) and smaller than x, do x = y */ | ||
45 | #define CM_MIN_VALID(x, y) x = (((y > 0) && ((x) > (y))) ? (y) : (x)) | ||
46 | |||
47 | /* | ||
48 | * Regard CM_RTC_SMALL (sec) is small enough to ignore error in invoking | ||
49 | * rtc alarm. It should be 2 or larger | ||
50 | */ | ||
51 | #define CM_RTC_SMALL (2) | ||
52 | |||
53 | #define UEVENT_BUF_SIZE 32 | ||
54 | |||
55 | static LIST_HEAD(cm_list); | ||
56 | static DEFINE_MUTEX(cm_list_mtx); | ||
57 | |||
58 | /* About in-suspend (suspend-again) monitoring */ | ||
59 | static struct rtc_device *rtc_dev; | ||
60 | /* | ||
61 | * Backup RTC alarm | ||
62 | * Save the wakeup alarm before entering suspend-to-RAM | ||
63 | */ | ||
64 | static struct rtc_wkalrm rtc_wkalarm_save; | ||
65 | /* Backup RTC alarm time in terms of seconds since 01-01-1970 00:00:00 */ | ||
66 | static unsigned long rtc_wkalarm_save_time; | ||
67 | static bool cm_suspended; | ||
68 | static bool cm_rtc_set; | ||
69 | static unsigned long cm_suspend_duration_ms; | ||
70 | |||
71 | /* About normal (not suspended) monitoring */ | ||
72 | static unsigned long polling_jiffy = ULONG_MAX; /* ULONG_MAX: no polling */ | ||
73 | static unsigned long next_polling; /* Next appointed polling time */ | ||
74 | static struct workqueue_struct *cm_wq; /* init at driver add */ | ||
75 | static struct delayed_work cm_monitor_work; /* init at driver add */ | ||
76 | |||
77 | /* Global charger-manager description */ | ||
78 | static struct charger_global_desc *g_desc; /* init with setup_charger_manager */ | ||
79 | |||
80 | /** | ||
81 | * is_batt_present - See if the battery presents in place. | ||
82 | * @cm: the Charger Manager representing the battery. | ||
83 | */ | ||
84 | static bool is_batt_present(struct charger_manager *cm) | ||
85 | { | ||
86 | union power_supply_propval val; | ||
87 | bool present = false; | ||
88 | int i, ret; | ||
89 | |||
90 | switch (cm->desc->battery_present) { | ||
91 | case CM_BATTERY_PRESENT: | ||
92 | present = true; | ||
93 | break; | ||
94 | case CM_NO_BATTERY: | ||
95 | break; | ||
96 | case CM_FUEL_GAUGE: | ||
97 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, | ||
98 | POWER_SUPPLY_PROP_PRESENT, &val); | ||
99 | if (ret == 0 && val.intval) | ||
100 | present = true; | ||
101 | break; | ||
102 | case CM_CHARGER_STAT: | ||
103 | for (i = 0; cm->charger_stat[i]; i++) { | ||
104 | ret = cm->charger_stat[i]->get_property( | ||
105 | cm->charger_stat[i], | ||
106 | POWER_SUPPLY_PROP_PRESENT, &val); | ||
107 | if (ret == 0 && val.intval) { | ||
108 | present = true; | ||
109 | break; | ||
110 | } | ||
111 | } | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | return present; | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * is_ext_pwr_online - See if an external power source is attached to charge | ||
120 | * @cm: the Charger Manager representing the battery. | ||
121 | * | ||
122 | * Returns true if at least one of the chargers of the battery has an external | ||
123 | * power source attached to charge the battery regardless of whether it is | ||
124 | * actually charging or not. | ||
125 | */ | ||
126 | static bool is_ext_pwr_online(struct charger_manager *cm) | ||
127 | { | ||
128 | union power_supply_propval val; | ||
129 | bool online = false; | ||
130 | int i, ret; | ||
131 | |||
132 | /* If at least one of them has one, it's yes. */ | ||
133 | for (i = 0; cm->charger_stat[i]; i++) { | ||
134 | ret = cm->charger_stat[i]->get_property( | ||
135 | cm->charger_stat[i], | ||
136 | POWER_SUPPLY_PROP_ONLINE, &val); | ||
137 | if (ret == 0 && val.intval) { | ||
138 | online = true; | ||
139 | break; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | return online; | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * get_batt_uV - Get the voltage level of the battery | ||
148 | * @cm: the Charger Manager representing the battery. | ||
149 | * @uV: the voltage level returned. | ||
150 | * | ||
151 | * Returns 0 if there is no error. | ||
152 | * Returns a negative value on error. | ||
153 | */ | ||
154 | static int get_batt_uV(struct charger_manager *cm, int *uV) | ||
155 | { | ||
156 | union power_supply_propval val; | ||
157 | int ret; | ||
158 | |||
159 | if (!cm->fuel_gauge) | ||
160 | return -ENODEV; | ||
161 | |||
162 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, | ||
163 | POWER_SUPPLY_PROP_VOLTAGE_NOW, &val); | ||
164 | if (ret) | ||
165 | return ret; | ||
166 | |||
167 | *uV = val.intval; | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * is_charging - Returns true if the battery is being charged. | ||
173 | * @cm: the Charger Manager representing the battery. | ||
174 | */ | ||
175 | static bool is_charging(struct charger_manager *cm) | ||
176 | { | ||
177 | int i, ret; | ||
178 | bool charging = false; | ||
179 | union power_supply_propval val; | ||
180 | |||
181 | /* If there is no battery, it cannot be charged */ | ||
182 | if (!is_batt_present(cm)) | ||
183 | return false; | ||
184 | |||
185 | /* If at least one of the charger is charging, return yes */ | ||
186 | for (i = 0; cm->charger_stat[i]; i++) { | ||
187 | /* 1. The charger sholuld not be DISABLED */ | ||
188 | if (cm->emergency_stop) | ||
189 | continue; | ||
190 | if (!cm->charger_enabled) | ||
191 | continue; | ||
192 | |||
193 | /* 2. The charger should be online (ext-power) */ | ||
194 | ret = cm->charger_stat[i]->get_property( | ||
195 | cm->charger_stat[i], | ||
196 | POWER_SUPPLY_PROP_ONLINE, &val); | ||
197 | if (ret) { | ||
198 | dev_warn(cm->dev, "Cannot read ONLINE value from %s.\n", | ||
199 | cm->desc->psy_charger_stat[i]); | ||
200 | continue; | ||
201 | } | ||
202 | if (val.intval == 0) | ||
203 | continue; | ||
204 | |||
205 | /* | ||
206 | * 3. The charger should not be FULL, DISCHARGING, | ||
207 | * or NOT_CHARGING. | ||
208 | */ | ||
209 | ret = cm->charger_stat[i]->get_property( | ||
210 | cm->charger_stat[i], | ||
211 | POWER_SUPPLY_PROP_STATUS, &val); | ||
212 | if (ret) { | ||
213 | dev_warn(cm->dev, "Cannot read STATUS value from %s.\n", | ||
214 | cm->desc->psy_charger_stat[i]); | ||
215 | continue; | ||
216 | } | ||
217 | if (val.intval == POWER_SUPPLY_STATUS_FULL || | ||
218 | val.intval == POWER_SUPPLY_STATUS_DISCHARGING || | ||
219 | val.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) | ||
220 | continue; | ||
221 | |||
222 | /* Then, this is charging. */ | ||
223 | charging = true; | ||
224 | break; | ||
225 | } | ||
226 | |||
227 | return charging; | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * is_full_charged - Returns true if the battery is fully charged. | ||
232 | * @cm: the Charger Manager representing the battery. | ||
233 | */ | ||
234 | static bool is_full_charged(struct charger_manager *cm) | ||
235 | { | ||
236 | struct charger_desc *desc = cm->desc; | ||
237 | union power_supply_propval val; | ||
238 | int ret = 0; | ||
239 | int uV; | ||
240 | |||
241 | /* If there is no battery, it cannot be charged */ | ||
242 | if (!is_batt_present(cm)) | ||
243 | return false; | ||
244 | |||
245 | if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) { | ||
246 | val.intval = 0; | ||
247 | |||
248 | /* Not full if capacity of fuel gauge isn't full */ | ||
249 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, | ||
250 | POWER_SUPPLY_PROP_CHARGE_FULL, &val); | ||
251 | if (!ret && val.intval > desc->fullbatt_full_capacity) | ||
252 | return true; | ||
253 | } | ||
254 | |||
255 | /* Full, if it's over the fullbatt voltage */ | ||
256 | if (desc->fullbatt_uV > 0) { | ||
257 | ret = get_batt_uV(cm, &uV); | ||
258 | if (!ret && uV >= desc->fullbatt_uV) | ||
259 | return true; | ||
260 | } | ||
261 | |||
262 | /* Full, if the capacity is more than fullbatt_soc */ | ||
263 | if (cm->fuel_gauge && desc->fullbatt_soc > 0) { | ||
264 | val.intval = 0; | ||
265 | |||
266 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, | ||
267 | POWER_SUPPLY_PROP_CAPACITY, &val); | ||
268 | if (!ret && val.intval >= desc->fullbatt_soc) | ||
269 | return true; | ||
270 | } | ||
271 | |||
272 | return false; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * is_polling_required - Return true if need to continue polling for this CM. | ||
277 | * @cm: the Charger Manager representing the battery. | ||
278 | */ | ||
279 | static bool is_polling_required(struct charger_manager *cm) | ||
280 | { | ||
281 | switch (cm->desc->polling_mode) { | ||
282 | case CM_POLL_DISABLE: | ||
283 | return false; | ||
284 | case CM_POLL_ALWAYS: | ||
285 | return true; | ||
286 | case CM_POLL_EXTERNAL_POWER_ONLY: | ||
287 | return is_ext_pwr_online(cm); | ||
288 | case CM_POLL_CHARGING_ONLY: | ||
289 | return is_charging(cm); | ||
290 | default: | ||
291 | dev_warn(cm->dev, "Incorrect polling_mode (%d)\n", | ||
292 | cm->desc->polling_mode); | ||
293 | } | ||
294 | |||
295 | return false; | ||
296 | } | ||
297 | |||
298 | /** | ||
299 | * try_charger_enable - Enable/Disable chargers altogether | ||
300 | * @cm: the Charger Manager representing the battery. | ||
301 | * @enable: true: enable / false: disable | ||
302 | * | ||
303 | * Note that Charger Manager keeps the charger enabled regardless whether | ||
304 | * the charger is charging or not (because battery is full or no external | ||
305 | * power source exists) except when CM needs to disable chargers forcibly | ||
306 | * bacause of emergency causes; when the battery is overheated or too cold. | ||
307 | */ | ||
308 | static int try_charger_enable(struct charger_manager *cm, bool enable) | ||
309 | { | ||
310 | int err = 0, i; | ||
311 | struct charger_desc *desc = cm->desc; | ||
312 | |||
313 | /* Ignore if it's redundent command */ | ||
314 | if (enable == cm->charger_enabled) | ||
315 | return 0; | ||
316 | |||
317 | if (enable) { | ||
318 | if (cm->emergency_stop) | ||
319 | return -EAGAIN; | ||
320 | |||
321 | /* | ||
322 | * Save start time of charging to limit | ||
323 | * maximum possible charging time. | ||
324 | */ | ||
325 | cm->charging_start_time = ktime_to_ms(ktime_get()); | ||
326 | cm->charging_end_time = 0; | ||
327 | |||
328 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | ||
329 | if (desc->charger_regulators[i].externally_control) | ||
330 | continue; | ||
331 | |||
332 | err = regulator_enable(desc->charger_regulators[i].consumer); | ||
333 | if (err < 0) { | ||
334 | dev_warn(cm->dev, | ||
335 | "Cannot enable %s regulator\n", | ||
336 | desc->charger_regulators[i].regulator_name); | ||
337 | } | ||
338 | } | ||
339 | } else { | ||
340 | /* | ||
341 | * Save end time of charging to maintain fully charged state | ||
342 | * of battery after full-batt. | ||
343 | */ | ||
344 | cm->charging_start_time = 0; | ||
345 | cm->charging_end_time = ktime_to_ms(ktime_get()); | ||
346 | |||
347 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | ||
348 | if (desc->charger_regulators[i].externally_control) | ||
349 | continue; | ||
350 | |||
351 | err = regulator_disable(desc->charger_regulators[i].consumer); | ||
352 | if (err < 0) { | ||
353 | dev_warn(cm->dev, | ||
354 | "Cannot disable %s regulator\n", | ||
355 | desc->charger_regulators[i].regulator_name); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * Abnormal battery state - Stop charging forcibly, | ||
361 | * even if charger was enabled at the other places | ||
362 | */ | ||
363 | for (i = 0; i < desc->num_charger_regulators; i++) { | ||
364 | if (regulator_is_enabled( | ||
365 | desc->charger_regulators[i].consumer)) { | ||
366 | regulator_force_disable( | ||
367 | desc->charger_regulators[i].consumer); | ||
368 | dev_warn(cm->dev, | ||
369 | "Disable regulator(%s) forcibly.\n", | ||
370 | desc->charger_regulators[i].regulator_name); | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | |||
375 | if (!err) | ||
376 | cm->charger_enabled = enable; | ||
377 | |||
378 | return err; | ||
379 | } | ||
380 | |||
381 | /** | ||
382 | * try_charger_restart - Restart charging. | ||
383 | * @cm: the Charger Manager representing the battery. | ||
384 | * | ||
385 | * Restart charging by turning off and on the charger. | ||
386 | */ | ||
387 | static int try_charger_restart(struct charger_manager *cm) | ||
388 | { | ||
389 | int err; | ||
390 | |||
391 | if (cm->emergency_stop) | ||
392 | return -EAGAIN; | ||
393 | |||
394 | err = try_charger_enable(cm, false); | ||
395 | if (err) | ||
396 | return err; | ||
397 | |||
398 | return try_charger_enable(cm, true); | ||
399 | } | ||
400 | |||
401 | /** | ||
402 | * uevent_notify - Let users know something has changed. | ||
403 | * @cm: the Charger Manager representing the battery. | ||
404 | * @event: the event string. | ||
405 | * | ||
406 | * If @event is null, it implies that uevent_notify is called | ||
407 | * by resume function. When called in the resume function, cm_suspended | ||
408 | * should be already reset to false in order to let uevent_notify | ||
409 | * notify the recent event during the suspend to users. While | ||
410 | * suspended, uevent_notify does not notify users, but tracks | ||
411 | * events so that uevent_notify can notify users later after resumed. | ||
412 | */ | ||
413 | static void uevent_notify(struct charger_manager *cm, const char *event) | ||
414 | { | ||
415 | static char env_str[UEVENT_BUF_SIZE + 1] = ""; | ||
416 | static char env_str_save[UEVENT_BUF_SIZE + 1] = ""; | ||
417 | |||
418 | if (cm_suspended) { | ||
419 | /* Nothing in suspended-event buffer */ | ||
420 | if (env_str_save[0] == 0) { | ||
421 | if (!strncmp(env_str, event, UEVENT_BUF_SIZE)) | ||
422 | return; /* status not changed */ | ||
423 | strncpy(env_str_save, event, UEVENT_BUF_SIZE); | ||
424 | return; | ||
425 | } | ||
426 | |||
427 | if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE)) | ||
428 | return; /* Duplicated. */ | ||
429 | strncpy(env_str_save, event, UEVENT_BUF_SIZE); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | if (event == NULL) { | ||
434 | /* No messages pending */ | ||
435 | if (!env_str_save[0]) | ||
436 | return; | ||
437 | |||
438 | strncpy(env_str, env_str_save, UEVENT_BUF_SIZE); | ||
439 | kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE); | ||
440 | env_str_save[0] = 0; | ||
441 | |||
442 | return; | ||
443 | } | ||
444 | |||
445 | /* status not changed */ | ||
446 | if (!strncmp(env_str, event, UEVENT_BUF_SIZE)) | ||
447 | return; | ||
448 | |||
449 | /* save the status and notify the update */ | ||
450 | strncpy(env_str, event, UEVENT_BUF_SIZE); | ||
451 | kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE); | ||
452 | |||
453 | dev_info(cm->dev, event); | ||
454 | } | ||
455 | |||
456 | /** | ||
457 | * fullbatt_vchk - Check voltage drop some times after "FULL" event. | ||
458 | * @work: the work_struct appointing the function | ||
459 | * | ||
460 | * If a user has designated "fullbatt_vchkdrop_ms/uV" values with | ||
461 | * charger_desc, Charger Manager checks voltage drop after the battery | ||
462 | * "FULL" event. It checks whether the voltage has dropped more than | ||
463 | * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms. | ||
464 | */ | ||
465 | static void fullbatt_vchk(struct work_struct *work) | ||
466 | { | ||
467 | struct delayed_work *dwork = to_delayed_work(work); | ||
468 | struct charger_manager *cm = container_of(dwork, | ||
469 | struct charger_manager, fullbatt_vchk_work); | ||
470 | struct charger_desc *desc = cm->desc; | ||
471 | int batt_uV, err, diff; | ||
472 | |||
473 | /* remove the appointment for fullbatt_vchk */ | ||
474 | cm->fullbatt_vchk_jiffies_at = 0; | ||
475 | |||
476 | if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms) | ||
477 | return; | ||
478 | |||
479 | err = get_batt_uV(cm, &batt_uV); | ||
480 | if (err) { | ||
481 | dev_err(cm->dev, "%s: get_batt_uV error(%d).\n", __func__, err); | ||
482 | return; | ||
483 | } | ||
484 | |||
485 | diff = desc->fullbatt_uV - batt_uV; | ||
486 | if (diff < 0) | ||
487 | return; | ||
488 | |||
489 | dev_info(cm->dev, "VBATT dropped %duV after full-batt.\n", diff); | ||
490 | |||
491 | if (diff > desc->fullbatt_vchkdrop_uV) { | ||
492 | try_charger_restart(cm); | ||
493 | uevent_notify(cm, "Recharging"); | ||
494 | } | ||
495 | } | ||
496 | |||
497 | /** | ||
498 | * check_charging_duration - Monitor charging/discharging duration | ||
499 | * @cm: the Charger Manager representing the battery. | ||
500 | * | ||
501 | * If whole charging duration exceed 'charging_max_duration_ms', | ||
502 | * cm stop charging to prevent overcharge/overheat. If discharging | ||
503 | * duration exceed 'discharging _max_duration_ms', charger cable is | ||
504 | * attached, after full-batt, cm start charging to maintain fully | ||
505 | * charged state for battery. | ||
506 | */ | ||
507 | static int check_charging_duration(struct charger_manager *cm) | ||
508 | { | ||
509 | struct charger_desc *desc = cm->desc; | ||
510 | u64 curr = ktime_to_ms(ktime_get()); | ||
511 | u64 duration; | ||
512 | int ret = false; | ||
513 | |||
514 | if (!desc->charging_max_duration_ms && | ||
515 | !desc->discharging_max_duration_ms) | ||
516 | return ret; | ||
517 | |||
518 | if (cm->charger_enabled) { | ||
519 | duration = curr - cm->charging_start_time; | ||
520 | |||
521 | if (duration > desc->charging_max_duration_ms) { | ||
522 | dev_info(cm->dev, "Charging duration exceed %lldms", | ||
523 | desc->charging_max_duration_ms); | ||
524 | uevent_notify(cm, "Discharging"); | ||
525 | try_charger_enable(cm, false); | ||
526 | ret = true; | ||
527 | } | ||
528 | } else if (is_ext_pwr_online(cm) && !cm->charger_enabled) { | ||
529 | duration = curr - cm->charging_end_time; | ||
530 | |||
531 | if (duration > desc->charging_max_duration_ms && | ||
532 | is_ext_pwr_online(cm)) { | ||
533 | dev_info(cm->dev, "DisCharging duration exceed %lldms", | ||
534 | desc->discharging_max_duration_ms); | ||
535 | uevent_notify(cm, "Recharing"); | ||
536 | try_charger_enable(cm, true); | ||
537 | ret = true; | ||
538 | } | ||
539 | } | ||
540 | |||
541 | return ret; | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * _cm_monitor - Monitor the temperature and return true for exceptions. | ||
546 | * @cm: the Charger Manager representing the battery. | ||
547 | * | ||
548 | * Returns true if there is an event to notify for the battery. | ||
549 | * (True if the status of "emergency_stop" changes) | ||
550 | */ | ||
551 | static bool _cm_monitor(struct charger_manager *cm) | ||
552 | { | ||
553 | struct charger_desc *desc = cm->desc; | ||
554 | int temp = desc->temperature_out_of_range(&cm->last_temp_mC); | ||
555 | |||
556 | dev_dbg(cm->dev, "monitoring (%2.2d.%3.3dC)\n", | ||
557 | cm->last_temp_mC / 1000, cm->last_temp_mC % 1000); | ||
558 | |||
559 | /* It has been stopped already */ | ||
560 | if (temp && cm->emergency_stop) | ||
561 | return false; | ||
562 | |||
563 | /* | ||
564 | * Check temperature whether overheat or cold. | ||
565 | * If temperature is out of range normal state, stop charging. | ||
566 | */ | ||
567 | if (temp) { | ||
568 | cm->emergency_stop = temp; | ||
569 | if (!try_charger_enable(cm, false)) { | ||
570 | if (temp > 0) | ||
571 | uevent_notify(cm, "OVERHEAT"); | ||
572 | else | ||
573 | uevent_notify(cm, "COLD"); | ||
574 | } | ||
575 | |||
576 | /* | ||
577 | * Check whole charging duration and discharing duration | ||
578 | * after full-batt. | ||
579 | */ | ||
580 | } else if (!cm->emergency_stop && check_charging_duration(cm)) { | ||
581 | dev_dbg(cm->dev, | ||
582 | "Charging/Discharging duration is out of range"); | ||
583 | /* | ||
584 | * Check dropped voltage of battery. If battery voltage is more | ||
585 | * dropped than fullbatt_vchkdrop_uV after fully charged state, | ||
586 | * charger-manager have to recharge battery. | ||
587 | */ | ||
588 | } else if (!cm->emergency_stop && is_ext_pwr_online(cm) && | ||
589 | !cm->charger_enabled) { | ||
590 | fullbatt_vchk(&cm->fullbatt_vchk_work.work); | ||
591 | |||
592 | /* | ||
593 | * Check whether fully charged state to protect overcharge | ||
594 | * if charger-manager is charging for battery. | ||
595 | */ | ||
596 | } else if (!cm->emergency_stop && is_full_charged(cm) && | ||
597 | cm->charger_enabled) { | ||
598 | dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged.\n"); | ||
599 | uevent_notify(cm, default_event_names[CM_EVENT_BATT_FULL]); | ||
600 | |||
601 | try_charger_enable(cm, false); | ||
602 | |||
603 | fullbatt_vchk(&cm->fullbatt_vchk_work.work); | ||
604 | } else { | ||
605 | cm->emergency_stop = 0; | ||
606 | if (is_ext_pwr_online(cm)) { | ||
607 | if (!try_charger_enable(cm, true)) | ||
608 | uevent_notify(cm, "CHARGING"); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | return true; | ||
613 | } | ||
614 | |||
615 | /** | ||
616 | * cm_monitor - Monitor every battery. | ||
617 | * | ||
618 | * Returns true if there is an event to notify from any of the batteries. | ||
619 | * (True if the status of "emergency_stop" changes) | ||
620 | */ | ||
621 | static bool cm_monitor(void) | ||
622 | { | ||
623 | bool stop = false; | ||
624 | struct charger_manager *cm; | ||
625 | |||
626 | mutex_lock(&cm_list_mtx); | ||
627 | |||
628 | list_for_each_entry(cm, &cm_list, entry) { | ||
629 | if (_cm_monitor(cm)) | ||
630 | stop = true; | ||
631 | } | ||
632 | |||
633 | mutex_unlock(&cm_list_mtx); | ||
634 | |||
635 | return stop; | ||
636 | } | ||
637 | |||
638 | /** | ||
639 | * _setup_polling - Setup the next instance of polling. | ||
640 | * @work: work_struct of the function _setup_polling. | ||
641 | */ | ||
642 | static void _setup_polling(struct work_struct *work) | ||
643 | { | ||
644 | unsigned long min = ULONG_MAX; | ||
645 | struct charger_manager *cm; | ||
646 | bool keep_polling = false; | ||
647 | unsigned long _next_polling; | ||
648 | |||
649 | mutex_lock(&cm_list_mtx); | ||
650 | |||
651 | list_for_each_entry(cm, &cm_list, entry) { | ||
652 | if (is_polling_required(cm) && cm->desc->polling_interval_ms) { | ||
653 | keep_polling = true; | ||
654 | |||
655 | if (min > cm->desc->polling_interval_ms) | ||
656 | min = cm->desc->polling_interval_ms; | ||
657 | } | ||
658 | } | ||
659 | |||
660 | polling_jiffy = msecs_to_jiffies(min); | ||
661 | if (polling_jiffy <= CM_JIFFIES_SMALL) | ||
662 | polling_jiffy = CM_JIFFIES_SMALL + 1; | ||
663 | |||
664 | if (!keep_polling) | ||
665 | polling_jiffy = ULONG_MAX; | ||
666 | if (polling_jiffy == ULONG_MAX) | ||
667 | goto out; | ||
668 | |||
669 | WARN(cm_wq == NULL, "charger-manager: workqueue not initialized" | ||
670 | ". try it later. %s\n", __func__); | ||
671 | |||
672 | _next_polling = jiffies + polling_jiffy; | ||
673 | |||
674 | if (!delayed_work_pending(&cm_monitor_work) || | ||
675 | (delayed_work_pending(&cm_monitor_work) && | ||
676 | time_after(next_polling, _next_polling))) { | ||
677 | next_polling = jiffies + polling_jiffy; | ||
678 | mod_delayed_work(cm_wq, &cm_monitor_work, polling_jiffy); | ||
679 | } | ||
680 | |||
681 | out: | ||
682 | mutex_unlock(&cm_list_mtx); | ||
683 | } | ||
684 | static DECLARE_WORK(setup_polling, _setup_polling); | ||
685 | |||
686 | /** | ||
687 | * cm_monitor_poller - The Monitor / Poller. | ||
688 | * @work: work_struct of the function cm_monitor_poller | ||
689 | * | ||
690 | * During non-suspended state, cm_monitor_poller is used to poll and monitor | ||
691 | * the batteries. | ||
692 | */ | ||
693 | static void cm_monitor_poller(struct work_struct *work) | ||
694 | { | ||
695 | cm_monitor(); | ||
696 | schedule_work(&setup_polling); | ||
697 | } | ||
698 | |||
699 | /** | ||
700 | * fullbatt_handler - Event handler for CM_EVENT_BATT_FULL | ||
701 | * @cm: the Charger Manager representing the battery. | ||
702 | */ | ||
703 | static void fullbatt_handler(struct charger_manager *cm) | ||
704 | { | ||
705 | struct charger_desc *desc = cm->desc; | ||
706 | |||
707 | if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms) | ||
708 | goto out; | ||
709 | |||
710 | if (cm_suspended) | ||
711 | device_set_wakeup_capable(cm->dev, true); | ||
712 | |||
713 | mod_delayed_work(cm_wq, &cm->fullbatt_vchk_work, | ||
714 | msecs_to_jiffies(desc->fullbatt_vchkdrop_ms)); | ||
715 | cm->fullbatt_vchk_jiffies_at = jiffies + msecs_to_jiffies( | ||
716 | desc->fullbatt_vchkdrop_ms); | ||
717 | |||
718 | if (cm->fullbatt_vchk_jiffies_at == 0) | ||
719 | cm->fullbatt_vchk_jiffies_at = 1; | ||
720 | |||
721 | out: | ||
722 | dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged.\n"); | ||
723 | uevent_notify(cm, default_event_names[CM_EVENT_BATT_FULL]); | ||
724 | } | ||
725 | |||
726 | /** | ||
727 | * battout_handler - Event handler for CM_EVENT_BATT_OUT | ||
728 | * @cm: the Charger Manager representing the battery. | ||
729 | */ | ||
730 | static void battout_handler(struct charger_manager *cm) | ||
731 | { | ||
732 | if (cm_suspended) | ||
733 | device_set_wakeup_capable(cm->dev, true); | ||
734 | |||
735 | if (!is_batt_present(cm)) { | ||
736 | dev_emerg(cm->dev, "Battery Pulled Out!\n"); | ||
737 | uevent_notify(cm, default_event_names[CM_EVENT_BATT_OUT]); | ||
738 | } else { | ||
739 | uevent_notify(cm, "Battery Reinserted?"); | ||
740 | } | ||
741 | } | ||
742 | |||
743 | /** | ||
744 | * misc_event_handler - Handler for other evnets | ||
745 | * @cm: the Charger Manager representing the battery. | ||
746 | * @type: the Charger Manager representing the battery. | ||
747 | */ | ||
748 | static void misc_event_handler(struct charger_manager *cm, | ||
749 | enum cm_event_types type) | ||
750 | { | ||
751 | if (cm_suspended) | ||
752 | device_set_wakeup_capable(cm->dev, true); | ||
753 | |||
754 | if (!delayed_work_pending(&cm_monitor_work) && | ||
755 | is_polling_required(cm) && cm->desc->polling_interval_ms) | ||
756 | schedule_work(&setup_polling); | ||
757 | uevent_notify(cm, default_event_names[type]); | ||
758 | } | ||
759 | |||
760 | static int charger_get_property(struct power_supply *psy, | ||
761 | enum power_supply_property psp, | ||
762 | union power_supply_propval *val) | ||
763 | { | ||
764 | struct charger_manager *cm = container_of(psy, | ||
765 | struct charger_manager, charger_psy); | ||
766 | struct charger_desc *desc = cm->desc; | ||
767 | int ret = 0; | ||
768 | int uV; | ||
769 | |||
770 | switch (psp) { | ||
771 | case POWER_SUPPLY_PROP_STATUS: | ||
772 | if (is_charging(cm)) | ||
773 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
774 | else if (is_ext_pwr_online(cm)) | ||
775 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
776 | else | ||
777 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
778 | break; | ||
779 | case POWER_SUPPLY_PROP_HEALTH: | ||
780 | if (cm->emergency_stop > 0) | ||
781 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
782 | else if (cm->emergency_stop < 0) | ||
783 | val->intval = POWER_SUPPLY_HEALTH_COLD; | ||
784 | else | ||
785 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
786 | break; | ||
787 | case POWER_SUPPLY_PROP_PRESENT: | ||
788 | if (is_batt_present(cm)) | ||
789 | val->intval = 1; | ||
790 | else | ||
791 | val->intval = 0; | ||
792 | break; | ||
793 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
794 | ret = get_batt_uV(cm, &val->intval); | ||
795 | break; | ||
796 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
797 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, | ||
798 | POWER_SUPPLY_PROP_CURRENT_NOW, val); | ||
799 | break; | ||
800 | case POWER_SUPPLY_PROP_TEMP: | ||
801 | /* in thenth of centigrade */ | ||
802 | if (cm->last_temp_mC == INT_MIN) | ||
803 | desc->temperature_out_of_range(&cm->last_temp_mC); | ||
804 | val->intval = cm->last_temp_mC / 100; | ||
805 | if (!desc->measure_battery_temp) | ||
806 | ret = -ENODEV; | ||
807 | break; | ||
808 | case POWER_SUPPLY_PROP_TEMP_AMBIENT: | ||
809 | /* in thenth of centigrade */ | ||
810 | if (cm->last_temp_mC == INT_MIN) | ||
811 | desc->temperature_out_of_range(&cm->last_temp_mC); | ||
812 | val->intval = cm->last_temp_mC / 100; | ||
813 | if (desc->measure_battery_temp) | ||
814 | ret = -ENODEV; | ||
815 | break; | ||
816 | case POWER_SUPPLY_PROP_CAPACITY: | ||
817 | if (!cm->fuel_gauge) { | ||
818 | ret = -ENODEV; | ||
819 | break; | ||
820 | } | ||
821 | |||
822 | if (!is_batt_present(cm)) { | ||
823 | /* There is no battery. Assume 100% */ | ||
824 | val->intval = 100; | ||
825 | break; | ||
826 | } | ||
827 | |||
828 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, | ||
829 | POWER_SUPPLY_PROP_CAPACITY, val); | ||
830 | if (ret) | ||
831 | break; | ||
832 | |||
833 | if (val->intval > 100) { | ||
834 | val->intval = 100; | ||
835 | break; | ||
836 | } | ||
837 | if (val->intval < 0) | ||
838 | val->intval = 0; | ||
839 | |||
840 | /* Do not adjust SOC when charging: voltage is overrated */ | ||
841 | if (is_charging(cm)) | ||
842 | break; | ||
843 | |||
844 | /* | ||
845 | * If the capacity value is inconsistent, calibrate it base on | ||
846 | * the battery voltage values and the thresholds given as desc | ||
847 | */ | ||
848 | ret = get_batt_uV(cm, &uV); | ||
849 | if (ret) { | ||
850 | /* Voltage information not available. No calibration */ | ||
851 | ret = 0; | ||
852 | break; | ||
853 | } | ||
854 | |||
855 | if (desc->fullbatt_uV > 0 && uV >= desc->fullbatt_uV && | ||
856 | !is_charging(cm)) { | ||
857 | val->intval = 100; | ||
858 | break; | ||
859 | } | ||
860 | |||
861 | break; | ||
862 | case POWER_SUPPLY_PROP_ONLINE: | ||
863 | if (is_ext_pwr_online(cm)) | ||
864 | val->intval = 1; | ||
865 | else | ||
866 | val->intval = 0; | ||
867 | break; | ||
868 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
869 | if (is_full_charged(cm)) | ||
870 | val->intval = 1; | ||
871 | else | ||
872 | val->intval = 0; | ||
873 | ret = 0; | ||
874 | break; | ||
875 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
876 | if (is_charging(cm)) { | ||
877 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, | ||
878 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
879 | val); | ||
880 | if (ret) { | ||
881 | val->intval = 1; | ||
882 | ret = 0; | ||
883 | } else { | ||
884 | /* If CHARGE_NOW is supplied, use it */ | ||
885 | val->intval = (val->intval > 0) ? | ||
886 | val->intval : 1; | ||
887 | } | ||
888 | } else { | ||
889 | val->intval = 0; | ||
890 | } | ||
891 | break; | ||
892 | default: | ||
893 | return -EINVAL; | ||
894 | } | ||
895 | return ret; | ||
896 | } | ||
897 | |||
898 | #define NUM_CHARGER_PSY_OPTIONAL (4) | ||
899 | static enum power_supply_property default_charger_props[] = { | ||
900 | /* Guaranteed to provide */ | ||
901 | POWER_SUPPLY_PROP_STATUS, | ||
902 | POWER_SUPPLY_PROP_HEALTH, | ||
903 | POWER_SUPPLY_PROP_PRESENT, | ||
904 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
905 | POWER_SUPPLY_PROP_CAPACITY, | ||
906 | POWER_SUPPLY_PROP_ONLINE, | ||
907 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
908 | /* | ||
909 | * Optional properties are: | ||
910 | * POWER_SUPPLY_PROP_CHARGE_NOW, | ||
911 | * POWER_SUPPLY_PROP_CURRENT_NOW, | ||
912 | * POWER_SUPPLY_PROP_TEMP, and | ||
913 | * POWER_SUPPLY_PROP_TEMP_AMBIENT, | ||
914 | */ | ||
915 | }; | ||
916 | |||
917 | static struct power_supply psy_default = { | ||
918 | .name = "battery", | ||
919 | .type = POWER_SUPPLY_TYPE_BATTERY, | ||
920 | .properties = default_charger_props, | ||
921 | .num_properties = ARRAY_SIZE(default_charger_props), | ||
922 | .get_property = charger_get_property, | ||
923 | }; | ||
924 | |||
925 | /** | ||
926 | * cm_setup_timer - For in-suspend monitoring setup wakeup alarm | ||
927 | * for suspend_again. | ||
928 | * | ||
929 | * Returns true if the alarm is set for Charger Manager to use. | ||
930 | * Returns false if | ||
931 | * cm_setup_timer fails to set an alarm, | ||
932 | * cm_setup_timer does not need to set an alarm for Charger Manager, | ||
933 | * or an alarm previously configured is to be used. | ||
934 | */ | ||
935 | static bool cm_setup_timer(void) | ||
936 | { | ||
937 | struct charger_manager *cm; | ||
938 | unsigned int wakeup_ms = UINT_MAX; | ||
939 | bool ret = false; | ||
940 | |||
941 | mutex_lock(&cm_list_mtx); | ||
942 | |||
943 | list_for_each_entry(cm, &cm_list, entry) { | ||
944 | unsigned int fbchk_ms = 0; | ||
945 | |||
946 | /* fullbatt_vchk is required. setup timer for that */ | ||
947 | if (cm->fullbatt_vchk_jiffies_at) { | ||
948 | fbchk_ms = jiffies_to_msecs(cm->fullbatt_vchk_jiffies_at | ||
949 | - jiffies); | ||
950 | if (time_is_before_eq_jiffies( | ||
951 | cm->fullbatt_vchk_jiffies_at) || | ||
952 | msecs_to_jiffies(fbchk_ms) < CM_JIFFIES_SMALL) { | ||
953 | fullbatt_vchk(&cm->fullbatt_vchk_work.work); | ||
954 | fbchk_ms = 0; | ||
955 | } | ||
956 | } | ||
957 | CM_MIN_VALID(wakeup_ms, fbchk_ms); | ||
958 | |||
959 | /* Skip if polling is not required for this CM */ | ||
960 | if (!is_polling_required(cm) && !cm->emergency_stop) | ||
961 | continue; | ||
962 | if (cm->desc->polling_interval_ms == 0) | ||
963 | continue; | ||
964 | CM_MIN_VALID(wakeup_ms, cm->desc->polling_interval_ms); | ||
965 | } | ||
966 | |||
967 | mutex_unlock(&cm_list_mtx); | ||
968 | |||
969 | if (wakeup_ms < UINT_MAX && wakeup_ms > 0) { | ||
970 | pr_info("Charger Manager wakeup timer: %u ms.\n", wakeup_ms); | ||
971 | if (rtc_dev) { | ||
972 | struct rtc_wkalrm tmp; | ||
973 | unsigned long time, now; | ||
974 | unsigned long add = DIV_ROUND_UP(wakeup_ms, 1000); | ||
975 | |||
976 | /* | ||
977 | * Set alarm with the polling interval (wakeup_ms) | ||
978 | * except when rtc_wkalarm_save comes first. | ||
979 | * However, the alarm time should be NOW + | ||
980 | * CM_RTC_SMALL or later. | ||
981 | */ | ||
982 | tmp.enabled = 1; | ||
983 | rtc_read_time(rtc_dev, &tmp.time); | ||
984 | rtc_tm_to_time(&tmp.time, &now); | ||
985 | if (add < CM_RTC_SMALL) | ||
986 | add = CM_RTC_SMALL; | ||
987 | time = now + add; | ||
988 | |||
989 | ret = true; | ||
990 | |||
991 | if (rtc_wkalarm_save.enabled && | ||
992 | rtc_wkalarm_save_time && | ||
993 | rtc_wkalarm_save_time < time) { | ||
994 | if (rtc_wkalarm_save_time < now + CM_RTC_SMALL) | ||
995 | time = now + CM_RTC_SMALL; | ||
996 | else | ||
997 | time = rtc_wkalarm_save_time; | ||
998 | |||
999 | /* The timer is not appointed by CM */ | ||
1000 | ret = false; | ||
1001 | } | ||
1002 | |||
1003 | pr_info("Waking up after %lu secs.\n", | ||
1004 | time - now); | ||
1005 | |||
1006 | rtc_time_to_tm(time, &tmp.time); | ||
1007 | rtc_set_alarm(rtc_dev, &tmp); | ||
1008 | cm_suspend_duration_ms += wakeup_ms; | ||
1009 | return ret; | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | if (rtc_dev) | ||
1014 | rtc_set_alarm(rtc_dev, &rtc_wkalarm_save); | ||
1015 | return false; | ||
1016 | } | ||
1017 | |||
1018 | static void _cm_fbchk_in_suspend(struct charger_manager *cm) | ||
1019 | { | ||
1020 | unsigned long jiffy_now = jiffies; | ||
1021 | |||
1022 | if (!cm->fullbatt_vchk_jiffies_at) | ||
1023 | return; | ||
1024 | |||
1025 | if (g_desc && g_desc->assume_timer_stops_in_suspend) | ||
1026 | jiffy_now += msecs_to_jiffies(cm_suspend_duration_ms); | ||
1027 | |||
1028 | /* Execute now if it's going to be executed not too long after */ | ||
1029 | jiffy_now += CM_JIFFIES_SMALL; | ||
1030 | |||
1031 | if (time_after_eq(jiffy_now, cm->fullbatt_vchk_jiffies_at)) | ||
1032 | fullbatt_vchk(&cm->fullbatt_vchk_work.work); | ||
1033 | } | ||
1034 | |||
1035 | /** | ||
1036 | * cm_suspend_again - Determine whether suspend again or not | ||
1037 | * | ||
1038 | * Returns true if the system should be suspended again | ||
1039 | * Returns false if the system should be woken up | ||
1040 | */ | ||
1041 | bool cm_suspend_again(void) | ||
1042 | { | ||
1043 | struct charger_manager *cm; | ||
1044 | bool ret = false; | ||
1045 | |||
1046 | if (!g_desc || !g_desc->rtc_only_wakeup || !g_desc->rtc_only_wakeup() || | ||
1047 | !cm_rtc_set) | ||
1048 | return false; | ||
1049 | |||
1050 | if (cm_monitor()) | ||
1051 | goto out; | ||
1052 | |||
1053 | ret = true; | ||
1054 | mutex_lock(&cm_list_mtx); | ||
1055 | list_for_each_entry(cm, &cm_list, entry) { | ||
1056 | _cm_fbchk_in_suspend(cm); | ||
1057 | |||
1058 | if (cm->status_save_ext_pwr_inserted != is_ext_pwr_online(cm) || | ||
1059 | cm->status_save_batt != is_batt_present(cm)) { | ||
1060 | ret = false; | ||
1061 | break; | ||
1062 | } | ||
1063 | } | ||
1064 | mutex_unlock(&cm_list_mtx); | ||
1065 | |||
1066 | cm_rtc_set = cm_setup_timer(); | ||
1067 | out: | ||
1068 | /* It's about the time when the non-CM appointed timer goes off */ | ||
1069 | if (rtc_wkalarm_save.enabled) { | ||
1070 | unsigned long now; | ||
1071 | struct rtc_time tmp; | ||
1072 | |||
1073 | rtc_read_time(rtc_dev, &tmp); | ||
1074 | rtc_tm_to_time(&tmp, &now); | ||
1075 | |||
1076 | if (rtc_wkalarm_save_time && | ||
1077 | now + CM_RTC_SMALL >= rtc_wkalarm_save_time) | ||
1078 | return false; | ||
1079 | } | ||
1080 | return ret; | ||
1081 | } | ||
1082 | EXPORT_SYMBOL_GPL(cm_suspend_again); | ||
1083 | |||
1084 | /** | ||
1085 | * setup_charger_manager - initialize charger_global_desc data | ||
1086 | * @gd: pointer to instance of charger_global_desc | ||
1087 | */ | ||
1088 | int setup_charger_manager(struct charger_global_desc *gd) | ||
1089 | { | ||
1090 | if (!gd) | ||
1091 | return -EINVAL; | ||
1092 | |||
1093 | if (rtc_dev) | ||
1094 | rtc_class_close(rtc_dev); | ||
1095 | rtc_dev = NULL; | ||
1096 | g_desc = NULL; | ||
1097 | |||
1098 | if (!gd->rtc_only_wakeup) { | ||
1099 | pr_err("The callback rtc_only_wakeup is not given.\n"); | ||
1100 | return -EINVAL; | ||
1101 | } | ||
1102 | |||
1103 | if (gd->rtc_name) { | ||
1104 | rtc_dev = rtc_class_open(gd->rtc_name); | ||
1105 | if (IS_ERR_OR_NULL(rtc_dev)) { | ||
1106 | rtc_dev = NULL; | ||
1107 | /* Retry at probe. RTC may be not registered yet */ | ||
1108 | } | ||
1109 | } else { | ||
1110 | pr_warn("No wakeup timer is given for charger manager." | ||
1111 | "In-suspend monitoring won't work.\n"); | ||
1112 | } | ||
1113 | |||
1114 | g_desc = gd; | ||
1115 | return 0; | ||
1116 | } | ||
1117 | EXPORT_SYMBOL_GPL(setup_charger_manager); | ||
1118 | |||
1119 | /** | ||
1120 | * charger_extcon_work - enable/diable charger according to the state | ||
1121 | * of charger cable | ||
1122 | * | ||
1123 | * @work: work_struct of the function charger_extcon_work. | ||
1124 | */ | ||
1125 | static void charger_extcon_work(struct work_struct *work) | ||
1126 | { | ||
1127 | struct charger_cable *cable = | ||
1128 | container_of(work, struct charger_cable, wq); | ||
1129 | int ret; | ||
1130 | |||
1131 | if (cable->attached && cable->min_uA != 0 && cable->max_uA != 0) { | ||
1132 | ret = regulator_set_current_limit(cable->charger->consumer, | ||
1133 | cable->min_uA, cable->max_uA); | ||
1134 | if (ret < 0) { | ||
1135 | pr_err("Cannot set current limit of %s (%s)\n", | ||
1136 | cable->charger->regulator_name, cable->name); | ||
1137 | return; | ||
1138 | } | ||
1139 | |||
1140 | pr_info("Set current limit of %s : %duA ~ %duA\n", | ||
1141 | cable->charger->regulator_name, | ||
1142 | cable->min_uA, cable->max_uA); | ||
1143 | } | ||
1144 | |||
1145 | try_charger_enable(cable->cm, cable->attached); | ||
1146 | } | ||
1147 | |||
1148 | /** | ||
1149 | * charger_extcon_notifier - receive the state of charger cable | ||
1150 | * when registered cable is attached or detached. | ||
1151 | * | ||
1152 | * @self: the notifier block of the charger_extcon_notifier. | ||
1153 | * @event: the cable state. | ||
1154 | * @ptr: the data pointer of notifier block. | ||
1155 | */ | ||
1156 | static int charger_extcon_notifier(struct notifier_block *self, | ||
1157 | unsigned long event, void *ptr) | ||
1158 | { | ||
1159 | struct charger_cable *cable = | ||
1160 | container_of(self, struct charger_cable, nb); | ||
1161 | |||
1162 | /* | ||
1163 | * The newly state of charger cable. | ||
1164 | * If cable is attached, cable->attached is true. | ||
1165 | */ | ||
1166 | cable->attached = event; | ||
1167 | |||
1168 | /* | ||
1169 | * Setup monitoring to check battery state | ||
1170 | * when charger cable is attached. | ||
1171 | */ | ||
1172 | if (cable->attached && is_polling_required(cable->cm)) { | ||
1173 | if (work_pending(&setup_polling)) | ||
1174 | cancel_work_sync(&setup_polling); | ||
1175 | schedule_work(&setup_polling); | ||
1176 | } | ||
1177 | |||
1178 | /* | ||
1179 | * Setup work for controlling charger(regulator) | ||
1180 | * according to charger cable. | ||
1181 | */ | ||
1182 | schedule_work(&cable->wq); | ||
1183 | |||
1184 | return NOTIFY_DONE; | ||
1185 | } | ||
1186 | |||
1187 | /** | ||
1188 | * charger_extcon_init - register external connector to use it | ||
1189 | * as the charger cable | ||
1190 | * | ||
1191 | * @cm: the Charger Manager representing the battery. | ||
1192 | * @cable: the Charger cable representing the external connector. | ||
1193 | */ | ||
1194 | static int charger_extcon_init(struct charger_manager *cm, | ||
1195 | struct charger_cable *cable) | ||
1196 | { | ||
1197 | int ret = 0; | ||
1198 | |||
1199 | /* | ||
1200 | * Charger manager use Extcon framework to identify | ||
1201 | * the charger cable among various external connector | ||
1202 | * cable (e.g., TA, USB, MHL, Dock). | ||
1203 | */ | ||
1204 | INIT_WORK(&cable->wq, charger_extcon_work); | ||
1205 | cable->nb.notifier_call = charger_extcon_notifier; | ||
1206 | ret = extcon_register_interest(&cable->extcon_dev, | ||
1207 | cable->extcon_name, cable->name, &cable->nb); | ||
1208 | if (ret < 0) { | ||
1209 | pr_info("Cannot register extcon_dev for %s(cable: %s).\n", | ||
1210 | cable->extcon_name, | ||
1211 | cable->name); | ||
1212 | ret = -EINVAL; | ||
1213 | } | ||
1214 | |||
1215 | return ret; | ||
1216 | } | ||
1217 | |||
1218 | /* help function of sysfs node to control charger(regulator) */ | ||
1219 | static ssize_t charger_name_show(struct device *dev, | ||
1220 | struct device_attribute *attr, char *buf) | ||
1221 | { | ||
1222 | struct charger_regulator *charger | ||
1223 | = container_of(attr, struct charger_regulator, attr_name); | ||
1224 | |||
1225 | return sprintf(buf, "%s\n", charger->regulator_name); | ||
1226 | } | ||
1227 | |||
1228 | static ssize_t charger_state_show(struct device *dev, | ||
1229 | struct device_attribute *attr, char *buf) | ||
1230 | { | ||
1231 | struct charger_regulator *charger | ||
1232 | = container_of(attr, struct charger_regulator, attr_state); | ||
1233 | int state = 0; | ||
1234 | |||
1235 | if (!charger->externally_control) | ||
1236 | state = regulator_is_enabled(charger->consumer); | ||
1237 | |||
1238 | return sprintf(buf, "%s\n", state ? "enabled" : "disabled"); | ||
1239 | } | ||
1240 | |||
1241 | static ssize_t charger_externally_control_show(struct device *dev, | ||
1242 | struct device_attribute *attr, char *buf) | ||
1243 | { | ||
1244 | struct charger_regulator *charger = container_of(attr, | ||
1245 | struct charger_regulator, attr_externally_control); | ||
1246 | |||
1247 | return sprintf(buf, "%d\n", charger->externally_control); | ||
1248 | } | ||
1249 | |||
1250 | static ssize_t charger_externally_control_store(struct device *dev, | ||
1251 | struct device_attribute *attr, const char *buf, | ||
1252 | size_t count) | ||
1253 | { | ||
1254 | struct charger_regulator *charger | ||
1255 | = container_of(attr, struct charger_regulator, | ||
1256 | attr_externally_control); | ||
1257 | struct charger_manager *cm = charger->cm; | ||
1258 | struct charger_desc *desc = cm->desc; | ||
1259 | int i; | ||
1260 | int ret; | ||
1261 | int externally_control; | ||
1262 | int chargers_externally_control = 1; | ||
1263 | |||
1264 | ret = sscanf(buf, "%d", &externally_control); | ||
1265 | if (ret == 0) { | ||
1266 | ret = -EINVAL; | ||
1267 | return ret; | ||
1268 | } | ||
1269 | |||
1270 | if (!externally_control) { | ||
1271 | charger->externally_control = 0; | ||
1272 | return count; | ||
1273 | } | ||
1274 | |||
1275 | for (i = 0; i < desc->num_charger_regulators; i++) { | ||
1276 | if (&desc->charger_regulators[i] != charger && | ||
1277 | !desc->charger_regulators[i].externally_control) { | ||
1278 | /* | ||
1279 | * At least, one charger is controlled by | ||
1280 | * charger-manager | ||
1281 | */ | ||
1282 | chargers_externally_control = 0; | ||
1283 | break; | ||
1284 | } | ||
1285 | } | ||
1286 | |||
1287 | if (!chargers_externally_control) { | ||
1288 | if (cm->charger_enabled) { | ||
1289 | try_charger_enable(charger->cm, false); | ||
1290 | charger->externally_control = externally_control; | ||
1291 | try_charger_enable(charger->cm, true); | ||
1292 | } else { | ||
1293 | charger->externally_control = externally_control; | ||
1294 | } | ||
1295 | } else { | ||
1296 | dev_warn(cm->dev, | ||
1297 | "'%s' regulator should be controlled " | ||
1298 | "in charger-manager because charger-manager " | ||
1299 | "must need at least one charger for charging\n", | ||
1300 | charger->regulator_name); | ||
1301 | } | ||
1302 | |||
1303 | return count; | ||
1304 | } | ||
1305 | |||
1306 | static int charger_manager_probe(struct platform_device *pdev) | ||
1307 | { | ||
1308 | struct charger_desc *desc = dev_get_platdata(&pdev->dev); | ||
1309 | struct charger_manager *cm; | ||
1310 | int ret = 0, i = 0; | ||
1311 | int j = 0; | ||
1312 | int chargers_externally_control = 1; | ||
1313 | union power_supply_propval val; | ||
1314 | |||
1315 | if (g_desc && !rtc_dev && g_desc->rtc_name) { | ||
1316 | rtc_dev = rtc_class_open(g_desc->rtc_name); | ||
1317 | if (IS_ERR_OR_NULL(rtc_dev)) { | ||
1318 | rtc_dev = NULL; | ||
1319 | dev_err(&pdev->dev, "Cannot get RTC %s.\n", | ||
1320 | g_desc->rtc_name); | ||
1321 | ret = -ENODEV; | ||
1322 | goto err_alloc; | ||
1323 | } | ||
1324 | } | ||
1325 | |||
1326 | if (!desc) { | ||
1327 | dev_err(&pdev->dev, "No platform data (desc) found.\n"); | ||
1328 | ret = -ENODEV; | ||
1329 | goto err_alloc; | ||
1330 | } | ||
1331 | |||
1332 | cm = kzalloc(sizeof(struct charger_manager), GFP_KERNEL); | ||
1333 | if (!cm) { | ||
1334 | dev_err(&pdev->dev, "Cannot allocate memory.\n"); | ||
1335 | ret = -ENOMEM; | ||
1336 | goto err_alloc; | ||
1337 | } | ||
1338 | |||
1339 | /* Basic Values. Unspecified are Null or 0 */ | ||
1340 | cm->dev = &pdev->dev; | ||
1341 | cm->desc = kzalloc(sizeof(struct charger_desc), GFP_KERNEL); | ||
1342 | if (!cm->desc) { | ||
1343 | dev_err(&pdev->dev, "Cannot allocate memory.\n"); | ||
1344 | ret = -ENOMEM; | ||
1345 | goto err_alloc_desc; | ||
1346 | } | ||
1347 | memcpy(cm->desc, desc, sizeof(struct charger_desc)); | ||
1348 | cm->last_temp_mC = INT_MIN; /* denotes "unmeasured, yet" */ | ||
1349 | |||
1350 | /* | ||
1351 | * The following two do not need to be errors. | ||
1352 | * Users may intentionally ignore those two features. | ||
1353 | */ | ||
1354 | if (desc->fullbatt_uV == 0) { | ||
1355 | dev_info(&pdev->dev, "Ignoring full-battery voltage threshold" | ||
1356 | " as it is not supplied."); | ||
1357 | } | ||
1358 | if (!desc->fullbatt_vchkdrop_ms || !desc->fullbatt_vchkdrop_uV) { | ||
1359 | dev_info(&pdev->dev, "Disabling full-battery voltage drop " | ||
1360 | "checking mechanism as it is not supplied."); | ||
1361 | desc->fullbatt_vchkdrop_ms = 0; | ||
1362 | desc->fullbatt_vchkdrop_uV = 0; | ||
1363 | } | ||
1364 | if (desc->fullbatt_soc == 0) { | ||
1365 | dev_info(&pdev->dev, "Ignoring full-battery soc(state of" | ||
1366 | " charge) threshold as it is not" | ||
1367 | " supplied."); | ||
1368 | } | ||
1369 | if (desc->fullbatt_full_capacity == 0) { | ||
1370 | dev_info(&pdev->dev, "Ignoring full-battery full capacity" | ||
1371 | " threshold as it is not supplied."); | ||
1372 | } | ||
1373 | |||
1374 | if (!desc->charger_regulators || desc->num_charger_regulators < 1) { | ||
1375 | ret = -EINVAL; | ||
1376 | dev_err(&pdev->dev, "charger_regulators undefined.\n"); | ||
1377 | goto err_no_charger; | ||
1378 | } | ||
1379 | |||
1380 | if (!desc->psy_charger_stat || !desc->psy_charger_stat[0]) { | ||
1381 | dev_err(&pdev->dev, "No power supply defined.\n"); | ||
1382 | ret = -EINVAL; | ||
1383 | goto err_no_charger_stat; | ||
1384 | } | ||
1385 | |||
1386 | /* Counting index only */ | ||
1387 | while (desc->psy_charger_stat[i]) | ||
1388 | i++; | ||
1389 | |||
1390 | cm->charger_stat = kzalloc(sizeof(struct power_supply *) * (i + 1), | ||
1391 | GFP_KERNEL); | ||
1392 | if (!cm->charger_stat) { | ||
1393 | ret = -ENOMEM; | ||
1394 | goto err_no_charger_stat; | ||
1395 | } | ||
1396 | |||
1397 | for (i = 0; desc->psy_charger_stat[i]; i++) { | ||
1398 | cm->charger_stat[i] = power_supply_get_by_name( | ||
1399 | desc->psy_charger_stat[i]); | ||
1400 | if (!cm->charger_stat[i]) { | ||
1401 | dev_err(&pdev->dev, "Cannot find power supply " | ||
1402 | "\"%s\"\n", | ||
1403 | desc->psy_charger_stat[i]); | ||
1404 | ret = -ENODEV; | ||
1405 | goto err_chg_stat; | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge); | ||
1410 | if (!cm->fuel_gauge) { | ||
1411 | dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", | ||
1412 | desc->psy_fuel_gauge); | ||
1413 | ret = -ENODEV; | ||
1414 | goto err_chg_stat; | ||
1415 | } | ||
1416 | |||
1417 | if (desc->polling_interval_ms == 0 || | ||
1418 | msecs_to_jiffies(desc->polling_interval_ms) <= CM_JIFFIES_SMALL) { | ||
1419 | dev_err(&pdev->dev, "polling_interval_ms is too small\n"); | ||
1420 | ret = -EINVAL; | ||
1421 | goto err_chg_stat; | ||
1422 | } | ||
1423 | |||
1424 | if (!desc->temperature_out_of_range) { | ||
1425 | dev_err(&pdev->dev, "there is no temperature_out_of_range\n"); | ||
1426 | ret = -EINVAL; | ||
1427 | goto err_chg_stat; | ||
1428 | } | ||
1429 | |||
1430 | if (!desc->charging_max_duration_ms || | ||
1431 | !desc->discharging_max_duration_ms) { | ||
1432 | dev_info(&pdev->dev, "Cannot limit charging duration " | ||
1433 | "checking mechanism to prevent overcharge/overheat " | ||
1434 | "and control discharging duration"); | ||
1435 | desc->charging_max_duration_ms = 0; | ||
1436 | desc->discharging_max_duration_ms = 0; | ||
1437 | } | ||
1438 | |||
1439 | platform_set_drvdata(pdev, cm); | ||
1440 | |||
1441 | memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default)); | ||
1442 | |||
1443 | if (!desc->psy_name) { | ||
1444 | strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX); | ||
1445 | } else { | ||
1446 | strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX); | ||
1447 | } | ||
1448 | cm->charger_psy.name = cm->psy_name_buf; | ||
1449 | |||
1450 | /* Allocate for psy properties because they may vary */ | ||
1451 | cm->charger_psy.properties = kzalloc(sizeof(enum power_supply_property) | ||
1452 | * (ARRAY_SIZE(default_charger_props) + | ||
1453 | NUM_CHARGER_PSY_OPTIONAL), | ||
1454 | GFP_KERNEL); | ||
1455 | if (!cm->charger_psy.properties) { | ||
1456 | dev_err(&pdev->dev, "Cannot allocate for psy properties.\n"); | ||
1457 | ret = -ENOMEM; | ||
1458 | goto err_chg_stat; | ||
1459 | } | ||
1460 | memcpy(cm->charger_psy.properties, default_charger_props, | ||
1461 | sizeof(enum power_supply_property) * | ||
1462 | ARRAY_SIZE(default_charger_props)); | ||
1463 | cm->charger_psy.num_properties = psy_default.num_properties; | ||
1464 | |||
1465 | /* Find which optional psy-properties are available */ | ||
1466 | if (!cm->fuel_gauge->get_property(cm->fuel_gauge, | ||
1467 | POWER_SUPPLY_PROP_CHARGE_NOW, &val)) { | ||
1468 | cm->charger_psy.properties[cm->charger_psy.num_properties] = | ||
1469 | POWER_SUPPLY_PROP_CHARGE_NOW; | ||
1470 | cm->charger_psy.num_properties++; | ||
1471 | } | ||
1472 | if (!cm->fuel_gauge->get_property(cm->fuel_gauge, | ||
1473 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
1474 | &val)) { | ||
1475 | cm->charger_psy.properties[cm->charger_psy.num_properties] = | ||
1476 | POWER_SUPPLY_PROP_CURRENT_NOW; | ||
1477 | cm->charger_psy.num_properties++; | ||
1478 | } | ||
1479 | |||
1480 | if (desc->measure_battery_temp) { | ||
1481 | cm->charger_psy.properties[cm->charger_psy.num_properties] = | ||
1482 | POWER_SUPPLY_PROP_TEMP; | ||
1483 | cm->charger_psy.num_properties++; | ||
1484 | } else { | ||
1485 | cm->charger_psy.properties[cm->charger_psy.num_properties] = | ||
1486 | POWER_SUPPLY_PROP_TEMP_AMBIENT; | ||
1487 | cm->charger_psy.num_properties++; | ||
1488 | } | ||
1489 | |||
1490 | INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk); | ||
1491 | |||
1492 | ret = power_supply_register(NULL, &cm->charger_psy); | ||
1493 | if (ret) { | ||
1494 | dev_err(&pdev->dev, "Cannot register charger-manager with" | ||
1495 | " name \"%s\".\n", cm->charger_psy.name); | ||
1496 | goto err_register; | ||
1497 | } | ||
1498 | |||
1499 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | ||
1500 | struct charger_regulator *charger | ||
1501 | = &desc->charger_regulators[i]; | ||
1502 | char buf[11]; | ||
1503 | char *str; | ||
1504 | |||
1505 | charger->consumer = regulator_get(&pdev->dev, | ||
1506 | charger->regulator_name); | ||
1507 | if (charger->consumer == NULL) { | ||
1508 | dev_err(&pdev->dev, "Cannot find charger(%s)n", | ||
1509 | charger->regulator_name); | ||
1510 | ret = -EINVAL; | ||
1511 | goto err_chg_get; | ||
1512 | } | ||
1513 | charger->cm = cm; | ||
1514 | |||
1515 | for (j = 0 ; j < charger->num_cables ; j++) { | ||
1516 | struct charger_cable *cable = &charger->cables[j]; | ||
1517 | |||
1518 | ret = charger_extcon_init(cm, cable); | ||
1519 | if (ret < 0) { | ||
1520 | dev_err(&pdev->dev, "Cannot find charger(%s)n", | ||
1521 | charger->regulator_name); | ||
1522 | goto err_extcon; | ||
1523 | } | ||
1524 | cable->charger = charger; | ||
1525 | cable->cm = cm; | ||
1526 | } | ||
1527 | |||
1528 | /* Create sysfs entry to control charger(regulator) */ | ||
1529 | snprintf(buf, 10, "charger.%d", i); | ||
1530 | str = kzalloc(sizeof(char) * (strlen(buf) + 1), GFP_KERNEL); | ||
1531 | if (!str) { | ||
1532 | for (i--; i >= 0; i--) { | ||
1533 | charger = &desc->charger_regulators[i]; | ||
1534 | kfree(charger->attr_g.name); | ||
1535 | } | ||
1536 | ret = -ENOMEM; | ||
1537 | |||
1538 | goto err_extcon; | ||
1539 | } | ||
1540 | strcpy(str, buf); | ||
1541 | |||
1542 | charger->attrs[0] = &charger->attr_name.attr; | ||
1543 | charger->attrs[1] = &charger->attr_state.attr; | ||
1544 | charger->attrs[2] = &charger->attr_externally_control.attr; | ||
1545 | charger->attrs[3] = NULL; | ||
1546 | charger->attr_g.name = str; | ||
1547 | charger->attr_g.attrs = charger->attrs; | ||
1548 | |||
1549 | sysfs_attr_init(&charger->attr_name.attr); | ||
1550 | charger->attr_name.attr.name = "name"; | ||
1551 | charger->attr_name.attr.mode = 0444; | ||
1552 | charger->attr_name.show = charger_name_show; | ||
1553 | |||
1554 | sysfs_attr_init(&charger->attr_state.attr); | ||
1555 | charger->attr_state.attr.name = "state"; | ||
1556 | charger->attr_state.attr.mode = 0444; | ||
1557 | charger->attr_state.show = charger_state_show; | ||
1558 | |||
1559 | sysfs_attr_init(&charger->attr_externally_control.attr); | ||
1560 | charger->attr_externally_control.attr.name | ||
1561 | = "externally_control"; | ||
1562 | charger->attr_externally_control.attr.mode = 0644; | ||
1563 | charger->attr_externally_control.show | ||
1564 | = charger_externally_control_show; | ||
1565 | charger->attr_externally_control.store | ||
1566 | = charger_externally_control_store; | ||
1567 | |||
1568 | if (!desc->charger_regulators[i].externally_control || | ||
1569 | !chargers_externally_control) { | ||
1570 | chargers_externally_control = 0; | ||
1571 | } | ||
1572 | dev_info(&pdev->dev, "'%s' regulator's externally_control" | ||
1573 | "is %d\n", charger->regulator_name, | ||
1574 | charger->externally_control); | ||
1575 | |||
1576 | ret = sysfs_create_group(&cm->charger_psy.dev->kobj, | ||
1577 | &charger->attr_g); | ||
1578 | if (ret < 0) { | ||
1579 | dev_info(&pdev->dev, "Cannot create sysfs entry" | ||
1580 | "of %s regulator\n", | ||
1581 | charger->regulator_name); | ||
1582 | } | ||
1583 | } | ||
1584 | |||
1585 | if (chargers_externally_control) { | ||
1586 | dev_err(&pdev->dev, "Cannot register regulator because " | ||
1587 | "charger-manager must need at least " | ||
1588 | "one charger for charging battery\n"); | ||
1589 | |||
1590 | ret = -EINVAL; | ||
1591 | goto err_chg_enable; | ||
1592 | } | ||
1593 | |||
1594 | ret = try_charger_enable(cm, true); | ||
1595 | if (ret) { | ||
1596 | dev_err(&pdev->dev, "Cannot enable charger regulators\n"); | ||
1597 | goto err_chg_enable; | ||
1598 | } | ||
1599 | |||
1600 | /* Add to the list */ | ||
1601 | mutex_lock(&cm_list_mtx); | ||
1602 | list_add(&cm->entry, &cm_list); | ||
1603 | mutex_unlock(&cm_list_mtx); | ||
1604 | |||
1605 | /* | ||
1606 | * Charger-manager is capable of waking up the systme from sleep | ||
1607 | * when event is happend through cm_notify_event() | ||
1608 | */ | ||
1609 | device_init_wakeup(&pdev->dev, true); | ||
1610 | device_set_wakeup_capable(&pdev->dev, false); | ||
1611 | |||
1612 | schedule_work(&setup_polling); | ||
1613 | |||
1614 | return 0; | ||
1615 | |||
1616 | err_chg_enable: | ||
1617 | for (i = 0; i < desc->num_charger_regulators; i++) { | ||
1618 | struct charger_regulator *charger; | ||
1619 | |||
1620 | charger = &desc->charger_regulators[i]; | ||
1621 | sysfs_remove_group(&cm->charger_psy.dev->kobj, | ||
1622 | &charger->attr_g); | ||
1623 | kfree(charger->attr_g.name); | ||
1624 | } | ||
1625 | err_extcon: | ||
1626 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | ||
1627 | struct charger_regulator *charger | ||
1628 | = &desc->charger_regulators[i]; | ||
1629 | for (j = 0 ; j < charger->num_cables ; j++) { | ||
1630 | struct charger_cable *cable = &charger->cables[j]; | ||
1631 | extcon_unregister_interest(&cable->extcon_dev); | ||
1632 | } | ||
1633 | } | ||
1634 | err_chg_get: | ||
1635 | for (i = 0 ; i < desc->num_charger_regulators ; i++) | ||
1636 | regulator_put(desc->charger_regulators[i].consumer); | ||
1637 | |||
1638 | power_supply_unregister(&cm->charger_psy); | ||
1639 | err_register: | ||
1640 | kfree(cm->charger_psy.properties); | ||
1641 | err_chg_stat: | ||
1642 | kfree(cm->charger_stat); | ||
1643 | err_no_charger_stat: | ||
1644 | err_no_charger: | ||
1645 | kfree(cm->desc); | ||
1646 | err_alloc_desc: | ||
1647 | kfree(cm); | ||
1648 | err_alloc: | ||
1649 | return ret; | ||
1650 | } | ||
1651 | |||
1652 | static int charger_manager_remove(struct platform_device *pdev) | ||
1653 | { | ||
1654 | struct charger_manager *cm = platform_get_drvdata(pdev); | ||
1655 | struct charger_desc *desc = cm->desc; | ||
1656 | int i = 0; | ||
1657 | int j = 0; | ||
1658 | |||
1659 | /* Remove from the list */ | ||
1660 | mutex_lock(&cm_list_mtx); | ||
1661 | list_del(&cm->entry); | ||
1662 | mutex_unlock(&cm_list_mtx); | ||
1663 | |||
1664 | if (work_pending(&setup_polling)) | ||
1665 | cancel_work_sync(&setup_polling); | ||
1666 | if (delayed_work_pending(&cm_monitor_work)) | ||
1667 | cancel_delayed_work_sync(&cm_monitor_work); | ||
1668 | |||
1669 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | ||
1670 | struct charger_regulator *charger | ||
1671 | = &desc->charger_regulators[i]; | ||
1672 | for (j = 0 ; j < charger->num_cables ; j++) { | ||
1673 | struct charger_cable *cable = &charger->cables[j]; | ||
1674 | extcon_unregister_interest(&cable->extcon_dev); | ||
1675 | } | ||
1676 | } | ||
1677 | |||
1678 | for (i = 0 ; i < desc->num_charger_regulators ; i++) | ||
1679 | regulator_put(desc->charger_regulators[i].consumer); | ||
1680 | |||
1681 | power_supply_unregister(&cm->charger_psy); | ||
1682 | |||
1683 | try_charger_enable(cm, false); | ||
1684 | |||
1685 | kfree(cm->charger_psy.properties); | ||
1686 | kfree(cm->charger_stat); | ||
1687 | kfree(cm->desc); | ||
1688 | kfree(cm); | ||
1689 | |||
1690 | return 0; | ||
1691 | } | ||
1692 | |||
1693 | static const struct platform_device_id charger_manager_id[] = { | ||
1694 | { "charger-manager", 0 }, | ||
1695 | { }, | ||
1696 | }; | ||
1697 | MODULE_DEVICE_TABLE(platform, charger_manager_id); | ||
1698 | |||
1699 | static int cm_suspend_noirq(struct device *dev) | ||
1700 | { | ||
1701 | int ret = 0; | ||
1702 | |||
1703 | if (device_may_wakeup(dev)) { | ||
1704 | device_set_wakeup_capable(dev, false); | ||
1705 | ret = -EAGAIN; | ||
1706 | } | ||
1707 | |||
1708 | return ret; | ||
1709 | } | ||
1710 | |||
1711 | static int cm_suspend_prepare(struct device *dev) | ||
1712 | { | ||
1713 | struct charger_manager *cm = dev_get_drvdata(dev); | ||
1714 | |||
1715 | if (!cm_suspended) { | ||
1716 | if (rtc_dev) { | ||
1717 | struct rtc_time tmp; | ||
1718 | unsigned long now; | ||
1719 | |||
1720 | rtc_read_alarm(rtc_dev, &rtc_wkalarm_save); | ||
1721 | rtc_read_time(rtc_dev, &tmp); | ||
1722 | |||
1723 | if (rtc_wkalarm_save.enabled) { | ||
1724 | rtc_tm_to_time(&rtc_wkalarm_save.time, | ||
1725 | &rtc_wkalarm_save_time); | ||
1726 | rtc_tm_to_time(&tmp, &now); | ||
1727 | if (now > rtc_wkalarm_save_time) | ||
1728 | rtc_wkalarm_save_time = 0; | ||
1729 | } else { | ||
1730 | rtc_wkalarm_save_time = 0; | ||
1731 | } | ||
1732 | } | ||
1733 | cm_suspended = true; | ||
1734 | } | ||
1735 | |||
1736 | if (delayed_work_pending(&cm->fullbatt_vchk_work)) | ||
1737 | cancel_delayed_work(&cm->fullbatt_vchk_work); | ||
1738 | cm->status_save_ext_pwr_inserted = is_ext_pwr_online(cm); | ||
1739 | cm->status_save_batt = is_batt_present(cm); | ||
1740 | |||
1741 | if (!cm_rtc_set) { | ||
1742 | cm_suspend_duration_ms = 0; | ||
1743 | cm_rtc_set = cm_setup_timer(); | ||
1744 | } | ||
1745 | |||
1746 | return 0; | ||
1747 | } | ||
1748 | |||
1749 | static void cm_suspend_complete(struct device *dev) | ||
1750 | { | ||
1751 | struct charger_manager *cm = dev_get_drvdata(dev); | ||
1752 | |||
1753 | if (cm_suspended) { | ||
1754 | if (rtc_dev) { | ||
1755 | struct rtc_wkalrm tmp; | ||
1756 | |||
1757 | rtc_read_alarm(rtc_dev, &tmp); | ||
1758 | rtc_wkalarm_save.pending = tmp.pending; | ||
1759 | rtc_set_alarm(rtc_dev, &rtc_wkalarm_save); | ||
1760 | } | ||
1761 | cm_suspended = false; | ||
1762 | cm_rtc_set = false; | ||
1763 | } | ||
1764 | |||
1765 | /* Re-enqueue delayed work (fullbatt_vchk_work) */ | ||
1766 | if (cm->fullbatt_vchk_jiffies_at) { | ||
1767 | unsigned long delay = 0; | ||
1768 | unsigned long now = jiffies + CM_JIFFIES_SMALL; | ||
1769 | |||
1770 | if (time_after_eq(now, cm->fullbatt_vchk_jiffies_at)) { | ||
1771 | delay = (unsigned long)((long)now | ||
1772 | - (long)(cm->fullbatt_vchk_jiffies_at)); | ||
1773 | delay = jiffies_to_msecs(delay); | ||
1774 | } else { | ||
1775 | delay = 0; | ||
1776 | } | ||
1777 | |||
1778 | /* | ||
1779 | * Account for cm_suspend_duration_ms if | ||
1780 | * assume_timer_stops_in_suspend is active | ||
1781 | */ | ||
1782 | if (g_desc && g_desc->assume_timer_stops_in_suspend) { | ||
1783 | if (delay > cm_suspend_duration_ms) | ||
1784 | delay -= cm_suspend_duration_ms; | ||
1785 | else | ||
1786 | delay = 0; | ||
1787 | } | ||
1788 | |||
1789 | queue_delayed_work(cm_wq, &cm->fullbatt_vchk_work, | ||
1790 | msecs_to_jiffies(delay)); | ||
1791 | } | ||
1792 | device_set_wakeup_capable(cm->dev, false); | ||
1793 | uevent_notify(cm, NULL); | ||
1794 | } | ||
1795 | |||
1796 | static const struct dev_pm_ops charger_manager_pm = { | ||
1797 | .prepare = cm_suspend_prepare, | ||
1798 | .suspend_noirq = cm_suspend_noirq, | ||
1799 | .complete = cm_suspend_complete, | ||
1800 | }; | ||
1801 | |||
1802 | static struct platform_driver charger_manager_driver = { | ||
1803 | .driver = { | ||
1804 | .name = "charger-manager", | ||
1805 | .owner = THIS_MODULE, | ||
1806 | .pm = &charger_manager_pm, | ||
1807 | }, | ||
1808 | .probe = charger_manager_probe, | ||
1809 | .remove = charger_manager_remove, | ||
1810 | .id_table = charger_manager_id, | ||
1811 | }; | ||
1812 | |||
1813 | static int __init charger_manager_init(void) | ||
1814 | { | ||
1815 | cm_wq = create_freezable_workqueue("charger_manager"); | ||
1816 | INIT_DELAYED_WORK(&cm_monitor_work, cm_monitor_poller); | ||
1817 | |||
1818 | return platform_driver_register(&charger_manager_driver); | ||
1819 | } | ||
1820 | late_initcall(charger_manager_init); | ||
1821 | |||
1822 | static void __exit charger_manager_cleanup(void) | ||
1823 | { | ||
1824 | destroy_workqueue(cm_wq); | ||
1825 | cm_wq = NULL; | ||
1826 | |||
1827 | platform_driver_unregister(&charger_manager_driver); | ||
1828 | } | ||
1829 | module_exit(charger_manager_cleanup); | ||
1830 | |||
1831 | /** | ||
1832 | * find_power_supply - find the associated power_supply of charger | ||
1833 | * @cm: the Charger Manager representing the battery | ||
1834 | * @psy: pointer to instance of charger's power_supply | ||
1835 | */ | ||
1836 | static bool find_power_supply(struct charger_manager *cm, | ||
1837 | struct power_supply *psy) | ||
1838 | { | ||
1839 | int i; | ||
1840 | bool found = false; | ||
1841 | |||
1842 | for (i = 0; cm->charger_stat[i]; i++) { | ||
1843 | if (psy == cm->charger_stat[i]) { | ||
1844 | found = true; | ||
1845 | break; | ||
1846 | } | ||
1847 | } | ||
1848 | |||
1849 | return found; | ||
1850 | } | ||
1851 | |||
1852 | /** | ||
1853 | * cm_notify_event - charger driver notify Charger Manager of charger event | ||
1854 | * @psy: pointer to instance of charger's power_supply | ||
1855 | * @type: type of charger event | ||
1856 | * @msg: optional message passed to uevent_notify fuction | ||
1857 | */ | ||
1858 | void cm_notify_event(struct power_supply *psy, enum cm_event_types type, | ||
1859 | char *msg) | ||
1860 | { | ||
1861 | struct charger_manager *cm; | ||
1862 | bool found_power_supply = false; | ||
1863 | |||
1864 | if (psy == NULL) | ||
1865 | return; | ||
1866 | |||
1867 | mutex_lock(&cm_list_mtx); | ||
1868 | list_for_each_entry(cm, &cm_list, entry) { | ||
1869 | found_power_supply = find_power_supply(cm, psy); | ||
1870 | if (found_power_supply) | ||
1871 | break; | ||
1872 | } | ||
1873 | mutex_unlock(&cm_list_mtx); | ||
1874 | |||
1875 | if (!found_power_supply) | ||
1876 | return; | ||
1877 | |||
1878 | switch (type) { | ||
1879 | case CM_EVENT_BATT_FULL: | ||
1880 | fullbatt_handler(cm); | ||
1881 | break; | ||
1882 | case CM_EVENT_BATT_OUT: | ||
1883 | battout_handler(cm); | ||
1884 | break; | ||
1885 | case CM_EVENT_BATT_IN: | ||
1886 | case CM_EVENT_EXT_PWR_IN_OUT ... CM_EVENT_CHG_START_STOP: | ||
1887 | misc_event_handler(cm, type); | ||
1888 | break; | ||
1889 | case CM_EVENT_UNKNOWN: | ||
1890 | case CM_EVENT_OTHERS: | ||
1891 | uevent_notify(cm, msg ? msg : default_event_names[type]); | ||
1892 | break; | ||
1893 | default: | ||
1894 | dev_err(cm->dev, "%s type not specified.\n", __func__); | ||
1895 | break; | ||
1896 | } | ||
1897 | } | ||
1898 | EXPORT_SYMBOL_GPL(cm_notify_event); | ||
1899 | |||
1900 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
1901 | MODULE_DESCRIPTION("Charger Manager"); | ||
1902 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c index c58d0e31bde..548d263b1ad 100644 --- a/drivers/power/collie_battery.c +++ b/drivers/power/collie_battery.c | |||
@@ -146,7 +146,7 @@ static void collie_bat_external_power_changed(struct power_supply *psy) | |||
146 | 146 | ||
147 | static irqreturn_t collie_bat_gpio_isr(int irq, void *data) | 147 | static irqreturn_t collie_bat_gpio_isr(int irq, void *data) |
148 | { | 148 | { |
149 | pr_info("collie_bat_gpio irq\n"); | 149 | pr_info("collie_bat_gpio irq: %d\n", gpio_get_value(irq_to_gpio(irq))); |
150 | schedule_work(&bat_work); | 150 | schedule_work(&bat_work); |
151 | return IRQ_HANDLED; | 151 | return IRQ_HANDLED; |
152 | } | 152 | } |
@@ -277,20 +277,25 @@ static struct collie_bat collie_bat_bu = { | |||
277 | .adc_temp_divider = -1, | 277 | .adc_temp_divider = -1, |
278 | }; | 278 | }; |
279 | 279 | ||
280 | static struct gpio collie_batt_gpios[] = { | 280 | static struct { |
281 | { COLLIE_GPIO_CO, GPIOF_IN, "main battery full" }, | 281 | int gpio; |
282 | { COLLIE_GPIO_MAIN_BAT_LOW, GPIOF_IN, "main battery low" }, | 282 | char *name; |
283 | { COLLIE_GPIO_CHARGE_ON, GPIOF_OUT_INIT_LOW, "main charge on" }, | 283 | bool output; |
284 | { COLLIE_GPIO_MBAT_ON, GPIOF_OUT_INIT_LOW, "main battery" }, | 284 | int value; |
285 | { COLLIE_GPIO_TMP_ON, GPIOF_OUT_INIT_LOW, "main battery temp" }, | 285 | } gpios[] = { |
286 | { COLLIE_GPIO_BBAT_ON, GPIOF_OUT_INIT_LOW, "backup battery" }, | 286 | { COLLIE_GPIO_CO, "main battery full", 0, 0 }, |
287 | { COLLIE_GPIO_MAIN_BAT_LOW, "main battery low", 0, 0 }, | ||
288 | { COLLIE_GPIO_CHARGE_ON, "main charge on", 1, 0 }, | ||
289 | { COLLIE_GPIO_MBAT_ON, "main battery", 1, 0 }, | ||
290 | { COLLIE_GPIO_TMP_ON, "main battery temp", 1, 0 }, | ||
291 | { COLLIE_GPIO_BBAT_ON, "backup battery", 1, 0 }, | ||
287 | }; | 292 | }; |
288 | 293 | ||
289 | #ifdef CONFIG_PM | 294 | #ifdef CONFIG_PM |
290 | static int collie_bat_suspend(struct ucb1x00_dev *dev, pm_message_t state) | 295 | static int collie_bat_suspend(struct ucb1x00_dev *dev, pm_message_t state) |
291 | { | 296 | { |
292 | /* flush all pending status updates */ | 297 | /* flush all pending status updates */ |
293 | flush_work(&bat_work); | 298 | flush_work_sync(&bat_work); |
294 | return 0; | 299 | return 0; |
295 | } | 300 | } |
296 | 301 | ||
@@ -305,19 +310,32 @@ static int collie_bat_resume(struct ucb1x00_dev *dev) | |||
305 | #define collie_bat_resume NULL | 310 | #define collie_bat_resume NULL |
306 | #endif | 311 | #endif |
307 | 312 | ||
308 | static int collie_bat_probe(struct ucb1x00_dev *dev) | 313 | static int __devinit collie_bat_probe(struct ucb1x00_dev *dev) |
309 | { | 314 | { |
310 | int ret; | 315 | int ret; |
316 | int i; | ||
311 | 317 | ||
312 | if (!machine_is_collie()) | 318 | if (!machine_is_collie()) |
313 | return -ENODEV; | 319 | return -ENODEV; |
314 | 320 | ||
315 | ucb = dev->ucb; | 321 | ucb = dev->ucb; |
316 | 322 | ||
317 | ret = gpio_request_array(collie_batt_gpios, | 323 | for (i = 0; i < ARRAY_SIZE(gpios); i++) { |
318 | ARRAY_SIZE(collie_batt_gpios)); | 324 | ret = gpio_request(gpios[i].gpio, gpios[i].name); |
319 | if (ret) | 325 | if (ret) { |
320 | return ret; | 326 | i--; |
327 | goto err_gpio; | ||
328 | } | ||
329 | |||
330 | if (gpios[i].output) | ||
331 | ret = gpio_direction_output(gpios[i].gpio, | ||
332 | gpios[i].value); | ||
333 | else | ||
334 | ret = gpio_direction_input(gpios[i].gpio); | ||
335 | |||
336 | if (ret) | ||
337 | goto err_gpio; | ||
338 | } | ||
321 | 339 | ||
322 | mutex_init(&collie_bat_main.work_lock); | 340 | mutex_init(&collie_bat_main.work_lock); |
323 | 341 | ||
@@ -345,12 +363,19 @@ err_psy_reg_main: | |||
345 | 363 | ||
346 | /* see comment in collie_bat_remove */ | 364 | /* see comment in collie_bat_remove */ |
347 | cancel_work_sync(&bat_work); | 365 | cancel_work_sync(&bat_work); |
348 | gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios)); | 366 | |
367 | i--; | ||
368 | err_gpio: | ||
369 | for (; i >= 0; i--) | ||
370 | gpio_free(gpios[i].gpio); | ||
371 | |||
349 | return ret; | 372 | return ret; |
350 | } | 373 | } |
351 | 374 | ||
352 | static void collie_bat_remove(struct ucb1x00_dev *dev) | 375 | static void __devexit collie_bat_remove(struct ucb1x00_dev *dev) |
353 | { | 376 | { |
377 | int i; | ||
378 | |||
354 | free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main); | 379 | free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main); |
355 | 380 | ||
356 | power_supply_unregister(&collie_bat_bu.psy); | 381 | power_supply_unregister(&collie_bat_bu.psy); |
@@ -362,12 +387,14 @@ static void collie_bat_remove(struct ucb1x00_dev *dev) | |||
362 | * unregistered now. | 387 | * unregistered now. |
363 | */ | 388 | */ |
364 | cancel_work_sync(&bat_work); | 389 | cancel_work_sync(&bat_work); |
365 | gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios)); | 390 | |
391 | for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--) | ||
392 | gpio_free(gpios[i].gpio); | ||
366 | } | 393 | } |
367 | 394 | ||
368 | static struct ucb1x00_driver collie_bat_driver = { | 395 | static struct ucb1x00_driver collie_bat_driver = { |
369 | .add = collie_bat_probe, | 396 | .add = collie_bat_probe, |
370 | .remove = collie_bat_remove, | 397 | .remove = __devexit_p(collie_bat_remove), |
371 | .suspend = collie_bat_suspend, | 398 | .suspend = collie_bat_suspend, |
372 | .resume = collie_bat_resume, | 399 | .resume = collie_bat_resume, |
373 | }; | 400 | }; |
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c index 94762e67e22..d2c793cf676 100644 --- a/drivers/power/da9030_battery.c +++ b/drivers/power/da9030_battery.c | |||
@@ -187,8 +187,8 @@ static const struct file_operations bat_debug_fops = { | |||
187 | 187 | ||
188 | static struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger) | 188 | static struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger) |
189 | { | 189 | { |
190 | charger->debug_file = debugfs_create_file("charger", 0666, NULL, | 190 | charger->debug_file = debugfs_create_file("charger", 0666, 0, charger, |
191 | charger, &bat_debug_fops); | 191 | &bat_debug_fops); |
192 | return charger->debug_file; | 192 | return charger->debug_file; |
193 | } | 193 | } |
194 | 194 | ||
@@ -588,7 +588,18 @@ static struct platform_driver da903x_battery_driver = { | |||
588 | .remove = da9030_battery_remove, | 588 | .remove = da9030_battery_remove, |
589 | }; | 589 | }; |
590 | 590 | ||
591 | module_platform_driver(da903x_battery_driver); | 591 | static int da903x_battery_init(void) |
592 | { | ||
593 | return platform_driver_register(&da903x_battery_driver); | ||
594 | } | ||
595 | |||
596 | static void da903x_battery_exit(void) | ||
597 | { | ||
598 | platform_driver_unregister(&da903x_battery_driver); | ||
599 | } | ||
600 | |||
601 | module_init(da903x_battery_init); | ||
602 | module_exit(da903x_battery_exit); | ||
592 | 603 | ||
593 | MODULE_DESCRIPTION("DA9030 battery charger driver"); | 604 | MODULE_DESCRIPTION("DA9030 battery charger driver"); |
594 | MODULE_AUTHOR("Mike Rapoport, CompuLab"); | 605 | MODULE_AUTHOR("Mike Rapoport, CompuLab"); |
diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c deleted file mode 100644 index 3c5c2e459d7..00000000000 --- a/drivers/power/da9052-battery.c +++ /dev/null | |||
@@ -1,668 +0,0 @@ | |||
1 | /* | ||
2 | * Batttery Driver for Dialog DA9052 PMICs | ||
3 | * | ||
4 | * Copyright(c) 2011 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: David Dajun Chen <dchen@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/freezer.h> | ||
16 | #include <linux/fs.h> | ||
17 | #include <linux/jiffies.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/uaccess.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/power_supply.h> | ||
23 | |||
24 | #include <linux/mfd/da9052/da9052.h> | ||
25 | #include <linux/mfd/da9052/pdata.h> | ||
26 | #include <linux/mfd/da9052/reg.h> | ||
27 | |||
28 | /* STATIC CONFIGURATION */ | ||
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 | ||
35 | |||
36 | #define DA9052_ISET_USB_MASK 0x0F | ||
37 | #define DA9052_CHG_USB_ILIM_MASK 0x40 | ||
38 | #define DA9052_CHG_LIM_COLS 16 | ||
39 | |||
40 | #define DA9052_MEAN(x, y) ((x + y) / 2) | ||
41 | |||
42 | enum charger_type_enum { | ||
43 | DA9052_NOCHARGER = 1, | ||
44 | DA9052_CHARGER, | ||
45 | }; | ||
46 | |||
47 | static const u16 da9052_chg_current_lim[2][DA9052_CHG_LIM_COLS] = { | ||
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}, | ||
52 | }; | ||
53 | |||
54 | static const u16 vc_tbl_ref[3] = {10, 25, 40}; | ||
55 | /* Lookup table for voltage vs capacity */ | ||
56 | static u32 const vc_tbl[3][68][2] = { | ||
57 | /* For temperature 10 degree Celsius */ | ||
58 | { | ||
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}, | ||
89 | {3587, 9}, {3572, 7}, | ||
90 | {3548, 6}, {3503, 5}, | ||
91 | {3420, 3}, {3268, 2}, | ||
92 | {2992, 1}, {2746, 0} | ||
93 | }, | ||
94 | /* For temperature 25 degree Celsius */ | ||
95 | { | ||
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}, | ||
129 | {3546, 1}, {2747, 0} | ||
130 | }, | ||
131 | /* For temperature 40 degree Celsius */ | ||
132 | { | ||
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}, | ||
166 | {3594, 1}, {2747, 0} | ||
167 | } | ||
168 | }; | ||
169 | |||
170 | struct da9052_battery { | ||
171 | struct da9052 *da9052; | ||
172 | struct power_supply psy; | ||
173 | struct notifier_block nb; | ||
174 | int charger_type; | ||
175 | int status; | ||
176 | int health; | ||
177 | }; | ||
178 | |||
179 | static inline int volt_reg_to_mV(int value) | ||
180 | { | ||
181 | return ((value * 1000) / 512) + 2500; | ||
182 | } | ||
183 | |||
184 | static inline int ichg_reg_to_mA(int value) | ||
185 | { | ||
186 | return (value * 3900) / 1000; | ||
187 | } | ||
188 | |||
189 | static int da9052_read_chgend_current(struct da9052_battery *bat, | ||
190 | int *current_mA) | ||
191 | { | ||
192 | int ret; | ||
193 | |||
194 | if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING) | ||
195 | return -EINVAL; | ||
196 | |||
197 | ret = da9052_reg_read(bat->da9052, DA9052_ICHG_END_REG); | ||
198 | if (ret < 0) | ||
199 | return ret; | ||
200 | |||
201 | *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGEND_ICHGEND); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int da9052_read_chg_current(struct da9052_battery *bat, int *current_mA) | ||
207 | { | ||
208 | int ret; | ||
209 | |||
210 | if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING) | ||
211 | return -EINVAL; | ||
212 | |||
213 | ret = da9052_reg_read(bat->da9052, DA9052_ICHG_AV_REG); | ||
214 | if (ret < 0) | ||
215 | return ret; | ||
216 | |||
217 | *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGAV_ICHGAV); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int da9052_bat_check_status(struct da9052_battery *bat, int *status) | ||
223 | { | ||
224 | u8 v[2] = {0, 0}; | ||
225 | u8 bat_status; | ||
226 | u8 chg_end; | ||
227 | int ret; | ||
228 | int chg_current; | ||
229 | int chg_end_current; | ||
230 | bool dcinsel; | ||
231 | bool dcindet; | ||
232 | bool vbussel; | ||
233 | bool vbusdet; | ||
234 | bool dc; | ||
235 | bool vbus; | ||
236 | |||
237 | ret = da9052_group_read(bat->da9052, DA9052_STATUS_A_REG, 2, v); | ||
238 | if (ret < 0) | ||
239 | return ret; | ||
240 | |||
241 | bat_status = v[0]; | ||
242 | chg_end = v[1]; | ||
243 | |||
244 | dcinsel = bat_status & DA9052_STATUSA_DCINSEL; | ||
245 | dcindet = bat_status & DA9052_STATUSA_DCINDET; | ||
246 | vbussel = bat_status & DA9052_STATUSA_VBUSSEL; | ||
247 | vbusdet = bat_status & DA9052_STATUSA_VBUSDET; | ||
248 | dc = dcinsel && dcindet; | ||
249 | vbus = vbussel && vbusdet; | ||
250 | |||
251 | /* Preference to WALL(DCIN) charger unit */ | ||
252 | if (dc || vbus) { | ||
253 | bat->charger_type = DA9052_CHARGER; | ||
254 | |||
255 | /* If charging end flag is set and Charging current is greater | ||
256 | * than charging end limit then battery is charging | ||
257 | */ | ||
258 | if ((chg_end & DA9052_STATUSB_CHGEND) != 0) { | ||
259 | ret = da9052_read_chg_current(bat, &chg_current); | ||
260 | if (ret < 0) | ||
261 | return ret; | ||
262 | ret = da9052_read_chgend_current(bat, &chg_end_current); | ||
263 | if (ret < 0) | ||
264 | return ret; | ||
265 | |||
266 | if (chg_current >= chg_end_current) | ||
267 | bat->status = POWER_SUPPLY_STATUS_CHARGING; | ||
268 | else | ||
269 | bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
270 | } else { | ||
271 | /* If Charging end flag is cleared then battery is | ||
272 | * charging | ||
273 | */ | ||
274 | bat->status = POWER_SUPPLY_STATUS_CHARGING; | ||
275 | } | ||
276 | } else if (dcindet || vbusdet) { | ||
277 | bat->charger_type = DA9052_CHARGER; | ||
278 | bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
279 | } else { | ||
280 | bat->charger_type = DA9052_NOCHARGER; | ||
281 | bat->status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
282 | } | ||
283 | |||
284 | if (status != NULL) | ||
285 | *status = bat->status; | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int da9052_bat_read_volt(struct da9052_battery *bat, int *volt_mV) | ||
290 | { | ||
291 | int volt; | ||
292 | |||
293 | volt = da9052_adc_manual_read(bat->da9052, DA9052_ADC_MAN_MUXSEL_VBAT); | ||
294 | if (volt < 0) | ||
295 | return volt; | ||
296 | |||
297 | *volt_mV = volt_reg_to_mV(volt); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static int da9052_bat_check_presence(struct da9052_battery *bat, int *illegal) | ||
303 | { | ||
304 | int bat_temp; | ||
305 | |||
306 | bat_temp = da9052_adc_read_temp(bat->da9052); | ||
307 | if (bat_temp < 0) | ||
308 | return bat_temp; | ||
309 | |||
310 | if (bat_temp > DA9052_BAT_TSH) | ||
311 | *illegal = 1; | ||
312 | else | ||
313 | *illegal = 0; | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int da9052_bat_interpolate(int vbat_lower, int vbat_upper, | ||
319 | int level_lower, int level_upper, | ||
320 | int bat_voltage) | ||
321 | { | ||
322 | int tmp; | ||
323 | |||
324 | tmp = ((level_upper - level_lower) * 1000) / (vbat_upper - vbat_lower); | ||
325 | tmp = level_lower + (((bat_voltage - vbat_lower) * tmp) / 1000); | ||
326 | |||
327 | return tmp; | ||
328 | } | ||
329 | |||
330 | static unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp) | ||
331 | { | ||
332 | int i; | ||
333 | |||
334 | if (adc_temp <= vc_tbl_ref[0]) | ||
335 | return 0; | ||
336 | |||
337 | if (adc_temp > vc_tbl_ref[DA9052_VC_TBL_REF_SZ - 1]) | ||
338 | return DA9052_VC_TBL_REF_SZ - 1; | ||
339 | |||
340 | for (i = 0; i < DA9052_VC_TBL_REF_SZ; i++) { | ||
341 | if ((adc_temp > vc_tbl_ref[i]) && | ||
342 | (adc_temp <= DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1]))) | ||
343 | return i; | ||
344 | if ((adc_temp > DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1])) | ||
345 | && (adc_temp <= vc_tbl_ref[i])) | ||
346 | return i + 1; | ||
347 | } | ||
348 | /* | ||
349 | * For some reason authors of the driver didn't presume that we can | ||
350 | * end up here. It might be OK, but might be not, no one knows for | ||
351 | * sure. Go check your battery, is it on fire? | ||
352 | */ | ||
353 | WARN_ON(1); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static int da9052_bat_read_capacity(struct da9052_battery *bat, int *capacity) | ||
358 | { | ||
359 | int adc_temp; | ||
360 | int bat_voltage; | ||
361 | int vbat_lower; | ||
362 | int vbat_upper; | ||
363 | int level_upper; | ||
364 | int level_lower; | ||
365 | int ret; | ||
366 | int flag; | ||
367 | int i = 0; | ||
368 | int j; | ||
369 | |||
370 | ret = da9052_bat_read_volt(bat, &bat_voltage); | ||
371 | if (ret < 0) | ||
372 | return ret; | ||
373 | |||
374 | adc_temp = da9052_adc_read_temp(bat->da9052); | ||
375 | if (adc_temp < 0) | ||
376 | return adc_temp; | ||
377 | |||
378 | i = da9052_determine_vc_tbl_index(adc_temp); | ||
379 | |||
380 | if (bat_voltage >= vc_tbl[i][0][0]) { | ||
381 | *capacity = 100; | ||
382 | return 0; | ||
383 | } | ||
384 | if (bat_voltage <= vc_tbl[i][DA9052_VC_TBL_SZ - 1][0]) { | ||
385 | *capacity = 0; | ||
386 | return 0; | ||
387 | } | ||
388 | flag = 0; | ||
389 | |||
390 | for (j = 0; j < (DA9052_VC_TBL_SZ-1); j++) { | ||
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]; | ||
397 | flag = 1; | ||
398 | break; | ||
399 | } | ||
400 | } | ||
401 | if (!flag) | ||
402 | return -EIO; | ||
403 | |||
404 | *capacity = da9052_bat_interpolate(vbat_lower, vbat_upper, level_lower, | ||
405 | level_upper, bat_voltage); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | static int da9052_bat_check_health(struct da9052_battery *bat, int *health) | ||
411 | { | ||
412 | int ret; | ||
413 | int bat_illegal; | ||
414 | int capacity; | ||
415 | |||
416 | ret = da9052_bat_check_presence(bat, &bat_illegal); | ||
417 | if (ret < 0) | ||
418 | return ret; | ||
419 | |||
420 | if (bat_illegal) { | ||
421 | bat->health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | if (bat->health != POWER_SUPPLY_HEALTH_OVERHEAT) { | ||
426 | ret = da9052_bat_read_capacity(bat, &capacity); | ||
427 | if (ret < 0) | ||
428 | return ret; | ||
429 | if (capacity < DA9052_BAT_LOW_CAP) | ||
430 | bat->health = POWER_SUPPLY_HEALTH_DEAD; | ||
431 | else | ||
432 | bat->health = POWER_SUPPLY_HEALTH_GOOD; | ||
433 | } | ||
434 | |||
435 | *health = bat->health; | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static irqreturn_t da9052_bat_irq(int irq, void *data) | ||
441 | { | ||
442 | struct da9052_battery *bat = data; | ||
443 | int virq; | ||
444 | |||
445 | virq = regmap_irq_get_virq(bat->da9052->irq_data, irq); | ||
446 | irq -= virq; | ||
447 | |||
448 | if (irq == DA9052_IRQ_CHGEND) | ||
449 | bat->status = POWER_SUPPLY_STATUS_FULL; | ||
450 | else | ||
451 | da9052_bat_check_status(bat, NULL); | ||
452 | |||
453 | if (irq == DA9052_IRQ_CHGEND || irq == DA9052_IRQ_DCIN || | ||
454 | irq == DA9052_IRQ_VBUS || irq == DA9052_IRQ_TBAT) { | ||
455 | power_supply_changed(&bat->psy); | ||
456 | } | ||
457 | |||
458 | return IRQ_HANDLED; | ||
459 | } | ||
460 | |||
461 | static int da9052_USB_current_notifier(struct notifier_block *nb, | ||
462 | unsigned long events, void *data) | ||
463 | { | ||
464 | u8 row; | ||
465 | u8 col; | ||
466 | int *current_mA = data; | ||
467 | int ret; | ||
468 | struct da9052_battery *bat = container_of(nb, struct da9052_battery, | ||
469 | nb); | ||
470 | |||
471 | if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING) | ||
472 | return -EPERM; | ||
473 | |||
474 | ret = da9052_reg_read(bat->da9052, DA9052_CHGBUCK_REG); | ||
475 | if (ret & DA9052_CHG_USB_ILIM_MASK) | ||
476 | return -EPERM; | ||
477 | |||
478 | if (bat->da9052->chip_id == DA9052) | ||
479 | row = 0; | ||
480 | else | ||
481 | row = 1; | ||
482 | |||
483 | if (*current_mA < da9052_chg_current_lim[row][0] || | ||
484 | *current_mA > da9052_chg_current_lim[row][DA9052_CHG_LIM_COLS - 1]) | ||
485 | return -EINVAL; | ||
486 | |||
487 | for (col = 0; col <= DA9052_CHG_LIM_COLS - 1 ; col++) { | ||
488 | if (*current_mA <= da9052_chg_current_lim[row][col]) | ||
489 | break; | ||
490 | } | ||
491 | |||
492 | return da9052_reg_update(bat->da9052, DA9052_ISET_REG, | ||
493 | DA9052_ISET_USB_MASK, col); | ||
494 | } | ||
495 | |||
496 | static int da9052_bat_get_property(struct power_supply *psy, | ||
497 | enum power_supply_property psp, | ||
498 | union power_supply_propval *val) | ||
499 | { | ||
500 | int ret; | ||
501 | int illegal; | ||
502 | struct da9052_battery *bat = container_of(psy, struct da9052_battery, | ||
503 | psy); | ||
504 | |||
505 | ret = da9052_bat_check_presence(bat, &illegal); | ||
506 | if (ret < 0) | ||
507 | return ret; | ||
508 | |||
509 | if (illegal && psp != POWER_SUPPLY_PROP_PRESENT) | ||
510 | return -ENODEV; | ||
511 | |||
512 | switch (psp) { | ||
513 | case POWER_SUPPLY_PROP_STATUS: | ||
514 | ret = da9052_bat_check_status(bat, &val->intval); | ||
515 | break; | ||
516 | case POWER_SUPPLY_PROP_ONLINE: | ||
517 | val->intval = | ||
518 | (bat->charger_type == DA9052_NOCHARGER) ? 0 : 1; | ||
519 | break; | ||
520 | case POWER_SUPPLY_PROP_PRESENT: | ||
521 | ret = da9052_bat_check_presence(bat, &val->intval); | ||
522 | break; | ||
523 | case POWER_SUPPLY_PROP_HEALTH: | ||
524 | ret = da9052_bat_check_health(bat, &val->intval); | ||
525 | break; | ||
526 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | ||
527 | val->intval = DA9052_BAT_CUTOFF_VOLT * 1000; | ||
528 | break; | ||
529 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | ||
530 | ret = da9052_bat_read_volt(bat, &val->intval); | ||
531 | break; | ||
532 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
533 | ret = da9052_read_chg_current(bat, &val->intval); | ||
534 | break; | ||
535 | case POWER_SUPPLY_PROP_CAPACITY: | ||
536 | ret = da9052_bat_read_capacity(bat, &val->intval); | ||
537 | break; | ||
538 | case POWER_SUPPLY_PROP_TEMP: | ||
539 | val->intval = da9052_adc_read_temp(bat->da9052); | ||
540 | ret = val->intval; | ||
541 | break; | ||
542 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
543 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | ||
544 | break; | ||
545 | default: | ||
546 | return -EINVAL; | ||
547 | } | ||
548 | return ret; | ||
549 | } | ||
550 | |||
551 | static enum power_supply_property da9052_bat_props[] = { | ||
552 | POWER_SUPPLY_PROP_STATUS, | ||
553 | POWER_SUPPLY_PROP_ONLINE, | ||
554 | POWER_SUPPLY_PROP_PRESENT, | ||
555 | POWER_SUPPLY_PROP_HEALTH, | ||
556 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | ||
557 | POWER_SUPPLY_PROP_VOLTAGE_AVG, | ||
558 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
559 | POWER_SUPPLY_PROP_CAPACITY, | ||
560 | POWER_SUPPLY_PROP_TEMP, | ||
561 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
562 | }; | ||
563 | |||
564 | static struct power_supply template_battery = { | ||
565 | .name = "da9052-bat", | ||
566 | .type = POWER_SUPPLY_TYPE_BATTERY, | ||
567 | .properties = da9052_bat_props, | ||
568 | .num_properties = ARRAY_SIZE(da9052_bat_props), | ||
569 | .get_property = da9052_bat_get_property, | ||
570 | }; | ||
571 | |||
572 | static char *da9052_bat_irqs[] = { | ||
573 | "BATT TEMP", | ||
574 | "DCIN DET", | ||
575 | "DCIN REM", | ||
576 | "VBUS DET", | ||
577 | "VBUS REM", | ||
578 | "CHG END", | ||
579 | }; | ||
580 | |||
581 | static int da9052_bat_irq_bits[] = { | ||
582 | DA9052_IRQ_TBAT, | ||
583 | DA9052_IRQ_DCIN, | ||
584 | DA9052_IRQ_DCINREM, | ||
585 | DA9052_IRQ_VBUS, | ||
586 | DA9052_IRQ_VBUSREM, | ||
587 | DA9052_IRQ_CHGEND, | ||
588 | }; | ||
589 | |||
590 | static s32 da9052_bat_probe(struct platform_device *pdev) | ||
591 | { | ||
592 | struct da9052_pdata *pdata; | ||
593 | struct da9052_battery *bat; | ||
594 | int ret; | ||
595 | int i; | ||
596 | |||
597 | bat = kzalloc(sizeof(struct da9052_battery), GFP_KERNEL); | ||
598 | if (!bat) | ||
599 | return -ENOMEM; | ||
600 | |||
601 | bat->da9052 = dev_get_drvdata(pdev->dev.parent); | ||
602 | bat->psy = template_battery; | ||
603 | bat->charger_type = DA9052_NOCHARGER; | ||
604 | bat->status = POWER_SUPPLY_STATUS_UNKNOWN; | ||
605 | bat->health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
606 | bat->nb.notifier_call = da9052_USB_current_notifier; | ||
607 | |||
608 | pdata = bat->da9052->dev->platform_data; | ||
609 | if (pdata != NULL && pdata->use_for_apm) | ||
610 | bat->psy.use_for_apm = pdata->use_for_apm; | ||
611 | else | ||
612 | bat->psy.use_for_apm = 1; | ||
613 | |||
614 | for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) { | ||
615 | ret = da9052_request_irq(bat->da9052, | ||
616 | da9052_bat_irq_bits[i], da9052_bat_irqs[i], | ||
617 | da9052_bat_irq, bat); | ||
618 | |||
619 | if (ret != 0) { | ||
620 | dev_err(bat->da9052->dev, | ||
621 | "DA9052 failed to request %s IRQ: %d\n", | ||
622 | da9052_bat_irqs[i], ret); | ||
623 | goto err; | ||
624 | } | ||
625 | } | ||
626 | |||
627 | ret = power_supply_register(&pdev->dev, &bat->psy); | ||
628 | if (ret) | ||
629 | goto err; | ||
630 | |||
631 | platform_set_drvdata(pdev, bat); | ||
632 | return 0; | ||
633 | |||
634 | err: | ||
635 | while (--i >= 0) | ||
636 | da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat); | ||
637 | |||
638 | kfree(bat); | ||
639 | return ret; | ||
640 | } | ||
641 | static int da9052_bat_remove(struct platform_device *pdev) | ||
642 | { | ||
643 | int i; | ||
644 | struct da9052_battery *bat = platform_get_drvdata(pdev); | ||
645 | |||
646 | for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) | ||
647 | da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat); | ||
648 | |||
649 | power_supply_unregister(&bat->psy); | ||
650 | kfree(bat); | ||
651 | |||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | static struct platform_driver da9052_bat_driver = { | ||
656 | .probe = da9052_bat_probe, | ||
657 | .remove = da9052_bat_remove, | ||
658 | .driver = { | ||
659 | .name = "da9052-bat", | ||
660 | .owner = THIS_MODULE, | ||
661 | }, | ||
662 | }; | ||
663 | module_platform_driver(da9052_bat_driver); | ||
664 | |||
665 | MODULE_DESCRIPTION("DA9052 BAT Device Driver"); | ||
666 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | ||
667 | MODULE_LICENSE("GPL"); | ||
668 | MODULE_ALIAS("platform:da9052-bat"); | ||
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index 704e652072b..f2c9cc33c0f 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c | |||
@@ -64,7 +64,7 @@ static unsigned int cache_time = 1000; | |||
64 | module_param(cache_time, uint, 0644); | 64 | module_param(cache_time, uint, 0644); |
65 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); | 65 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); |
66 | 66 | ||
67 | static bool pmod_enabled; | 67 | static unsigned int pmod_enabled; |
68 | module_param(pmod_enabled, bool, 0644); | 68 | module_param(pmod_enabled, bool, 0644); |
69 | MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit"); | 69 | MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit"); |
70 | 70 | ||
@@ -95,11 +95,7 @@ static int rated_capacities[] = { | |||
95 | 2880, /* Samsung */ | 95 | 2880, /* Samsung */ |
96 | 2880, /* BYD */ | 96 | 2880, /* BYD */ |
97 | 2880, /* Lishen */ | 97 | 2880, /* Lishen */ |
98 | 2880, /* NEC */ | 98 | 2880 /* NEC */ |
99 | #ifdef CONFIG_MACH_H4700 | ||
100 | 0, | ||
101 | 3600, /* HP iPAQ hx4700 3.7V 3600mAh (359114-001) */ | ||
102 | #endif | ||
103 | }; | 99 | }; |
104 | 100 | ||
105 | /* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C | 101 | /* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C |
@@ -355,7 +351,8 @@ static void ds2760_battery_external_power_changed(struct power_supply *psy) | |||
355 | 351 | ||
356 | dev_dbg(di->dev, "%s\n", __func__); | 352 | dev_dbg(di->dev, "%s\n", __func__); |
357 | 353 | ||
358 | mod_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10); | 354 | cancel_delayed_work(&di->monitor_work); |
355 | queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10); | ||
359 | } | 356 | } |
360 | 357 | ||
361 | 358 | ||
@@ -400,7 +397,8 @@ static void ds2760_battery_set_charged(struct power_supply *psy) | |||
400 | 397 | ||
401 | /* postpone the actual work by 20 secs. This is for debouncing GPIO | 398 | /* postpone the actual work by 20 secs. This is for debouncing GPIO |
402 | * signals and to let the current value settle. See AN4188. */ | 399 | * signals and to let the current value settle. See AN4188. */ |
403 | mod_delayed_work(di->monitor_wqueue, &di->set_charged_work, HZ * 20); | 400 | cancel_delayed_work(&di->set_charged_work); |
401 | queue_delayed_work(di->monitor_wqueue, &di->set_charged_work, HZ * 20); | ||
404 | } | 402 | } |
405 | 403 | ||
406 | static int ds2760_battery_get_property(struct power_supply *psy, | 404 | static int ds2760_battery_get_property(struct power_supply *psy, |
@@ -614,7 +612,8 @@ static int ds2760_battery_resume(struct platform_device *pdev) | |||
614 | di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN; | 612 | di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN; |
615 | power_supply_changed(&di->bat); | 613 | power_supply_changed(&di->bat); |
616 | 614 | ||
617 | mod_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ); | 615 | cancel_delayed_work(&di->monitor_work); |
616 | queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ); | ||
618 | 617 | ||
619 | return 0; | 618 | return 0; |
620 | } | 619 | } |
@@ -638,7 +637,18 @@ static struct platform_driver ds2760_battery_driver = { | |||
638 | .resume = ds2760_battery_resume, | 637 | .resume = ds2760_battery_resume, |
639 | }; | 638 | }; |
640 | 639 | ||
641 | module_platform_driver(ds2760_battery_driver); | 640 | static int __init ds2760_battery_init(void) |
641 | { | ||
642 | return platform_driver_register(&ds2760_battery_driver); | ||
643 | } | ||
644 | |||
645 | static void __exit ds2760_battery_exit(void) | ||
646 | { | ||
647 | platform_driver_unregister(&ds2760_battery_driver); | ||
648 | } | ||
649 | |||
650 | module_init(ds2760_battery_init); | ||
651 | module_exit(ds2760_battery_exit); | ||
642 | 652 | ||
643 | MODULE_LICENSE("GPL"); | 653 | MODULE_LICENSE("GPL"); |
644 | MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, " | 654 | MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, " |
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c index 8b6c4539e7f..91a783d7236 100644 --- a/drivers/power/ds2780_battery.c +++ b/drivers/power/ds2780_battery.c | |||
@@ -39,6 +39,7 @@ struct ds2780_device_info { | |||
39 | struct device *dev; | 39 | struct device *dev; |
40 | struct power_supply bat; | 40 | struct power_supply bat; |
41 | struct device *w1_dev; | 41 | struct device *w1_dev; |
42 | struct task_struct *mutex_holder; | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | enum current_types { | 45 | enum current_types { |
@@ -63,7 +64,10 @@ static inline struct power_supply *to_power_supply(struct device *dev) | |||
63 | static inline int ds2780_battery_io(struct ds2780_device_info *dev_info, | 64 | static inline int ds2780_battery_io(struct ds2780_device_info *dev_info, |
64 | char *buf, int addr, size_t count, int io) | 65 | char *buf, int addr, size_t count, int io) |
65 | { | 66 | { |
66 | return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io); | 67 | if (dev_info->mutex_holder == current) |
68 | return w1_ds2780_io_nolock(dev_info->w1_dev, buf, addr, count, io); | ||
69 | else | ||
70 | return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io); | ||
67 | } | 71 | } |
68 | 72 | ||
69 | static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val, | 73 | static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val, |
@@ -755,7 +759,7 @@ static const struct attribute_group ds2780_attr_group = { | |||
755 | .attrs = ds2780_attributes, | 759 | .attrs = ds2780_attributes, |
756 | }; | 760 | }; |
757 | 761 | ||
758 | static int ds2780_battery_probe(struct platform_device *pdev) | 762 | static int __devinit ds2780_battery_probe(struct platform_device *pdev) |
759 | { | 763 | { |
760 | int ret = 0; | 764 | int ret = 0; |
761 | struct ds2780_device_info *dev_info; | 765 | struct ds2780_device_info *dev_info; |
@@ -775,6 +779,7 @@ static int ds2780_battery_probe(struct platform_device *pdev) | |||
775 | dev_info->bat.properties = ds2780_battery_props; | 779 | dev_info->bat.properties = ds2780_battery_props; |
776 | dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props); | 780 | dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props); |
777 | dev_info->bat.get_property = ds2780_battery_get_property; | 781 | dev_info->bat.get_property = ds2780_battery_get_property; |
782 | dev_info->mutex_holder = current; | ||
778 | 783 | ||
779 | ret = power_supply_register(&pdev->dev, &dev_info->bat); | 784 | ret = power_supply_register(&pdev->dev, &dev_info->bat); |
780 | if (ret) { | 785 | if (ret) { |
@@ -804,6 +809,8 @@ static int ds2780_battery_probe(struct platform_device *pdev) | |||
804 | goto fail_remove_bin_file; | 809 | goto fail_remove_bin_file; |
805 | } | 810 | } |
806 | 811 | ||
812 | dev_info->mutex_holder = NULL; | ||
813 | |||
807 | return 0; | 814 | return 0; |
808 | 815 | ||
809 | fail_remove_bin_file: | 816 | fail_remove_bin_file: |
@@ -819,10 +826,12 @@ fail: | |||
819 | return ret; | 826 | return ret; |
820 | } | 827 | } |
821 | 828 | ||
822 | static int ds2780_battery_remove(struct platform_device *pdev) | 829 | static int __devexit ds2780_battery_remove(struct platform_device *pdev) |
823 | { | 830 | { |
824 | struct ds2780_device_info *dev_info = platform_get_drvdata(pdev); | 831 | struct ds2780_device_info *dev_info = platform_get_drvdata(pdev); |
825 | 832 | ||
833 | dev_info->mutex_holder = current; | ||
834 | |||
826 | /* remove attributes */ | 835 | /* remove attributes */ |
827 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); | 836 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); |
828 | 837 | ||
@@ -832,6 +841,8 @@ static int ds2780_battery_remove(struct platform_device *pdev) | |||
832 | return 0; | 841 | return 0; |
833 | } | 842 | } |
834 | 843 | ||
844 | MODULE_ALIAS("platform:ds2780-battery"); | ||
845 | |||
835 | static struct platform_driver ds2780_battery_driver = { | 846 | static struct platform_driver ds2780_battery_driver = { |
836 | .driver = { | 847 | .driver = { |
837 | .name = "ds2780-battery", | 848 | .name = "ds2780-battery", |
@@ -840,9 +851,19 @@ static struct platform_driver ds2780_battery_driver = { | |||
840 | .remove = ds2780_battery_remove, | 851 | .remove = ds2780_battery_remove, |
841 | }; | 852 | }; |
842 | 853 | ||
843 | module_platform_driver(ds2780_battery_driver); | 854 | static int __init ds2780_battery_init(void) |
855 | { | ||
856 | return platform_driver_register(&ds2780_battery_driver); | ||
857 | } | ||
858 | |||
859 | static void __exit ds2780_battery_exit(void) | ||
860 | { | ||
861 | platform_driver_unregister(&ds2780_battery_driver); | ||
862 | } | ||
863 | |||
864 | module_init(ds2780_battery_init); | ||
865 | module_exit(ds2780_battery_exit); | ||
844 | 866 | ||
845 | MODULE_LICENSE("GPL"); | 867 | MODULE_LICENSE("GPL"); |
846 | MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>"); | 868 | MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>"); |
847 | MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauage IC driver"); | 869 | MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauage IC driver"); |
848 | MODULE_ALIAS("platform:ds2780-battery"); | ||
diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c deleted file mode 100644 index 0a5acc6fc6f..00000000000 --- a/drivers/power/ds2781_battery.c +++ /dev/null | |||
@@ -1,838 +0,0 @@ | |||
1 | /* | ||
2 | * 1-wire client/driver for the Maxim/Dallas DS2781 Stand-Alone Fuel Gauge IC | ||
3 | * | ||
4 | * Author: Renata Sayakhova <renata@oktetlabs.ru> | ||
5 | * | ||
6 | * Based on ds2780_battery drivers | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/param.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/power_supply.h> | ||
20 | #include <linux/idr.h> | ||
21 | |||
22 | #include "../w1/w1.h" | ||
23 | #include "../w1/slaves/w1_ds2781.h" | ||
24 | |||
25 | /* Current unit measurement in uA for a 1 milli-ohm sense resistor */ | ||
26 | #define DS2781_CURRENT_UNITS 1563 | ||
27 | /* Charge unit measurement in uAh for a 1 milli-ohm sense resistor */ | ||
28 | #define DS2781_CHARGE_UNITS 6250 | ||
29 | /* Number of bytes in user EEPROM space */ | ||
30 | #define DS2781_USER_EEPROM_SIZE (DS2781_EEPROM_BLOCK0_END - \ | ||
31 | DS2781_EEPROM_BLOCK0_START + 1) | ||
32 | /* Number of bytes in parameter EEPROM space */ | ||
33 | #define DS2781_PARAM_EEPROM_SIZE (DS2781_EEPROM_BLOCK1_END - \ | ||
34 | DS2781_EEPROM_BLOCK1_START + 1) | ||
35 | |||
36 | struct ds2781_device_info { | ||
37 | struct device *dev; | ||
38 | struct power_supply bat; | ||
39 | struct device *w1_dev; | ||
40 | }; | ||
41 | |||
42 | enum current_types { | ||
43 | CURRENT_NOW, | ||
44 | CURRENT_AVG, | ||
45 | }; | ||
46 | |||
47 | static const char model[] = "DS2781"; | ||
48 | static const char manufacturer[] = "Maxim/Dallas"; | ||
49 | |||
50 | static inline struct ds2781_device_info * | ||
51 | to_ds2781_device_info(struct power_supply *psy) | ||
52 | { | ||
53 | return container_of(psy, struct ds2781_device_info, bat); | ||
54 | } | ||
55 | |||
56 | static inline struct power_supply *to_power_supply(struct device *dev) | ||
57 | { | ||
58 | return dev_get_drvdata(dev); | ||
59 | } | ||
60 | |||
61 | static inline int ds2781_battery_io(struct ds2781_device_info *dev_info, | ||
62 | char *buf, int addr, size_t count, int io) | ||
63 | { | ||
64 | return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io); | ||
65 | } | ||
66 | |||
67 | static int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, | ||
68 | int addr, size_t count) | ||
69 | { | ||
70 | return ds2781_battery_io(dev_info, buf, addr, count, 0); | ||
71 | } | ||
72 | |||
73 | static inline int ds2781_read8(struct ds2781_device_info *dev_info, u8 *val, | ||
74 | int addr) | ||
75 | { | ||
76 | return ds2781_battery_io(dev_info, val, addr, sizeof(u8), 0); | ||
77 | } | ||
78 | |||
79 | static int ds2781_read16(struct ds2781_device_info *dev_info, s16 *val, | ||
80 | int addr) | ||
81 | { | ||
82 | int ret; | ||
83 | u8 raw[2]; | ||
84 | |||
85 | ret = ds2781_battery_io(dev_info, raw, addr, sizeof(raw), 0); | ||
86 | if (ret < 0) | ||
87 | return ret; | ||
88 | |||
89 | *val = (raw[0] << 8) | raw[1]; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static inline int ds2781_read_block(struct ds2781_device_info *dev_info, | ||
95 | u8 *val, int addr, size_t count) | ||
96 | { | ||
97 | return ds2781_battery_io(dev_info, val, addr, count, 0); | ||
98 | } | ||
99 | |||
100 | static inline int ds2781_write(struct ds2781_device_info *dev_info, u8 *val, | ||
101 | int addr, size_t count) | ||
102 | { | ||
103 | return ds2781_battery_io(dev_info, val, addr, count, 1); | ||
104 | } | ||
105 | |||
106 | static inline int ds2781_store_eeprom(struct device *dev, int addr) | ||
107 | { | ||
108 | return w1_ds2781_eeprom_cmd(dev, addr, W1_DS2781_COPY_DATA); | ||
109 | } | ||
110 | |||
111 | static inline int ds2781_recall_eeprom(struct device *dev, int addr) | ||
112 | { | ||
113 | return w1_ds2781_eeprom_cmd(dev, addr, W1_DS2781_RECALL_DATA); | ||
114 | } | ||
115 | |||
116 | static int ds2781_save_eeprom(struct ds2781_device_info *dev_info, int reg) | ||
117 | { | ||
118 | int ret; | ||
119 | |||
120 | ret = ds2781_store_eeprom(dev_info->w1_dev, reg); | ||
121 | if (ret < 0) | ||
122 | return ret; | ||
123 | |||
124 | ret = ds2781_recall_eeprom(dev_info->w1_dev, reg); | ||
125 | if (ret < 0) | ||
126 | return ret; | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | /* Set sense resistor value in mhos */ | ||
132 | static int ds2781_set_sense_register(struct ds2781_device_info *dev_info, | ||
133 | u8 conductance) | ||
134 | { | ||
135 | int ret; | ||
136 | |||
137 | ret = ds2781_write(dev_info, &conductance, | ||
138 | DS2781_RSNSP, sizeof(u8)); | ||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | |||
142 | return ds2781_save_eeprom(dev_info, DS2781_RSNSP); | ||
143 | } | ||
144 | |||
145 | /* Get RSGAIN value from 0 to 1.999 in steps of 0.001 */ | ||
146 | static int ds2781_get_rsgain_register(struct ds2781_device_info *dev_info, | ||
147 | u16 *rsgain) | ||
148 | { | ||
149 | return ds2781_read16(dev_info, rsgain, DS2781_RSGAIN_MSB); | ||
150 | } | ||
151 | |||
152 | /* Set RSGAIN value from 0 to 1.999 in steps of 0.001 */ | ||
153 | static int ds2781_set_rsgain_register(struct ds2781_device_info *dev_info, | ||
154 | u16 rsgain) | ||
155 | { | ||
156 | int ret; | ||
157 | u8 raw[] = {rsgain >> 8, rsgain & 0xFF}; | ||
158 | |||
159 | ret = ds2781_write(dev_info, raw, | ||
160 | DS2781_RSGAIN_MSB, sizeof(raw)); | ||
161 | if (ret < 0) | ||
162 | return ret; | ||
163 | |||
164 | return ds2781_save_eeprom(dev_info, DS2781_RSGAIN_MSB); | ||
165 | } | ||
166 | |||
167 | static int ds2781_get_voltage(struct ds2781_device_info *dev_info, | ||
168 | int *voltage_uV) | ||
169 | { | ||
170 | int ret; | ||
171 | char val[2]; | ||
172 | int voltage_raw; | ||
173 | |||
174 | ret = w1_ds2781_read(dev_info, val, DS2781_VOLT_MSB, 2 * sizeof(u8)); | ||
175 | if (ret < 0) | ||
176 | return ret; | ||
177 | /* | ||
178 | * The voltage value is located in 10 bits across the voltage MSB | ||
179 | * and LSB registers in two's compliment form | ||
180 | * Sign bit of the voltage value is in bit 7 of the voltage MSB register | ||
181 | * Bits 9 - 3 of the voltage value are in bits 6 - 0 of the | ||
182 | * voltage MSB register | ||
183 | * Bits 2 - 0 of the voltage value are in bits 7 - 5 of the | ||
184 | * voltage LSB register | ||
185 | */ | ||
186 | voltage_raw = (val[0] << 3) | | ||
187 | (val[1] >> 5); | ||
188 | |||
189 | /* DS2781 reports voltage in units of 9.76mV, but the battery class | ||
190 | * reports in units of uV, so convert by multiplying by 9760. */ | ||
191 | *voltage_uV = voltage_raw * 9760; | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int ds2781_get_temperature(struct ds2781_device_info *dev_info, | ||
197 | int *temp) | ||
198 | { | ||
199 | int ret; | ||
200 | char val[2]; | ||
201 | int temp_raw; | ||
202 | |||
203 | ret = w1_ds2781_read(dev_info, val, DS2781_TEMP_MSB, 2 * sizeof(u8)); | ||
204 | if (ret < 0) | ||
205 | return ret; | ||
206 | /* | ||
207 | * The temperature value is located in 10 bits across the temperature | ||
208 | * MSB and LSB registers in two's compliment form | ||
209 | * Sign bit of the temperature value is in bit 7 of the temperature | ||
210 | * MSB register | ||
211 | * Bits 9 - 3 of the temperature value are in bits 6 - 0 of the | ||
212 | * temperature MSB register | ||
213 | * Bits 2 - 0 of the temperature value are in bits 7 - 5 of the | ||
214 | * temperature LSB register | ||
215 | */ | ||
216 | temp_raw = ((val[0]) << 3) | | ||
217 | (val[1] >> 5); | ||
218 | *temp = temp_raw + (temp_raw / 4); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int ds2781_get_current(struct ds2781_device_info *dev_info, | ||
224 | enum current_types type, int *current_uA) | ||
225 | { | ||
226 | int ret, sense_res; | ||
227 | s16 current_raw; | ||
228 | u8 sense_res_raw, reg_msb; | ||
229 | |||
230 | /* | ||
231 | * The units of measurement for current are dependent on the value of | ||
232 | * the sense resistor. | ||
233 | */ | ||
234 | ret = ds2781_read8(dev_info, &sense_res_raw, DS2781_RSNSP); | ||
235 | if (ret < 0) | ||
236 | return ret; | ||
237 | |||
238 | if (sense_res_raw == 0) { | ||
239 | dev_err(dev_info->dev, "sense resistor value is 0\n"); | ||
240 | return -EINVAL; | ||
241 | } | ||
242 | sense_res = 1000 / sense_res_raw; | ||
243 | |||
244 | if (type == CURRENT_NOW) | ||
245 | reg_msb = DS2781_CURRENT_MSB; | ||
246 | else if (type == CURRENT_AVG) | ||
247 | reg_msb = DS2781_IAVG_MSB; | ||
248 | else | ||
249 | return -EINVAL; | ||
250 | |||
251 | /* | ||
252 | * The current value is located in 16 bits across the current MSB | ||
253 | * and LSB registers in two's compliment form | ||
254 | * Sign bit of the current value is in bit 7 of the current MSB register | ||
255 | * Bits 14 - 8 of the current value are in bits 6 - 0 of the current | ||
256 | * MSB register | ||
257 | * Bits 7 - 0 of the current value are in bits 7 - 0 of the current | ||
258 | * LSB register | ||
259 | */ | ||
260 | ret = ds2781_read16(dev_info, ¤t_raw, reg_msb); | ||
261 | if (ret < 0) | ||
262 | return ret; | ||
263 | |||
264 | *current_uA = current_raw * (DS2781_CURRENT_UNITS / sense_res); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static int ds2781_get_accumulated_current(struct ds2781_device_info *dev_info, | ||
269 | int *accumulated_current) | ||
270 | { | ||
271 | int ret, sense_res; | ||
272 | s16 current_raw; | ||
273 | u8 sense_res_raw; | ||
274 | |||
275 | /* | ||
276 | * The units of measurement for accumulated current are dependent on | ||
277 | * the value of the sense resistor. | ||
278 | */ | ||
279 | ret = ds2781_read8(dev_info, &sense_res_raw, DS2781_RSNSP); | ||
280 | if (ret < 0) | ||
281 | return ret; | ||
282 | |||
283 | if (sense_res_raw == 0) { | ||
284 | dev_err(dev_info->dev, "sense resistor value is 0\n"); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | sense_res = 1000 / sense_res_raw; | ||
288 | |||
289 | /* | ||
290 | * The ACR value is located in 16 bits across the ACR MSB and | ||
291 | * LSB registers | ||
292 | * Bits 15 - 8 of the ACR value are in bits 7 - 0 of the ACR | ||
293 | * MSB register | ||
294 | * Bits 7 - 0 of the ACR value are in bits 7 - 0 of the ACR | ||
295 | * LSB register | ||
296 | */ | ||
297 | ret = ds2781_read16(dev_info, ¤t_raw, DS2781_ACR_MSB); | ||
298 | if (ret < 0) | ||
299 | return ret; | ||
300 | |||
301 | *accumulated_current = current_raw * (DS2781_CHARGE_UNITS / sense_res); | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static int ds2781_get_capacity(struct ds2781_device_info *dev_info, | ||
306 | int *capacity) | ||
307 | { | ||
308 | int ret; | ||
309 | u8 raw; | ||
310 | |||
311 | ret = ds2781_read8(dev_info, &raw, DS2781_RARC); | ||
312 | if (ret < 0) | ||
313 | return ret; | ||
314 | |||
315 | *capacity = raw; | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int ds2781_get_status(struct ds2781_device_info *dev_info, int *status) | ||
320 | { | ||
321 | int ret, current_uA, capacity; | ||
322 | |||
323 | ret = ds2781_get_current(dev_info, CURRENT_NOW, ¤t_uA); | ||
324 | if (ret < 0) | ||
325 | return ret; | ||
326 | |||
327 | ret = ds2781_get_capacity(dev_info, &capacity); | ||
328 | if (ret < 0) | ||
329 | return ret; | ||
330 | |||
331 | if (power_supply_am_i_supplied(&dev_info->bat)) { | ||
332 | if (capacity == 100) | ||
333 | *status = POWER_SUPPLY_STATUS_FULL; | ||
334 | else if (current_uA > 50000) | ||
335 | *status = POWER_SUPPLY_STATUS_CHARGING; | ||
336 | else | ||
337 | *status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
338 | } else { | ||
339 | *status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
340 | } | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static int ds2781_get_charge_now(struct ds2781_device_info *dev_info, | ||
345 | int *charge_now) | ||
346 | { | ||
347 | int ret; | ||
348 | u16 charge_raw; | ||
349 | |||
350 | /* | ||
351 | * The RAAC value is located in 16 bits across the RAAC MSB and | ||
352 | * LSB registers | ||
353 | * Bits 15 - 8 of the RAAC value are in bits 7 - 0 of the RAAC | ||
354 | * MSB register | ||
355 | * Bits 7 - 0 of the RAAC value are in bits 7 - 0 of the RAAC | ||
356 | * LSB register | ||
357 | */ | ||
358 | ret = ds2781_read16(dev_info, &charge_raw, DS2781_RAAC_MSB); | ||
359 | if (ret < 0) | ||
360 | return ret; | ||
361 | |||
362 | *charge_now = charge_raw * 1600; | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static int ds2781_get_control_register(struct ds2781_device_info *dev_info, | ||
367 | u8 *control_reg) | ||
368 | { | ||
369 | return ds2781_read8(dev_info, control_reg, DS2781_CONTROL); | ||
370 | } | ||
371 | |||
372 | static int ds2781_set_control_register(struct ds2781_device_info *dev_info, | ||
373 | u8 control_reg) | ||
374 | { | ||
375 | int ret; | ||
376 | |||
377 | ret = ds2781_write(dev_info, &control_reg, | ||
378 | DS2781_CONTROL, sizeof(u8)); | ||
379 | if (ret < 0) | ||
380 | return ret; | ||
381 | |||
382 | return ds2781_save_eeprom(dev_info, DS2781_CONTROL); | ||
383 | } | ||
384 | |||
385 | static int ds2781_battery_get_property(struct power_supply *psy, | ||
386 | enum power_supply_property psp, | ||
387 | union power_supply_propval *val) | ||
388 | { | ||
389 | int ret = 0; | ||
390 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
391 | |||
392 | switch (psp) { | ||
393 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
394 | ret = ds2781_get_voltage(dev_info, &val->intval); | ||
395 | break; | ||
396 | |||
397 | case POWER_SUPPLY_PROP_TEMP: | ||
398 | ret = ds2781_get_temperature(dev_info, &val->intval); | ||
399 | break; | ||
400 | |||
401 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
402 | val->strval = model; | ||
403 | break; | ||
404 | |||
405 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
406 | val->strval = manufacturer; | ||
407 | break; | ||
408 | |||
409 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
410 | ret = ds2781_get_current(dev_info, CURRENT_NOW, &val->intval); | ||
411 | break; | ||
412 | |||
413 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
414 | ret = ds2781_get_current(dev_info, CURRENT_AVG, &val->intval); | ||
415 | break; | ||
416 | |||
417 | case POWER_SUPPLY_PROP_STATUS: | ||
418 | ret = ds2781_get_status(dev_info, &val->intval); | ||
419 | break; | ||
420 | |||
421 | case POWER_SUPPLY_PROP_CAPACITY: | ||
422 | ret = ds2781_get_capacity(dev_info, &val->intval); | ||
423 | break; | ||
424 | |||
425 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: | ||
426 | ret = ds2781_get_accumulated_current(dev_info, &val->intval); | ||
427 | break; | ||
428 | |||
429 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
430 | ret = ds2781_get_charge_now(dev_info, &val->intval); | ||
431 | break; | ||
432 | |||
433 | default: | ||
434 | ret = -EINVAL; | ||
435 | } | ||
436 | |||
437 | return ret; | ||
438 | } | ||
439 | |||
440 | static enum power_supply_property ds2781_battery_props[] = { | ||
441 | POWER_SUPPLY_PROP_STATUS, | ||
442 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
443 | POWER_SUPPLY_PROP_TEMP, | ||
444 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
445 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
446 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
447 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
448 | POWER_SUPPLY_PROP_CAPACITY, | ||
449 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | ||
450 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
451 | }; | ||
452 | |||
453 | static ssize_t ds2781_get_pmod_enabled(struct device *dev, | ||
454 | struct device_attribute *attr, | ||
455 | char *buf) | ||
456 | { | ||
457 | int ret; | ||
458 | u8 control_reg; | ||
459 | struct power_supply *psy = to_power_supply(dev); | ||
460 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
461 | |||
462 | /* Get power mode */ | ||
463 | ret = ds2781_get_control_register(dev_info, &control_reg); | ||
464 | if (ret < 0) | ||
465 | return ret; | ||
466 | |||
467 | return sprintf(buf, "%d\n", | ||
468 | !!(control_reg & DS2781_CONTROL_PMOD)); | ||
469 | } | ||
470 | |||
471 | static ssize_t ds2781_set_pmod_enabled(struct device *dev, | ||
472 | struct device_attribute *attr, | ||
473 | const char *buf, | ||
474 | size_t count) | ||
475 | { | ||
476 | int ret; | ||
477 | u8 control_reg, new_setting; | ||
478 | struct power_supply *psy = to_power_supply(dev); | ||
479 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
480 | |||
481 | /* Set power mode */ | ||
482 | ret = ds2781_get_control_register(dev_info, &control_reg); | ||
483 | if (ret < 0) | ||
484 | return ret; | ||
485 | |||
486 | ret = kstrtou8(buf, 0, &new_setting); | ||
487 | if (ret < 0) | ||
488 | return ret; | ||
489 | |||
490 | if ((new_setting != 0) && (new_setting != 1)) { | ||
491 | dev_err(dev_info->dev, "Invalid pmod setting (0 or 1)\n"); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | if (new_setting) | ||
496 | control_reg |= DS2781_CONTROL_PMOD; | ||
497 | else | ||
498 | control_reg &= ~DS2781_CONTROL_PMOD; | ||
499 | |||
500 | ret = ds2781_set_control_register(dev_info, control_reg); | ||
501 | if (ret < 0) | ||
502 | return ret; | ||
503 | |||
504 | return count; | ||
505 | } | ||
506 | |||
507 | static ssize_t ds2781_get_sense_resistor_value(struct device *dev, | ||
508 | struct device_attribute *attr, | ||
509 | char *buf) | ||
510 | { | ||
511 | int ret; | ||
512 | u8 sense_resistor; | ||
513 | struct power_supply *psy = to_power_supply(dev); | ||
514 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
515 | |||
516 | ret = ds2781_read8(dev_info, &sense_resistor, DS2781_RSNSP); | ||
517 | if (ret < 0) | ||
518 | return ret; | ||
519 | |||
520 | ret = sprintf(buf, "%d\n", sense_resistor); | ||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | static ssize_t ds2781_set_sense_resistor_value(struct device *dev, | ||
525 | struct device_attribute *attr, | ||
526 | const char *buf, | ||
527 | size_t count) | ||
528 | { | ||
529 | int ret; | ||
530 | u8 new_setting; | ||
531 | struct power_supply *psy = to_power_supply(dev); | ||
532 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
533 | |||
534 | ret = kstrtou8(buf, 0, &new_setting); | ||
535 | if (ret < 0) | ||
536 | return ret; | ||
537 | |||
538 | ret = ds2781_set_sense_register(dev_info, new_setting); | ||
539 | if (ret < 0) | ||
540 | return ret; | ||
541 | |||
542 | return count; | ||
543 | } | ||
544 | |||
545 | static ssize_t ds2781_get_rsgain_setting(struct device *dev, | ||
546 | struct device_attribute *attr, | ||
547 | char *buf) | ||
548 | { | ||
549 | int ret; | ||
550 | u16 rsgain; | ||
551 | struct power_supply *psy = to_power_supply(dev); | ||
552 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
553 | |||
554 | ret = ds2781_get_rsgain_register(dev_info, &rsgain); | ||
555 | if (ret < 0) | ||
556 | return ret; | ||
557 | |||
558 | return sprintf(buf, "%d\n", rsgain); | ||
559 | } | ||
560 | |||
561 | static ssize_t ds2781_set_rsgain_setting(struct device *dev, | ||
562 | struct device_attribute *attr, | ||
563 | const char *buf, | ||
564 | size_t count) | ||
565 | { | ||
566 | int ret; | ||
567 | u16 new_setting; | ||
568 | struct power_supply *psy = to_power_supply(dev); | ||
569 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
570 | |||
571 | ret = kstrtou16(buf, 0, &new_setting); | ||
572 | if (ret < 0) | ||
573 | return ret; | ||
574 | |||
575 | /* Gain can only be from 0 to 1.999 in steps of .001 */ | ||
576 | if (new_setting > 1999) { | ||
577 | dev_err(dev_info->dev, "Invalid rsgain setting (0 - 1999)\n"); | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | ret = ds2781_set_rsgain_register(dev_info, new_setting); | ||
582 | if (ret < 0) | ||
583 | return ret; | ||
584 | |||
585 | return count; | ||
586 | } | ||
587 | |||
588 | static ssize_t ds2781_get_pio_pin(struct device *dev, | ||
589 | struct device_attribute *attr, | ||
590 | char *buf) | ||
591 | { | ||
592 | int ret; | ||
593 | u8 sfr; | ||
594 | struct power_supply *psy = to_power_supply(dev); | ||
595 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
596 | |||
597 | ret = ds2781_read8(dev_info, &sfr, DS2781_SFR); | ||
598 | if (ret < 0) | ||
599 | return ret; | ||
600 | |||
601 | ret = sprintf(buf, "%d\n", sfr & DS2781_SFR_PIOSC); | ||
602 | return ret; | ||
603 | } | ||
604 | |||
605 | static ssize_t ds2781_set_pio_pin(struct device *dev, | ||
606 | struct device_attribute *attr, | ||
607 | const char *buf, | ||
608 | size_t count) | ||
609 | { | ||
610 | int ret; | ||
611 | u8 new_setting; | ||
612 | struct power_supply *psy = to_power_supply(dev); | ||
613 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
614 | |||
615 | ret = kstrtou8(buf, 0, &new_setting); | ||
616 | if (ret < 0) | ||
617 | return ret; | ||
618 | |||
619 | if ((new_setting != 0) && (new_setting != 1)) { | ||
620 | dev_err(dev_info->dev, "Invalid pio_pin setting (0 or 1)\n"); | ||
621 | return -EINVAL; | ||
622 | } | ||
623 | |||
624 | ret = ds2781_write(dev_info, &new_setting, | ||
625 | DS2781_SFR, sizeof(u8)); | ||
626 | if (ret < 0) | ||
627 | return ret; | ||
628 | |||
629 | return count; | ||
630 | } | ||
631 | |||
632 | static ssize_t ds2781_read_param_eeprom_bin(struct file *filp, | ||
633 | struct kobject *kobj, | ||
634 | struct bin_attribute *bin_attr, | ||
635 | char *buf, loff_t off, size_t count) | ||
636 | { | ||
637 | struct device *dev = container_of(kobj, struct device, kobj); | ||
638 | struct power_supply *psy = to_power_supply(dev); | ||
639 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
640 | |||
641 | count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off); | ||
642 | |||
643 | return ds2781_read_block(dev_info, buf, | ||
644 | DS2781_EEPROM_BLOCK1_START + off, count); | ||
645 | } | ||
646 | |||
647 | static ssize_t ds2781_write_param_eeprom_bin(struct file *filp, | ||
648 | struct kobject *kobj, | ||
649 | struct bin_attribute *bin_attr, | ||
650 | char *buf, loff_t off, size_t count) | ||
651 | { | ||
652 | struct device *dev = container_of(kobj, struct device, kobj); | ||
653 | struct power_supply *psy = to_power_supply(dev); | ||
654 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
655 | int ret; | ||
656 | |||
657 | count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off); | ||
658 | |||
659 | ret = ds2781_write(dev_info, buf, | ||
660 | DS2781_EEPROM_BLOCK1_START + off, count); | ||
661 | if (ret < 0) | ||
662 | return ret; | ||
663 | |||
664 | ret = ds2781_save_eeprom(dev_info, DS2781_EEPROM_BLOCK1_START); | ||
665 | if (ret < 0) | ||
666 | return ret; | ||
667 | |||
668 | return count; | ||
669 | } | ||
670 | |||
671 | static struct bin_attribute ds2781_param_eeprom_bin_attr = { | ||
672 | .attr = { | ||
673 | .name = "param_eeprom", | ||
674 | .mode = S_IRUGO | S_IWUSR, | ||
675 | }, | ||
676 | .size = DS2781_PARAM_EEPROM_SIZE, | ||
677 | .read = ds2781_read_param_eeprom_bin, | ||
678 | .write = ds2781_write_param_eeprom_bin, | ||
679 | }; | ||
680 | |||
681 | static ssize_t ds2781_read_user_eeprom_bin(struct file *filp, | ||
682 | struct kobject *kobj, | ||
683 | struct bin_attribute *bin_attr, | ||
684 | char *buf, loff_t off, size_t count) | ||
685 | { | ||
686 | struct device *dev = container_of(kobj, struct device, kobj); | ||
687 | struct power_supply *psy = to_power_supply(dev); | ||
688 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
689 | |||
690 | count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off); | ||
691 | |||
692 | return ds2781_read_block(dev_info, buf, | ||
693 | DS2781_EEPROM_BLOCK0_START + off, count); | ||
694 | |||
695 | } | ||
696 | |||
697 | static ssize_t ds2781_write_user_eeprom_bin(struct file *filp, | ||
698 | struct kobject *kobj, | ||
699 | struct bin_attribute *bin_attr, | ||
700 | char *buf, loff_t off, size_t count) | ||
701 | { | ||
702 | struct device *dev = container_of(kobj, struct device, kobj); | ||
703 | struct power_supply *psy = to_power_supply(dev); | ||
704 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
705 | int ret; | ||
706 | |||
707 | count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off); | ||
708 | |||
709 | ret = ds2781_write(dev_info, buf, | ||
710 | DS2781_EEPROM_BLOCK0_START + off, count); | ||
711 | if (ret < 0) | ||
712 | return ret; | ||
713 | |||
714 | ret = ds2781_save_eeprom(dev_info, DS2781_EEPROM_BLOCK0_START); | ||
715 | if (ret < 0) | ||
716 | return ret; | ||
717 | |||
718 | return count; | ||
719 | } | ||
720 | |||
721 | static struct bin_attribute ds2781_user_eeprom_bin_attr = { | ||
722 | .attr = { | ||
723 | .name = "user_eeprom", | ||
724 | .mode = S_IRUGO | S_IWUSR, | ||
725 | }, | ||
726 | .size = DS2781_USER_EEPROM_SIZE, | ||
727 | .read = ds2781_read_user_eeprom_bin, | ||
728 | .write = ds2781_write_user_eeprom_bin, | ||
729 | }; | ||
730 | |||
731 | static DEVICE_ATTR(pmod_enabled, S_IRUGO | S_IWUSR, ds2781_get_pmod_enabled, | ||
732 | ds2781_set_pmod_enabled); | ||
733 | static DEVICE_ATTR(sense_resistor_value, S_IRUGO | S_IWUSR, | ||
734 | ds2781_get_sense_resistor_value, ds2781_set_sense_resistor_value); | ||
735 | static DEVICE_ATTR(rsgain_setting, S_IRUGO | S_IWUSR, ds2781_get_rsgain_setting, | ||
736 | ds2781_set_rsgain_setting); | ||
737 | static DEVICE_ATTR(pio_pin, S_IRUGO | S_IWUSR, ds2781_get_pio_pin, | ||
738 | ds2781_set_pio_pin); | ||
739 | |||
740 | |||
741 | static struct attribute *ds2781_attributes[] = { | ||
742 | &dev_attr_pmod_enabled.attr, | ||
743 | &dev_attr_sense_resistor_value.attr, | ||
744 | &dev_attr_rsgain_setting.attr, | ||
745 | &dev_attr_pio_pin.attr, | ||
746 | NULL | ||
747 | }; | ||
748 | |||
749 | static const struct attribute_group ds2781_attr_group = { | ||
750 | .attrs = ds2781_attributes, | ||
751 | }; | ||
752 | |||
753 | static int ds2781_battery_probe(struct platform_device *pdev) | ||
754 | { | ||
755 | int ret = 0; | ||
756 | struct ds2781_device_info *dev_info; | ||
757 | |||
758 | dev_info = devm_kzalloc(&pdev->dev, sizeof(*dev_info), GFP_KERNEL); | ||
759 | if (!dev_info) | ||
760 | return -ENOMEM; | ||
761 | |||
762 | platform_set_drvdata(pdev, dev_info); | ||
763 | |||
764 | dev_info->dev = &pdev->dev; | ||
765 | dev_info->w1_dev = pdev->dev.parent; | ||
766 | dev_info->bat.name = dev_name(&pdev->dev); | ||
767 | dev_info->bat.type = POWER_SUPPLY_TYPE_BATTERY; | ||
768 | dev_info->bat.properties = ds2781_battery_props; | ||
769 | dev_info->bat.num_properties = ARRAY_SIZE(ds2781_battery_props); | ||
770 | dev_info->bat.get_property = ds2781_battery_get_property; | ||
771 | |||
772 | ret = power_supply_register(&pdev->dev, &dev_info->bat); | ||
773 | if (ret) { | ||
774 | dev_err(dev_info->dev, "failed to register battery\n"); | ||
775 | goto fail; | ||
776 | } | ||
777 | |||
778 | ret = sysfs_create_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); | ||
779 | if (ret) { | ||
780 | dev_err(dev_info->dev, "failed to create sysfs group\n"); | ||
781 | goto fail_unregister; | ||
782 | } | ||
783 | |||
784 | ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj, | ||
785 | &ds2781_param_eeprom_bin_attr); | ||
786 | if (ret) { | ||
787 | dev_err(dev_info->dev, | ||
788 | "failed to create param eeprom bin file"); | ||
789 | goto fail_remove_group; | ||
790 | } | ||
791 | |||
792 | ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj, | ||
793 | &ds2781_user_eeprom_bin_attr); | ||
794 | if (ret) { | ||
795 | dev_err(dev_info->dev, | ||
796 | "failed to create user eeprom bin file"); | ||
797 | goto fail_remove_bin_file; | ||
798 | } | ||
799 | |||
800 | return 0; | ||
801 | |||
802 | fail_remove_bin_file: | ||
803 | sysfs_remove_bin_file(&dev_info->bat.dev->kobj, | ||
804 | &ds2781_param_eeprom_bin_attr); | ||
805 | fail_remove_group: | ||
806 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); | ||
807 | fail_unregister: | ||
808 | power_supply_unregister(&dev_info->bat); | ||
809 | fail: | ||
810 | return ret; | ||
811 | } | ||
812 | |||
813 | static int ds2781_battery_remove(struct platform_device *pdev) | ||
814 | { | ||
815 | struct ds2781_device_info *dev_info = platform_get_drvdata(pdev); | ||
816 | |||
817 | /* remove attributes */ | ||
818 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); | ||
819 | |||
820 | power_supply_unregister(&dev_info->bat); | ||
821 | |||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | static struct platform_driver ds2781_battery_driver = { | ||
826 | .driver = { | ||
827 | .name = "ds2781-battery", | ||
828 | }, | ||
829 | .probe = ds2781_battery_probe, | ||
830 | .remove = ds2781_battery_remove, | ||
831 | }; | ||
832 | module_platform_driver(ds2781_battery_driver); | ||
833 | |||
834 | MODULE_LICENSE("GPL"); | ||
835 | MODULE_AUTHOR("Renata Sayakhova <renata@oktetlabs.ru>"); | ||
836 | MODULE_DESCRIPTION("Maxim/Dallas DS2781 Stand-Alone Fuel Gauage IC driver"); | ||
837 | MODULE_ALIAS("platform:ds2781-battery"); | ||
838 | |||
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 2fa9b6bf1f3..bfbce5de49d 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c | |||
@@ -80,13 +80,13 @@ static inline int ds278x_read_reg16(struct ds278x_info *info, int reg_msb, | |||
80 | { | 80 | { |
81 | int ret; | 81 | int ret; |
82 | 82 | ||
83 | ret = i2c_smbus_read_word_data(info->client, reg_msb); | 83 | ret = swab16(i2c_smbus_read_word_data(info->client, reg_msb)); |
84 | if (ret < 0) { | 84 | if (ret < 0) { |
85 | dev_err(&info->client->dev, "register read failed\n"); | 85 | dev_err(&info->client->dev, "register read failed\n"); |
86 | return ret; | 86 | return ret; |
87 | } | 87 | } |
88 | 88 | ||
89 | *val = swab16(ret); | 89 | *val = ret; |
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
@@ -403,7 +403,18 @@ static struct i2c_driver ds278x_battery_driver = { | |||
403 | .remove = ds278x_battery_remove, | 403 | .remove = ds278x_battery_remove, |
404 | .id_table = ds278x_id, | 404 | .id_table = ds278x_id, |
405 | }; | 405 | }; |
406 | module_i2c_driver(ds278x_battery_driver); | 406 | |
407 | static int __init ds278x_init(void) | ||
408 | { | ||
409 | return i2c_add_driver(&ds278x_battery_driver); | ||
410 | } | ||
411 | module_init(ds278x_init); | ||
412 | |||
413 | static void __exit ds278x_exit(void) | ||
414 | { | ||
415 | i2c_del_driver(&ds278x_battery_driver); | ||
416 | } | ||
417 | module_exit(ds278x_exit); | ||
407 | 418 | ||
408 | MODULE_AUTHOR("Ryan Mallon"); | 419 | MODULE_AUTHOR("Ryan Mallon"); |
409 | MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver"); | 420 | MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver"); |
diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c deleted file mode 100644 index 32ce17e235c..00000000000 --- a/drivers/power/generic-adc-battery.c +++ /dev/null | |||
@@ -1,423 +0,0 @@ | |||
1 | /* | ||
2 | * Generic battery driver code using IIO | ||
3 | * Copyright (C) 2012, Anish Kumar <anish198519851985@gmail.com> | ||
4 | * based on jz4740-battery.c | ||
5 | * based on s3c_adc_battery.c | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file COPYING in the main directory of this archive for | ||
9 | * more details. | ||
10 | * | ||
11 | */ | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/power_supply.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/timer.h> | ||
18 | #include <linux/jiffies.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/iio/consumer.h> | ||
24 | #include <linux/iio/types.h> | ||
25 | #include <linux/power/generic-adc-battery.h> | ||
26 | |||
27 | #define JITTER_DEFAULT 10 /* hope 10ms is enough */ | ||
28 | |||
29 | enum gab_chan_type { | ||
30 | GAB_VOLTAGE = 0, | ||
31 | GAB_CURRENT, | ||
32 | GAB_POWER, | ||
33 | GAB_MAX_CHAN_TYPE | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * gab_chan_name suggests the standard channel names for commonly used | ||
38 | * channel types. | ||
39 | */ | ||
40 | static const char *const gab_chan_name[] = { | ||
41 | [GAB_VOLTAGE] = "voltage", | ||
42 | [GAB_CURRENT] = "current", | ||
43 | [GAB_POWER] = "power", | ||
44 | }; | ||
45 | |||
46 | struct gab { | ||
47 | struct power_supply psy; | ||
48 | struct iio_channel *channel[GAB_MAX_CHAN_TYPE]; | ||
49 | struct gab_platform_data *pdata; | ||
50 | struct delayed_work bat_work; | ||
51 | int level; | ||
52 | int status; | ||
53 | bool cable_plugged; | ||
54 | }; | ||
55 | |||
56 | static struct gab *to_generic_bat(struct power_supply *psy) | ||
57 | { | ||
58 | return container_of(psy, struct gab, psy); | ||
59 | } | ||
60 | |||
61 | static void gab_ext_power_changed(struct power_supply *psy) | ||
62 | { | ||
63 | struct gab *adc_bat = to_generic_bat(psy); | ||
64 | |||
65 | schedule_delayed_work(&adc_bat->bat_work, msecs_to_jiffies(0)); | ||
66 | } | ||
67 | |||
68 | static const enum power_supply_property gab_props[] = { | ||
69 | POWER_SUPPLY_PROP_STATUS, | ||
70 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
71 | POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN, | ||
72 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
73 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
74 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
75 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
76 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | ||
77 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
78 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
79 | }; | ||
80 | |||
81 | /* | ||
82 | * This properties are set based on the received platform data and this | ||
83 | * should correspond one-to-one with enum chan_type. | ||
84 | */ | ||
85 | static const enum power_supply_property gab_dyn_props[] = { | ||
86 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
87 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
88 | POWER_SUPPLY_PROP_POWER_NOW, | ||
89 | }; | ||
90 | |||
91 | static bool gab_charge_finished(struct gab *adc_bat) | ||
92 | { | ||
93 | struct gab_platform_data *pdata = adc_bat->pdata; | ||
94 | bool ret = gpio_get_value(pdata->gpio_charge_finished); | ||
95 | bool inv = pdata->gpio_inverted; | ||
96 | |||
97 | if (!gpio_is_valid(pdata->gpio_charge_finished)) | ||
98 | return false; | ||
99 | return ret ^ inv; | ||
100 | } | ||
101 | |||
102 | static int gab_get_status(struct gab *adc_bat) | ||
103 | { | ||
104 | struct gab_platform_data *pdata = adc_bat->pdata; | ||
105 | struct power_supply_info *bat_info; | ||
106 | |||
107 | bat_info = &pdata->battery_info; | ||
108 | if (adc_bat->level == bat_info->charge_full_design) | ||
109 | return POWER_SUPPLY_STATUS_FULL; | ||
110 | return adc_bat->status; | ||
111 | } | ||
112 | |||
113 | static enum gab_chan_type gab_prop_to_chan(enum power_supply_property psp) | ||
114 | { | ||
115 | switch (psp) { | ||
116 | case POWER_SUPPLY_PROP_POWER_NOW: | ||
117 | return GAB_POWER; | ||
118 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
119 | return GAB_VOLTAGE; | ||
120 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
121 | return GAB_CURRENT; | ||
122 | default: | ||
123 | WARN_ON(1); | ||
124 | break; | ||
125 | } | ||
126 | return GAB_POWER; | ||
127 | } | ||
128 | |||
129 | static int read_channel(struct gab *adc_bat, enum power_supply_property psp, | ||
130 | int *result) | ||
131 | { | ||
132 | int ret; | ||
133 | int chan_index; | ||
134 | |||
135 | chan_index = gab_prop_to_chan(psp); | ||
136 | ret = iio_read_channel_processed(adc_bat->channel[chan_index], | ||
137 | result); | ||
138 | if (ret < 0) | ||
139 | pr_err("read channel error\n"); | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | static int gab_get_property(struct power_supply *psy, | ||
144 | enum power_supply_property psp, union power_supply_propval *val) | ||
145 | { | ||
146 | struct gab *adc_bat; | ||
147 | struct gab_platform_data *pdata; | ||
148 | struct power_supply_info *bat_info; | ||
149 | int result = 0; | ||
150 | int ret = 0; | ||
151 | |||
152 | adc_bat = to_generic_bat(psy); | ||
153 | if (!adc_bat) { | ||
154 | dev_err(psy->dev, "no battery infos ?!\n"); | ||
155 | return -EINVAL; | ||
156 | } | ||
157 | pdata = adc_bat->pdata; | ||
158 | bat_info = &pdata->battery_info; | ||
159 | |||
160 | switch (psp) { | ||
161 | case POWER_SUPPLY_PROP_STATUS: | ||
162 | gab_get_status(adc_bat); | ||
163 | break; | ||
164 | case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN: | ||
165 | val->intval = 0; | ||
166 | break; | ||
167 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
168 | val->intval = pdata->cal_charge(result); | ||
169 | break; | ||
170 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
171 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
172 | case POWER_SUPPLY_PROP_POWER_NOW: | ||
173 | ret = read_channel(adc_bat, psp, &result); | ||
174 | if (ret < 0) | ||
175 | goto err; | ||
176 | val->intval = result; | ||
177 | break; | ||
178 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
179 | val->intval = bat_info->technology; | ||
180 | break; | ||
181 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | ||
182 | val->intval = bat_info->voltage_min_design; | ||
183 | break; | ||
184 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
185 | val->intval = bat_info->voltage_max_design; | ||
186 | break; | ||
187 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
188 | val->intval = bat_info->charge_full_design; | ||
189 | break; | ||
190 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
191 | val->strval = bat_info->name; | ||
192 | break; | ||
193 | default: | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | err: | ||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | static void gab_work(struct work_struct *work) | ||
201 | { | ||
202 | struct gab *adc_bat; | ||
203 | struct gab_platform_data *pdata; | ||
204 | struct delayed_work *delayed_work; | ||
205 | bool is_plugged; | ||
206 | int status; | ||
207 | |||
208 | delayed_work = container_of(work, struct delayed_work, work); | ||
209 | adc_bat = container_of(delayed_work, struct gab, bat_work); | ||
210 | pdata = adc_bat->pdata; | ||
211 | status = adc_bat->status; | ||
212 | |||
213 | is_plugged = power_supply_am_i_supplied(&adc_bat->psy); | ||
214 | adc_bat->cable_plugged = is_plugged; | ||
215 | |||
216 | if (!is_plugged) | ||
217 | adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
218 | else if (gab_charge_finished(adc_bat)) | ||
219 | adc_bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
220 | else | ||
221 | adc_bat->status = POWER_SUPPLY_STATUS_CHARGING; | ||
222 | |||
223 | if (status != adc_bat->status) | ||
224 | power_supply_changed(&adc_bat->psy); | ||
225 | } | ||
226 | |||
227 | static irqreturn_t gab_charged(int irq, void *dev_id) | ||
228 | { | ||
229 | struct gab *adc_bat = dev_id; | ||
230 | struct gab_platform_data *pdata = adc_bat->pdata; | ||
231 | int delay; | ||
232 | |||
233 | delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT; | ||
234 | schedule_delayed_work(&adc_bat->bat_work, | ||
235 | msecs_to_jiffies(delay)); | ||
236 | return IRQ_HANDLED; | ||
237 | } | ||
238 | |||
239 | static int gab_probe(struct platform_device *pdev) | ||
240 | { | ||
241 | struct gab *adc_bat; | ||
242 | struct power_supply *psy; | ||
243 | struct gab_platform_data *pdata = pdev->dev.platform_data; | ||
244 | enum power_supply_property *properties; | ||
245 | int ret = 0; | ||
246 | int chan; | ||
247 | int index = 0; | ||
248 | |||
249 | adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL); | ||
250 | if (!adc_bat) { | ||
251 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
252 | return -ENOMEM; | ||
253 | } | ||
254 | |||
255 | psy = &adc_bat->psy; | ||
256 | psy->name = pdata->battery_info.name; | ||
257 | |||
258 | /* bootup default values for the battery */ | ||
259 | adc_bat->cable_plugged = false; | ||
260 | adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
261 | psy->type = POWER_SUPPLY_TYPE_BATTERY; | ||
262 | psy->get_property = gab_get_property; | ||
263 | psy->external_power_changed = gab_ext_power_changed; | ||
264 | adc_bat->pdata = pdata; | ||
265 | |||
266 | /* calculate the total number of channels */ | ||
267 | chan = ARRAY_SIZE(gab_chan_name); | ||
268 | |||
269 | /* | ||
270 | * copying the static properties and allocating extra memory for holding | ||
271 | * the extra configurable properties received from platform data. | ||
272 | */ | ||
273 | psy->properties = kcalloc(ARRAY_SIZE(gab_props) + | ||
274 | ARRAY_SIZE(gab_chan_name), | ||
275 | sizeof(*psy->properties), GFP_KERNEL); | ||
276 | if (!psy->properties) { | ||
277 | ret = -ENOMEM; | ||
278 | goto first_mem_fail; | ||
279 | } | ||
280 | |||
281 | memcpy(psy->properties, gab_props, sizeof(gab_props)); | ||
282 | properties = (enum power_supply_property *) | ||
283 | ((char *)psy->properties + sizeof(gab_props)); | ||
284 | |||
285 | /* | ||
286 | * getting channel from iio and copying the battery properties | ||
287 | * based on the channel supported by consumer device. | ||
288 | */ | ||
289 | for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) { | ||
290 | adc_bat->channel[chan] = iio_channel_get(dev_name(&pdev->dev), | ||
291 | gab_chan_name[chan]); | ||
292 | if (IS_ERR(adc_bat->channel[chan])) { | ||
293 | ret = PTR_ERR(adc_bat->channel[chan]); | ||
294 | } else { | ||
295 | /* copying properties for supported channels only */ | ||
296 | memcpy(properties + sizeof(*(psy->properties)) * index, | ||
297 | &gab_dyn_props[chan], | ||
298 | sizeof(gab_dyn_props[chan])); | ||
299 | index++; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | /* none of the channels are supported so let's bail out */ | ||
304 | if (index == ARRAY_SIZE(gab_chan_name)) | ||
305 | goto second_mem_fail; | ||
306 | |||
307 | /* | ||
308 | * Total number of properties is equal to static properties | ||
309 | * plus the dynamic properties.Some properties may not be set | ||
310 | * as come channels may be not be supported by the device.So | ||
311 | * we need to take care of that. | ||
312 | */ | ||
313 | psy->num_properties = ARRAY_SIZE(gab_props) + index; | ||
314 | |||
315 | ret = power_supply_register(&pdev->dev, psy); | ||
316 | if (ret) | ||
317 | goto err_reg_fail; | ||
318 | |||
319 | INIT_DELAYED_WORK(&adc_bat->bat_work, gab_work); | ||
320 | |||
321 | if (gpio_is_valid(pdata->gpio_charge_finished)) { | ||
322 | int irq; | ||
323 | ret = gpio_request(pdata->gpio_charge_finished, "charged"); | ||
324 | if (ret) | ||
325 | goto gpio_req_fail; | ||
326 | |||
327 | irq = gpio_to_irq(pdata->gpio_charge_finished); | ||
328 | ret = request_any_context_irq(irq, gab_charged, | ||
329 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
330 | "battery charged", adc_bat); | ||
331 | if (ret < 0) | ||
332 | goto err_gpio; | ||
333 | } | ||
334 | |||
335 | platform_set_drvdata(pdev, adc_bat); | ||
336 | |||
337 | /* Schedule timer to check current status */ | ||
338 | schedule_delayed_work(&adc_bat->bat_work, | ||
339 | msecs_to_jiffies(0)); | ||
340 | return 0; | ||
341 | |||
342 | err_gpio: | ||
343 | gpio_free(pdata->gpio_charge_finished); | ||
344 | gpio_req_fail: | ||
345 | power_supply_unregister(psy); | ||
346 | err_reg_fail: | ||
347 | for (chan = 0; ARRAY_SIZE(gab_chan_name); chan++) | ||
348 | iio_channel_release(adc_bat->channel[chan]); | ||
349 | second_mem_fail: | ||
350 | kfree(psy->properties); | ||
351 | first_mem_fail: | ||
352 | return ret; | ||
353 | } | ||
354 | |||
355 | static int gab_remove(struct platform_device *pdev) | ||
356 | { | ||
357 | int chan; | ||
358 | struct gab *adc_bat = platform_get_drvdata(pdev); | ||
359 | struct gab_platform_data *pdata = adc_bat->pdata; | ||
360 | |||
361 | power_supply_unregister(&adc_bat->psy); | ||
362 | |||
363 | if (gpio_is_valid(pdata->gpio_charge_finished)) { | ||
364 | free_irq(gpio_to_irq(pdata->gpio_charge_finished), adc_bat); | ||
365 | gpio_free(pdata->gpio_charge_finished); | ||
366 | } | ||
367 | |||
368 | for (chan = 0; ARRAY_SIZE(gab_chan_name); chan++) | ||
369 | iio_channel_release(adc_bat->channel[chan]); | ||
370 | |||
371 | kfree(adc_bat->psy.properties); | ||
372 | cancel_delayed_work(&adc_bat->bat_work); | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | #ifdef CONFIG_PM | ||
377 | static int gab_suspend(struct device *dev) | ||
378 | { | ||
379 | struct gab *adc_bat = dev_get_drvdata(dev); | ||
380 | |||
381 | cancel_delayed_work_sync(&adc_bat->bat_work); | ||
382 | adc_bat->status = POWER_SUPPLY_STATUS_UNKNOWN; | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static int gab_resume(struct device *dev) | ||
387 | { | ||
388 | struct gab *adc_bat = dev_get_drvdata(dev); | ||
389 | struct gab_platform_data *pdata = adc_bat->pdata; | ||
390 | int delay; | ||
391 | |||
392 | delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT; | ||
393 | |||
394 | /* Schedule timer to check current status */ | ||
395 | schedule_delayed_work(&adc_bat->bat_work, | ||
396 | msecs_to_jiffies(delay)); | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static const struct dev_pm_ops gab_pm_ops = { | ||
401 | .suspend = gab_suspend, | ||
402 | .resume = gab_resume, | ||
403 | }; | ||
404 | |||
405 | #define GAB_PM_OPS (&gab_pm_ops) | ||
406 | #else | ||
407 | #define GAB_PM_OPS (NULL) | ||
408 | #endif | ||
409 | |||
410 | static struct platform_driver gab_driver = { | ||
411 | .driver = { | ||
412 | .name = "generic-adc-battery", | ||
413 | .owner = THIS_MODULE, | ||
414 | .pm = GAB_PM_OPS | ||
415 | }, | ||
416 | .probe = gab_probe, | ||
417 | .remove = gab_remove, | ||
418 | }; | ||
419 | module_platform_driver(gab_driver); | ||
420 | |||
421 | MODULE_AUTHOR("anish kumar <anish198519851985@gmail.com>"); | ||
422 | MODULE_DESCRIPTION("generic battery driver using IIO"); | ||
423 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index e3e40a9f3af..020b415ef59 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c | |||
@@ -68,7 +68,7 @@ static enum power_supply_property gpio_charger_properties[] = { | |||
68 | POWER_SUPPLY_PROP_ONLINE, | 68 | POWER_SUPPLY_PROP_ONLINE, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static int gpio_charger_probe(struct platform_device *pdev) | 71 | static int __devinit gpio_charger_probe(struct platform_device *pdev) |
72 | { | 72 | { |
73 | const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data; | 73 | const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data; |
74 | struct gpio_charger *gpio_charger; | 74 | struct gpio_charger *gpio_charger; |
@@ -144,7 +144,7 @@ err_free: | |||
144 | return ret; | 144 | return ret; |
145 | } | 145 | } |
146 | 146 | ||
147 | static int gpio_charger_remove(struct platform_device *pdev) | 147 | static int __devexit gpio_charger_remove(struct platform_device *pdev) |
148 | { | 148 | { |
149 | struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); | 149 | struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); |
150 | 150 | ||
@@ -177,7 +177,7 @@ static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume); | |||
177 | 177 | ||
178 | static struct platform_driver gpio_charger_driver = { | 178 | static struct platform_driver gpio_charger_driver = { |
179 | .probe = gpio_charger_probe, | 179 | .probe = gpio_charger_probe, |
180 | .remove = gpio_charger_remove, | 180 | .remove = __devexit_p(gpio_charger_remove), |
181 | .driver = { | 181 | .driver = { |
182 | .name = "gpio-charger", | 182 | .name = "gpio-charger", |
183 | .owner = THIS_MODULE, | 183 | .owner = THIS_MODULE, |
@@ -185,7 +185,17 @@ static struct platform_driver gpio_charger_driver = { | |||
185 | }, | 185 | }, |
186 | }; | 186 | }; |
187 | 187 | ||
188 | module_platform_driver(gpio_charger_driver); | 188 | static int __init gpio_charger_init(void) |
189 | { | ||
190 | return platform_driver_register(&gpio_charger_driver); | ||
191 | } | ||
192 | module_init(gpio_charger_init); | ||
193 | |||
194 | static void __exit gpio_charger_exit(void) | ||
195 | { | ||
196 | platform_driver_unregister(&gpio_charger_driver); | ||
197 | } | ||
198 | module_exit(gpio_charger_exit); | ||
189 | 199 | ||
190 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 200 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
191 | MODULE_DESCRIPTION("Driver for chargers which report their online status through a GPIO"); | 201 | MODULE_DESCRIPTION("Driver for chargers which report their online status through a GPIO"); |
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c index 18d136b443e..cffcb7c00b0 100644 --- a/drivers/power/intel_mid_battery.c +++ b/drivers/power/intel_mid_battery.c | |||
@@ -61,8 +61,7 @@ MODULE_PARM_DESC(debug, "Flag to enable PMIC Battery debug messages."); | |||
61 | #define PMIC_BATT_CHR_SBATDET_MASK (1 << 5) | 61 | #define PMIC_BATT_CHR_SBATDET_MASK (1 << 5) |
62 | #define PMIC_BATT_CHR_SDCLMT_MASK (1 << 6) | 62 | #define PMIC_BATT_CHR_SDCLMT_MASK (1 << 6) |
63 | #define PMIC_BATT_CHR_SUSBOVP_MASK (1 << 7) | 63 | #define PMIC_BATT_CHR_SUSBOVP_MASK (1 << 7) |
64 | #define PMIC_BATT_CHR_EXCPT_MASK 0x86 | 64 | #define PMIC_BATT_CHR_EXCPT_MASK 0xC6 |
65 | |||
66 | #define PMIC_BATT_ADC_ACCCHRG_MASK (1 << 31) | 65 | #define PMIC_BATT_ADC_ACCCHRG_MASK (1 << 31) |
67 | #define PMIC_BATT_ADC_ACCCHRGVAL_MASK 0x7FFFFFFF | 66 | #define PMIC_BATT_ADC_ACCCHRGVAL_MASK 0x7FFFFFFF |
68 | 67 | ||
@@ -305,6 +304,11 @@ static void pmic_battery_read_status(struct pmic_power_module_info *pbi) | |||
305 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | 304 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; |
306 | pmic_battery_log_event(BATT_EVENT_BATOVP_EXCPT); | 305 | pmic_battery_log_event(BATT_EVENT_BATOVP_EXCPT); |
307 | batt_exception = 1; | 306 | batt_exception = 1; |
307 | } else if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { | ||
308 | pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
309 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
310 | pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); | ||
311 | batt_exception = 1; | ||
308 | } else if (r8 & PMIC_BATT_CHR_STEMP_MASK) { | 312 | } else if (r8 & PMIC_BATT_CHR_STEMP_MASK) { |
309 | pbi->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT; | 313 | pbi->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT; |
310 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | 314 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; |
@@ -312,10 +316,6 @@ static void pmic_battery_read_status(struct pmic_power_module_info *pbi) | |||
312 | batt_exception = 1; | 316 | batt_exception = 1; |
313 | } else { | 317 | } else { |
314 | pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD; | 318 | pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD; |
315 | if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { | ||
316 | /* PMIC will change charging current automatically */ | ||
317 | pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); | ||
318 | } | ||
319 | } | 319 | } |
320 | } | 320 | } |
321 | 321 | ||
@@ -649,7 +649,7 @@ static void pmic_battery_handle_intrpt(struct work_struct *work) | |||
649 | * PMIC battery initializes its internal data structue and other | 649 | * PMIC battery initializes its internal data structue and other |
650 | * infrastructure components for it to work as expected. | 650 | * infrastructure components for it to work as expected. |
651 | */ | 651 | */ |
652 | static int probe(int irq, struct device *dev) | 652 | static __devinit int probe(int irq, struct device *dev) |
653 | { | 653 | { |
654 | int retval = 0; | 654 | int retval = 0; |
655 | struct pmic_power_module_info *pbi; | 655 | struct pmic_power_module_info *pbi; |
@@ -739,7 +739,7 @@ wqueue_failed: | |||
739 | return retval; | 739 | return retval; |
740 | } | 740 | } |
741 | 741 | ||
742 | static int platform_pmic_battery_probe(struct platform_device *pdev) | 742 | static int __devinit platform_pmic_battery_probe(struct platform_device *pdev) |
743 | { | 743 | { |
744 | return probe(pdev->id, &pdev->dev); | 744 | return probe(pdev->id, &pdev->dev); |
745 | } | 745 | } |
@@ -754,7 +754,7 @@ static int platform_pmic_battery_probe(struct platform_device *pdev) | |||
754 | * pmic_battery_probe. | 754 | * pmic_battery_probe. |
755 | */ | 755 | */ |
756 | 756 | ||
757 | static int platform_pmic_battery_remove(struct platform_device *pdev) | 757 | static int __devexit platform_pmic_battery_remove(struct platform_device *pdev) |
758 | { | 758 | { |
759 | struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev); | 759 | struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev); |
760 | 760 | ||
@@ -776,10 +776,21 @@ static struct platform_driver platform_pmic_battery_driver = { | |||
776 | .owner = THIS_MODULE, | 776 | .owner = THIS_MODULE, |
777 | }, | 777 | }, |
778 | .probe = platform_pmic_battery_probe, | 778 | .probe = platform_pmic_battery_probe, |
779 | .remove = platform_pmic_battery_remove, | 779 | .remove = __devexit_p(platform_pmic_battery_remove), |
780 | }; | 780 | }; |
781 | 781 | ||
782 | module_platform_driver(platform_pmic_battery_driver); | 782 | static int __init platform_pmic_battery_module_init(void) |
783 | { | ||
784 | return platform_driver_register(&platform_pmic_battery_driver); | ||
785 | } | ||
786 | |||
787 | static void __exit platform_pmic_battery_module_exit(void) | ||
788 | { | ||
789 | platform_driver_unregister(&platform_pmic_battery_driver); | ||
790 | } | ||
791 | |||
792 | module_init(platform_pmic_battery_module_init); | ||
793 | module_exit(platform_pmic_battery_module_exit); | ||
783 | 794 | ||
784 | MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>"); | 795 | MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>"); |
785 | MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver"); | 796 | MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver"); |
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index 176ad59d99f..f6d72b402a8 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c | |||
@@ -56,7 +56,7 @@ static u16 isp170x_id[] = { | |||
56 | struct isp1704_charger { | 56 | struct isp1704_charger { |
57 | struct device *dev; | 57 | struct device *dev; |
58 | struct power_supply psy; | 58 | struct power_supply psy; |
59 | struct usb_phy *phy; | 59 | struct otg_transceiver *otg; |
60 | struct notifier_block nb; | 60 | struct notifier_block nb; |
61 | struct work_struct work; | 61 | struct work_struct work; |
62 | 62 | ||
@@ -71,16 +71,6 @@ struct isp1704_charger { | |||
71 | unsigned max_power; | 71 | unsigned max_power; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static inline int isp1704_read(struct isp1704_charger *isp, u32 reg) | ||
75 | { | ||
76 | return usb_phy_io_read(isp->phy, reg); | ||
77 | } | ||
78 | |||
79 | static inline int isp1704_write(struct isp1704_charger *isp, u32 val, u32 reg) | ||
80 | { | ||
81 | return usb_phy_io_write(isp->phy, val, reg); | ||
82 | } | ||
83 | |||
84 | /* | 74 | /* |
85 | * Disable/enable the power from the isp1704 if a function for it | 75 | * Disable/enable the power from the isp1704 if a function for it |
86 | * has been provided with platform data. | 76 | * has been provided with platform data. |
@@ -89,7 +79,7 @@ static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on) | |||
89 | { | 79 | { |
90 | struct isp1704_charger_data *board = isp->dev->platform_data; | 80 | struct isp1704_charger_data *board = isp->dev->platform_data; |
91 | 81 | ||
92 | if (board && board->set_power) | 82 | if (board->set_power) |
93 | board->set_power(on); | 83 | board->set_power(on); |
94 | } | 84 | } |
95 | 85 | ||
@@ -107,31 +97,31 @@ static inline int isp1704_charger_type(struct isp1704_charger *isp) | |||
107 | u8 otg_ctrl; | 97 | u8 otg_ctrl; |
108 | int type = POWER_SUPPLY_TYPE_USB_DCP; | 98 | int type = POWER_SUPPLY_TYPE_USB_DCP; |
109 | 99 | ||
110 | func_ctrl = isp1704_read(isp, ULPI_FUNC_CTRL); | 100 | func_ctrl = otg_io_read(isp->otg, ULPI_FUNC_CTRL); |
111 | otg_ctrl = isp1704_read(isp, ULPI_OTG_CTRL); | 101 | otg_ctrl = otg_io_read(isp->otg, ULPI_OTG_CTRL); |
112 | 102 | ||
113 | /* disable pulldowns */ | 103 | /* disable pulldowns */ |
114 | reg = ULPI_OTG_CTRL_DM_PULLDOWN | ULPI_OTG_CTRL_DP_PULLDOWN; | 104 | reg = ULPI_OTG_CTRL_DM_PULLDOWN | ULPI_OTG_CTRL_DP_PULLDOWN; |
115 | isp1704_write(isp, ULPI_CLR(ULPI_OTG_CTRL), reg); | 105 | otg_io_write(isp->otg, ULPI_CLR(ULPI_OTG_CTRL), reg); |
116 | 106 | ||
117 | /* full speed */ | 107 | /* full speed */ |
118 | isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL), | 108 | otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL), |
119 | ULPI_FUNC_CTRL_XCVRSEL_MASK); | 109 | ULPI_FUNC_CTRL_XCVRSEL_MASK); |
120 | isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), | 110 | otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), |
121 | ULPI_FUNC_CTRL_FULL_SPEED); | 111 | ULPI_FUNC_CTRL_FULL_SPEED); |
122 | 112 | ||
123 | /* Enable strong pull-up on DP (1.5K) and reset */ | 113 | /* Enable strong pull-up on DP (1.5K) and reset */ |
124 | reg = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET; | 114 | reg = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET; |
125 | isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), reg); | 115 | otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), reg); |
126 | usleep_range(1000, 2000); | 116 | usleep_range(1000, 2000); |
127 | 117 | ||
128 | reg = isp1704_read(isp, ULPI_DEBUG); | 118 | reg = otg_io_read(isp->otg, ULPI_DEBUG); |
129 | if ((reg & 3) != 3) | 119 | if ((reg & 3) != 3) |
130 | type = POWER_SUPPLY_TYPE_USB_CDP; | 120 | type = POWER_SUPPLY_TYPE_USB_CDP; |
131 | 121 | ||
132 | /* recover original state */ | 122 | /* recover original state */ |
133 | isp1704_write(isp, ULPI_FUNC_CTRL, func_ctrl); | 123 | otg_io_write(isp->otg, ULPI_FUNC_CTRL, func_ctrl); |
134 | isp1704_write(isp, ULPI_OTG_CTRL, otg_ctrl); | 124 | otg_io_write(isp->otg, ULPI_OTG_CTRL, otg_ctrl); |
135 | 125 | ||
136 | return type; | 126 | return type; |
137 | } | 127 | } |
@@ -146,28 +136,28 @@ static inline int isp1704_charger_verify(struct isp1704_charger *isp) | |||
146 | u8 r; | 136 | u8 r; |
147 | 137 | ||
148 | /* Reset the transceiver */ | 138 | /* Reset the transceiver */ |
149 | r = isp1704_read(isp, ULPI_FUNC_CTRL); | 139 | r = otg_io_read(isp->otg, ULPI_FUNC_CTRL); |
150 | r |= ULPI_FUNC_CTRL_RESET; | 140 | r |= ULPI_FUNC_CTRL_RESET; |
151 | isp1704_write(isp, ULPI_FUNC_CTRL, r); | 141 | otg_io_write(isp->otg, ULPI_FUNC_CTRL, r); |
152 | usleep_range(1000, 2000); | 142 | usleep_range(1000, 2000); |
153 | 143 | ||
154 | /* Set normal mode */ | 144 | /* Set normal mode */ |
155 | r &= ~(ULPI_FUNC_CTRL_RESET | ULPI_FUNC_CTRL_OPMODE_MASK); | 145 | r &= ~(ULPI_FUNC_CTRL_RESET | ULPI_FUNC_CTRL_OPMODE_MASK); |
156 | isp1704_write(isp, ULPI_FUNC_CTRL, r); | 146 | otg_io_write(isp->otg, ULPI_FUNC_CTRL, r); |
157 | 147 | ||
158 | /* Clear the DP and DM pull-down bits */ | 148 | /* Clear the DP and DM pull-down bits */ |
159 | r = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN; | 149 | r = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN; |
160 | isp1704_write(isp, ULPI_CLR(ULPI_OTG_CTRL), r); | 150 | otg_io_write(isp->otg, ULPI_CLR(ULPI_OTG_CTRL), r); |
161 | 151 | ||
162 | /* Enable strong pull-up on DP (1.5K) and reset */ | 152 | /* Enable strong pull-up on DP (1.5K) and reset */ |
163 | r = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET; | 153 | r = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET; |
164 | isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), r); | 154 | otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), r); |
165 | usleep_range(1000, 2000); | 155 | usleep_range(1000, 2000); |
166 | 156 | ||
167 | /* Read the line state */ | 157 | /* Read the line state */ |
168 | if (!isp1704_read(isp, ULPI_DEBUG)) { | 158 | if (!otg_io_read(isp->otg, ULPI_DEBUG)) { |
169 | /* Disable strong pull-up on DP (1.5K) */ | 159 | /* Disable strong pull-up on DP (1.5K) */ |
170 | isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL), | 160 | otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL), |
171 | ULPI_FUNC_CTRL_TERMSELECT); | 161 | ULPI_FUNC_CTRL_TERMSELECT); |
172 | return 1; | 162 | return 1; |
173 | } | 163 | } |
@@ -175,23 +165,23 @@ static inline int isp1704_charger_verify(struct isp1704_charger *isp) | |||
175 | /* Is it a charger or PS/2 connection */ | 165 | /* Is it a charger or PS/2 connection */ |
176 | 166 | ||
177 | /* Enable weak pull-up resistor on DP */ | 167 | /* Enable weak pull-up resistor on DP */ |
178 | isp1704_write(isp, ULPI_SET(ISP1704_PWR_CTRL), | 168 | otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL), |
179 | ISP1704_PWR_CTRL_DP_WKPU_EN); | 169 | ISP1704_PWR_CTRL_DP_WKPU_EN); |
180 | 170 | ||
181 | /* Disable strong pull-up on DP (1.5K) */ | 171 | /* Disable strong pull-up on DP (1.5K) */ |
182 | isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL), | 172 | otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL), |
183 | ULPI_FUNC_CTRL_TERMSELECT); | 173 | ULPI_FUNC_CTRL_TERMSELECT); |
184 | 174 | ||
185 | /* Enable weak pull-down resistor on DM */ | 175 | /* Enable weak pull-down resistor on DM */ |
186 | isp1704_write(isp, ULPI_SET(ULPI_OTG_CTRL), | 176 | otg_io_write(isp->otg, ULPI_SET(ULPI_OTG_CTRL), |
187 | ULPI_OTG_CTRL_DM_PULLDOWN); | 177 | ULPI_OTG_CTRL_DM_PULLDOWN); |
188 | 178 | ||
189 | /* It's a charger if the line states are clear */ | 179 | /* It's a charger if the line states are clear */ |
190 | if (!(isp1704_read(isp, ULPI_DEBUG))) | 180 | if (!(otg_io_read(isp->otg, ULPI_DEBUG))) |
191 | ret = 1; | 181 | ret = 1; |
192 | 182 | ||
193 | /* Disable weak pull-up resistor on DP */ | 183 | /* Disable weak pull-up resistor on DP */ |
194 | isp1704_write(isp, ULPI_CLR(ISP1704_PWR_CTRL), | 184 | otg_io_write(isp->otg, ULPI_CLR(ISP1704_PWR_CTRL), |
195 | ISP1704_PWR_CTRL_DP_WKPU_EN); | 185 | ISP1704_PWR_CTRL_DP_WKPU_EN); |
196 | 186 | ||
197 | return ret; | 187 | return ret; |
@@ -203,14 +193,14 @@ static inline int isp1704_charger_detect(struct isp1704_charger *isp) | |||
203 | u8 pwr_ctrl; | 193 | u8 pwr_ctrl; |
204 | int ret = 0; | 194 | int ret = 0; |
205 | 195 | ||
206 | pwr_ctrl = isp1704_read(isp, ISP1704_PWR_CTRL); | 196 | pwr_ctrl = otg_io_read(isp->otg, ISP1704_PWR_CTRL); |
207 | 197 | ||
208 | /* set SW control bit in PWR_CTRL register */ | 198 | /* set SW control bit in PWR_CTRL register */ |
209 | isp1704_write(isp, ISP1704_PWR_CTRL, | 199 | otg_io_write(isp->otg, ISP1704_PWR_CTRL, |
210 | ISP1704_PWR_CTRL_SWCTRL); | 200 | ISP1704_PWR_CTRL_SWCTRL); |
211 | 201 | ||
212 | /* enable manual charger detection */ | 202 | /* enable manual charger detection */ |
213 | isp1704_write(isp, ULPI_SET(ISP1704_PWR_CTRL), | 203 | otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL), |
214 | ISP1704_PWR_CTRL_SWCTRL | 204 | ISP1704_PWR_CTRL_SWCTRL |
215 | | ISP1704_PWR_CTRL_DPVSRC_EN); | 205 | | ISP1704_PWR_CTRL_DPVSRC_EN); |
216 | usleep_range(1000, 2000); | 206 | usleep_range(1000, 2000); |
@@ -218,7 +208,7 @@ static inline int isp1704_charger_detect(struct isp1704_charger *isp) | |||
218 | timeout = jiffies + msecs_to_jiffies(300); | 208 | timeout = jiffies + msecs_to_jiffies(300); |
219 | do { | 209 | do { |
220 | /* Check if there is a charger */ | 210 | /* Check if there is a charger */ |
221 | if (isp1704_read(isp, ISP1704_PWR_CTRL) | 211 | if (otg_io_read(isp->otg, ISP1704_PWR_CTRL) |
222 | & ISP1704_PWR_CTRL_VDAT_DET) { | 212 | & ISP1704_PWR_CTRL_VDAT_DET) { |
223 | ret = isp1704_charger_verify(isp); | 213 | ret = isp1704_charger_verify(isp); |
224 | break; | 214 | break; |
@@ -226,7 +216,7 @@ static inline int isp1704_charger_detect(struct isp1704_charger *isp) | |||
226 | } while (!time_after(jiffies, timeout) && isp->online); | 216 | } while (!time_after(jiffies, timeout) && isp->online); |
227 | 217 | ||
228 | /* recover original state */ | 218 | /* recover original state */ |
229 | isp1704_write(isp, ISP1704_PWR_CTRL, pwr_ctrl); | 219 | otg_io_write(isp->otg, ISP1704_PWR_CTRL, pwr_ctrl); |
230 | 220 | ||
231 | return ret; | 221 | return ret; |
232 | } | 222 | } |
@@ -274,8 +264,8 @@ static void isp1704_charger_work(struct work_struct *data) | |||
274 | case POWER_SUPPLY_TYPE_USB: | 264 | case POWER_SUPPLY_TYPE_USB: |
275 | default: | 265 | default: |
276 | /* enable data pullups */ | 266 | /* enable data pullups */ |
277 | if (isp->phy->otg->gadget) | 267 | if (isp->otg->gadget) |
278 | usb_gadget_connect(isp->phy->otg->gadget); | 268 | usb_gadget_connect(isp->otg->gadget); |
279 | } | 269 | } |
280 | break; | 270 | break; |
281 | case USB_EVENT_NONE: | 271 | case USB_EVENT_NONE: |
@@ -293,8 +283,8 @@ static void isp1704_charger_work(struct work_struct *data) | |||
293 | * chargers. The pullups may be enabled elsewhere, so this can | 283 | * chargers. The pullups may be enabled elsewhere, so this can |
294 | * not be the final solution. | 284 | * not be the final solution. |
295 | */ | 285 | */ |
296 | if (isp->phy->otg->gadget) | 286 | if (isp->otg->gadget) |
297 | usb_gadget_disconnect(isp->phy->otg->gadget); | 287 | usb_gadget_disconnect(isp->otg->gadget); |
298 | 288 | ||
299 | isp1704_charger_set_power(isp, 0); | 289 | isp1704_charger_set_power(isp, 0); |
300 | break; | 290 | break; |
@@ -374,11 +364,11 @@ static inline int isp1704_test_ulpi(struct isp1704_charger *isp) | |||
374 | int ret = -ENODEV; | 364 | int ret = -ENODEV; |
375 | 365 | ||
376 | /* Test ULPI interface */ | 366 | /* Test ULPI interface */ |
377 | ret = isp1704_write(isp, ULPI_SCRATCH, 0xaa); | 367 | ret = otg_io_write(isp->otg, ULPI_SCRATCH, 0xaa); |
378 | if (ret < 0) | 368 | if (ret < 0) |
379 | return ret; | 369 | return ret; |
380 | 370 | ||
381 | ret = isp1704_read(isp, ULPI_SCRATCH); | 371 | ret = otg_io_read(isp->otg, ULPI_SCRATCH); |
382 | if (ret < 0) | 372 | if (ret < 0) |
383 | return ret; | 373 | return ret; |
384 | 374 | ||
@@ -386,13 +376,13 @@ static inline int isp1704_test_ulpi(struct isp1704_charger *isp) | |||
386 | return -ENODEV; | 376 | return -ENODEV; |
387 | 377 | ||
388 | /* Verify the product and vendor id matches */ | 378 | /* Verify the product and vendor id matches */ |
389 | vendor = isp1704_read(isp, ULPI_VENDOR_ID_LOW); | 379 | vendor = otg_io_read(isp->otg, ULPI_VENDOR_ID_LOW); |
390 | vendor |= isp1704_read(isp, ULPI_VENDOR_ID_HIGH) << 8; | 380 | vendor |= otg_io_read(isp->otg, ULPI_VENDOR_ID_HIGH) << 8; |
391 | if (vendor != NXP_VENDOR_ID) | 381 | if (vendor != NXP_VENDOR_ID) |
392 | return -ENODEV; | 382 | return -ENODEV; |
393 | 383 | ||
394 | product = isp1704_read(isp, ULPI_PRODUCT_ID_LOW); | 384 | product = otg_io_read(isp->otg, ULPI_PRODUCT_ID_LOW); |
395 | product |= isp1704_read(isp, ULPI_PRODUCT_ID_HIGH) << 8; | 385 | product |= otg_io_read(isp->otg, ULPI_PRODUCT_ID_HIGH) << 8; |
396 | 386 | ||
397 | for (i = 0; i < ARRAY_SIZE(isp170x_id); i++) { | 387 | for (i = 0; i < ARRAY_SIZE(isp170x_id); i++) { |
398 | if (product == isp170x_id[i]) { | 388 | if (product == isp170x_id[i]) { |
@@ -406,7 +396,7 @@ static inline int isp1704_test_ulpi(struct isp1704_charger *isp) | |||
406 | return -ENODEV; | 396 | return -ENODEV; |
407 | } | 397 | } |
408 | 398 | ||
409 | static int isp1704_charger_probe(struct platform_device *pdev) | 399 | static int __devinit isp1704_charger_probe(struct platform_device *pdev) |
410 | { | 400 | { |
411 | struct isp1704_charger *isp; | 401 | struct isp1704_charger *isp; |
412 | int ret = -ENODEV; | 402 | int ret = -ENODEV; |
@@ -415,8 +405,8 @@ static int isp1704_charger_probe(struct platform_device *pdev) | |||
415 | if (!isp) | 405 | if (!isp) |
416 | return -ENOMEM; | 406 | return -ENOMEM; |
417 | 407 | ||
418 | isp->phy = usb_get_phy(USB_PHY_TYPE_USB2); | 408 | isp->otg = otg_get_transceiver(); |
419 | if (IS_ERR_OR_NULL(isp->phy)) | 409 | if (!isp->otg) |
420 | goto fail0; | 410 | goto fail0; |
421 | 411 | ||
422 | isp->dev = &pdev->dev; | 412 | isp->dev = &pdev->dev; |
@@ -439,14 +429,14 @@ static int isp1704_charger_probe(struct platform_device *pdev) | |||
439 | goto fail1; | 429 | goto fail1; |
440 | 430 | ||
441 | /* | 431 | /* |
442 | * REVISIT: using work in order to allow the usb notifications to be | 432 | * REVISIT: using work in order to allow the otg notifications to be |
443 | * made atomically in the future. | 433 | * made atomically in the future. |
444 | */ | 434 | */ |
445 | INIT_WORK(&isp->work, isp1704_charger_work); | 435 | INIT_WORK(&isp->work, isp1704_charger_work); |
446 | 436 | ||
447 | isp->nb.notifier_call = isp1704_notifier_call; | 437 | isp->nb.notifier_call = isp1704_notifier_call; |
448 | 438 | ||
449 | ret = usb_register_notifier(isp->phy, &isp->nb); | 439 | ret = otg_register_notifier(isp->otg, &isp->nb); |
450 | if (ret) | 440 | if (ret) |
451 | goto fail2; | 441 | goto fail2; |
452 | 442 | ||
@@ -459,13 +449,13 @@ static int isp1704_charger_probe(struct platform_device *pdev) | |||
459 | * enumerated. The charger driver should be always loaded before any | 449 | * enumerated. The charger driver should be always loaded before any |
460 | * gadget is loaded. | 450 | * gadget is loaded. |
461 | */ | 451 | */ |
462 | if (isp->phy->otg->gadget) | 452 | if (isp->otg->gadget) |
463 | usb_gadget_disconnect(isp->phy->otg->gadget); | 453 | usb_gadget_disconnect(isp->otg->gadget); |
464 | 454 | ||
465 | /* Detect charger if VBUS is valid (the cable was already plugged). */ | 455 | /* Detect charger if VBUS is valid (the cable was already plugged). */ |
466 | ret = isp1704_read(isp, ULPI_USB_INT_STS); | 456 | ret = otg_io_read(isp->otg, ULPI_USB_INT_STS); |
467 | isp1704_charger_set_power(isp, 0); | 457 | isp1704_charger_set_power(isp, 0); |
468 | if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) { | 458 | if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) { |
469 | isp->event = USB_EVENT_VBUS; | 459 | isp->event = USB_EVENT_VBUS; |
470 | schedule_work(&isp->work); | 460 | schedule_work(&isp->work); |
471 | } | 461 | } |
@@ -474,8 +464,7 @@ static int isp1704_charger_probe(struct platform_device *pdev) | |||
474 | fail2: | 464 | fail2: |
475 | power_supply_unregister(&isp->psy); | 465 | power_supply_unregister(&isp->psy); |
476 | fail1: | 466 | fail1: |
477 | isp1704_charger_set_power(isp, 0); | 467 | otg_put_transceiver(isp->otg); |
478 | usb_put_phy(isp->phy); | ||
479 | fail0: | 468 | fail0: |
480 | kfree(isp); | 469 | kfree(isp); |
481 | 470 | ||
@@ -484,13 +473,13 @@ fail0: | |||
484 | return ret; | 473 | return ret; |
485 | } | 474 | } |
486 | 475 | ||
487 | static int isp1704_charger_remove(struct platform_device *pdev) | 476 | static int __devexit isp1704_charger_remove(struct platform_device *pdev) |
488 | { | 477 | { |
489 | struct isp1704_charger *isp = platform_get_drvdata(pdev); | 478 | struct isp1704_charger *isp = platform_get_drvdata(pdev); |
490 | 479 | ||
491 | usb_unregister_notifier(isp->phy, &isp->nb); | 480 | otg_unregister_notifier(isp->otg, &isp->nb); |
492 | power_supply_unregister(&isp->psy); | 481 | power_supply_unregister(&isp->psy); |
493 | usb_put_phy(isp->phy); | 482 | otg_put_transceiver(isp->otg); |
494 | isp1704_charger_set_power(isp, 0); | 483 | isp1704_charger_set_power(isp, 0); |
495 | kfree(isp); | 484 | kfree(isp); |
496 | 485 | ||
@@ -502,10 +491,20 @@ static struct platform_driver isp1704_charger_driver = { | |||
502 | .name = "isp1704_charger", | 491 | .name = "isp1704_charger", |
503 | }, | 492 | }, |
504 | .probe = isp1704_charger_probe, | 493 | .probe = isp1704_charger_probe, |
505 | .remove = isp1704_charger_remove, | 494 | .remove = __devexit_p(isp1704_charger_remove), |
506 | }; | 495 | }; |
507 | 496 | ||
508 | module_platform_driver(isp1704_charger_driver); | 497 | static int __init isp1704_charger_init(void) |
498 | { | ||
499 | return platform_driver_register(&isp1704_charger_driver); | ||
500 | } | ||
501 | module_init(isp1704_charger_init); | ||
502 | |||
503 | static void __exit isp1704_charger_exit(void) | ||
504 | { | ||
505 | platform_driver_unregister(&isp1704_charger_driver); | ||
506 | } | ||
507 | module_exit(isp1704_charger_exit); | ||
509 | 508 | ||
510 | MODULE_ALIAS("platform:isp1704_charger"); | 509 | MODULE_ALIAS("platform:isp1704_charger"); |
511 | MODULE_AUTHOR("Nokia Corporation"); | 510 | MODULE_AUTHOR("Nokia Corporation"); |
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c index bf914893c6f..763f894ed18 100644 --- a/drivers/power/jz4740-battery.c +++ b/drivers/power/jz4740-battery.c | |||
@@ -33,6 +33,7 @@ struct jz_battery { | |||
33 | struct jz_battery_platform_data *pdata; | 33 | struct jz_battery_platform_data *pdata; |
34 | struct platform_device *pdev; | 34 | struct platform_device *pdev; |
35 | 35 | ||
36 | struct resource *mem; | ||
36 | void __iomem *base; | 37 | void __iomem *base; |
37 | 38 | ||
38 | int irq; | 39 | int irq; |
@@ -66,7 +67,7 @@ static irqreturn_t jz_battery_irq_handler(int irq, void *devid) | |||
66 | 67 | ||
67 | static long jz_battery_read_voltage(struct jz_battery *battery) | 68 | static long jz_battery_read_voltage(struct jz_battery *battery) |
68 | { | 69 | { |
69 | long t; | 70 | unsigned long t; |
70 | unsigned long val; | 71 | unsigned long val; |
71 | long voltage; | 72 | long voltage; |
72 | 73 | ||
@@ -172,14 +173,16 @@ static void jz_battery_external_power_changed(struct power_supply *psy) | |||
172 | { | 173 | { |
173 | struct jz_battery *jz_battery = psy_to_jz_battery(psy); | 174 | struct jz_battery *jz_battery = psy_to_jz_battery(psy); |
174 | 175 | ||
175 | mod_delayed_work(system_wq, &jz_battery->work, 0); | 176 | cancel_delayed_work(&jz_battery->work); |
177 | schedule_delayed_work(&jz_battery->work, 0); | ||
176 | } | 178 | } |
177 | 179 | ||
178 | static irqreturn_t jz_battery_charge_irq(int irq, void *data) | 180 | static irqreturn_t jz_battery_charge_irq(int irq, void *data) |
179 | { | 181 | { |
180 | struct jz_battery *jz_battery = data; | 182 | struct jz_battery *jz_battery = data; |
181 | 183 | ||
182 | mod_delayed_work(system_wq, &jz_battery->work, 0); | 184 | cancel_delayed_work(&jz_battery->work); |
185 | schedule_delayed_work(&jz_battery->work, 0); | ||
183 | 186 | ||
184 | return IRQ_HANDLED; | 187 | return IRQ_HANDLED; |
185 | } | 188 | } |
@@ -237,20 +240,19 @@ static void jz_battery_work(struct work_struct *work) | |||
237 | schedule_delayed_work(&jz_battery->work, interval); | 240 | schedule_delayed_work(&jz_battery->work, interval); |
238 | } | 241 | } |
239 | 242 | ||
240 | static int jz_battery_probe(struct platform_device *pdev) | 243 | static int __devinit jz_battery_probe(struct platform_device *pdev) |
241 | { | 244 | { |
242 | int ret = 0; | 245 | int ret = 0; |
243 | struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data; | 246 | struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data; |
244 | struct jz_battery *jz_battery; | 247 | struct jz_battery *jz_battery; |
245 | struct power_supply *battery; | 248 | struct power_supply *battery; |
246 | struct resource *mem; | ||
247 | 249 | ||
248 | if (!pdata) { | 250 | if (!pdata) { |
249 | dev_err(&pdev->dev, "No platform_data supplied\n"); | 251 | dev_err(&pdev->dev, "No platform_data supplied\n"); |
250 | return -ENXIO; | 252 | return -ENXIO; |
251 | } | 253 | } |
252 | 254 | ||
253 | jz_battery = devm_kzalloc(&pdev->dev, sizeof(*jz_battery), GFP_KERNEL); | 255 | jz_battery = kzalloc(sizeof(*jz_battery), GFP_KERNEL); |
254 | if (!jz_battery) { | 256 | if (!jz_battery) { |
255 | dev_err(&pdev->dev, "Failed to allocate driver structure\n"); | 257 | dev_err(&pdev->dev, "Failed to allocate driver structure\n"); |
256 | return -ENOMEM; | 258 | return -ENOMEM; |
@@ -260,15 +262,33 @@ static int jz_battery_probe(struct platform_device *pdev) | |||
260 | 262 | ||
261 | jz_battery->irq = platform_get_irq(pdev, 0); | 263 | jz_battery->irq = platform_get_irq(pdev, 0); |
262 | if (jz_battery->irq < 0) { | 264 | if (jz_battery->irq < 0) { |
265 | ret = jz_battery->irq; | ||
263 | dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); | 266 | dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); |
264 | return jz_battery->irq; | 267 | goto err_free; |
265 | } | 268 | } |
266 | 269 | ||
267 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 270 | jz_battery->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
271 | if (!jz_battery->mem) { | ||
272 | ret = -ENOENT; | ||
273 | dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); | ||
274 | goto err_free; | ||
275 | } | ||
276 | |||
277 | jz_battery->mem = request_mem_region(jz_battery->mem->start, | ||
278 | resource_size(jz_battery->mem), pdev->name); | ||
279 | if (!jz_battery->mem) { | ||
280 | ret = -EBUSY; | ||
281 | dev_err(&pdev->dev, "Failed to request mmio memory region\n"); | ||
282 | goto err_free; | ||
283 | } | ||
268 | 284 | ||
269 | jz_battery->base = devm_request_and_ioremap(&pdev->dev, mem); | 285 | jz_battery->base = ioremap_nocache(jz_battery->mem->start, |
270 | if (!jz_battery->base) | 286 | resource_size(jz_battery->mem)); |
271 | return -EBUSY; | 287 | if (!jz_battery->base) { |
288 | ret = -EBUSY; | ||
289 | dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); | ||
290 | goto err_release_mem_region; | ||
291 | } | ||
272 | 292 | ||
273 | battery = &jz_battery->battery; | 293 | battery = &jz_battery->battery; |
274 | battery->name = pdata->info.name; | 294 | battery->name = pdata->info.name; |
@@ -291,7 +311,7 @@ static int jz_battery_probe(struct platform_device *pdev) | |||
291 | jz_battery); | 311 | jz_battery); |
292 | if (ret) { | 312 | if (ret) { |
293 | dev_err(&pdev->dev, "Failed to request irq %d\n", ret); | 313 | dev_err(&pdev->dev, "Failed to request irq %d\n", ret); |
294 | goto err; | 314 | goto err_iounmap; |
295 | } | 315 | } |
296 | disable_irq(jz_battery->irq); | 316 | disable_irq(jz_battery->irq); |
297 | 317 | ||
@@ -348,12 +368,17 @@ err_free_gpio: | |||
348 | gpio_free(jz_battery->pdata->gpio_charge); | 368 | gpio_free(jz_battery->pdata->gpio_charge); |
349 | err_free_irq: | 369 | err_free_irq: |
350 | free_irq(jz_battery->irq, jz_battery); | 370 | free_irq(jz_battery->irq, jz_battery); |
351 | err: | 371 | err_iounmap: |
352 | platform_set_drvdata(pdev, NULL); | 372 | platform_set_drvdata(pdev, NULL); |
373 | iounmap(jz_battery->base); | ||
374 | err_release_mem_region: | ||
375 | release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem)); | ||
376 | err_free: | ||
377 | kfree(jz_battery); | ||
353 | return ret; | 378 | return ret; |
354 | } | 379 | } |
355 | 380 | ||
356 | static int jz_battery_remove(struct platform_device *pdev) | 381 | static int __devexit jz_battery_remove(struct platform_device *pdev) |
357 | { | 382 | { |
358 | struct jz_battery *jz_battery = platform_get_drvdata(pdev); | 383 | struct jz_battery *jz_battery = platform_get_drvdata(pdev); |
359 | 384 | ||
@@ -369,6 +394,10 @@ static int jz_battery_remove(struct platform_device *pdev) | |||
369 | 394 | ||
370 | free_irq(jz_battery->irq, jz_battery); | 395 | free_irq(jz_battery->irq, jz_battery); |
371 | 396 | ||
397 | iounmap(jz_battery->base); | ||
398 | release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem)); | ||
399 | kfree(jz_battery); | ||
400 | |||
372 | return 0; | 401 | return 0; |
373 | } | 402 | } |
374 | 403 | ||
@@ -404,7 +433,7 @@ static const struct dev_pm_ops jz_battery_pm_ops = { | |||
404 | 433 | ||
405 | static struct platform_driver jz_battery_driver = { | 434 | static struct platform_driver jz_battery_driver = { |
406 | .probe = jz_battery_probe, | 435 | .probe = jz_battery_probe, |
407 | .remove = jz_battery_remove, | 436 | .remove = __devexit_p(jz_battery_remove), |
408 | .driver = { | 437 | .driver = { |
409 | .name = "jz4740-battery", | 438 | .name = "jz4740-battery", |
410 | .owner = THIS_MODULE, | 439 | .owner = THIS_MODULE, |
@@ -412,7 +441,17 @@ static struct platform_driver jz_battery_driver = { | |||
412 | }, | 441 | }, |
413 | }; | 442 | }; |
414 | 443 | ||
415 | module_platform_driver(jz_battery_driver); | 444 | static int __init jz_battery_init(void) |
445 | { | ||
446 | return platform_driver_register(&jz_battery_driver); | ||
447 | } | ||
448 | module_init(jz_battery_init); | ||
449 | |||
450 | static void __exit jz_battery_exit(void) | ||
451 | { | ||
452 | platform_driver_unregister(&jz_battery_driver); | ||
453 | } | ||
454 | module_exit(jz_battery_exit); | ||
416 | 455 | ||
417 | MODULE_ALIAS("platform:jz4740-battery"); | 456 | MODULE_ALIAS("platform:jz4740-battery"); |
418 | MODULE_LICENSE("GPL"); | 457 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c deleted file mode 100644 index 4ee71a90e24..00000000000 --- a/drivers/power/lp8727_charger.c +++ /dev/null | |||
@@ -1,552 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for LP8727 Micro/Mini USB IC with integrated charger | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments | ||
5 | * Copyright (C) 2011 National Semiconductor | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/power_supply.h> | ||
18 | #include <linux/platform_data/lp8727.h> | ||
19 | |||
20 | #define LP8788_NUM_INTREGS 2 | ||
21 | #define DEFAULT_DEBOUNCE_MSEC 270 | ||
22 | |||
23 | /* Registers */ | ||
24 | #define LP8727_CTRL1 0x1 | ||
25 | #define LP8727_CTRL2 0x2 | ||
26 | #define LP8727_SWCTRL 0x3 | ||
27 | #define LP8727_INT1 0x4 | ||
28 | #define LP8727_INT2 0x5 | ||
29 | #define LP8727_STATUS1 0x6 | ||
30 | #define LP8727_STATUS2 0x7 | ||
31 | #define LP8727_CHGCTRL2 0x9 | ||
32 | |||
33 | /* CTRL1 register */ | ||
34 | #define LP8727_CP_EN BIT(0) | ||
35 | #define LP8727_ADC_EN BIT(1) | ||
36 | #define LP8727_ID200_EN BIT(4) | ||
37 | |||
38 | /* CTRL2 register */ | ||
39 | #define LP8727_CHGDET_EN BIT(1) | ||
40 | #define LP8727_INT_EN BIT(6) | ||
41 | |||
42 | /* SWCTRL register */ | ||
43 | #define LP8727_SW_DM1_DM (0x0 << 0) | ||
44 | #define LP8727_SW_DM1_HiZ (0x7 << 0) | ||
45 | #define LP8727_SW_DP2_DP (0x0 << 3) | ||
46 | #define LP8727_SW_DP2_HiZ (0x7 << 3) | ||
47 | |||
48 | /* INT1 register */ | ||
49 | #define LP8727_IDNO (0xF << 0) | ||
50 | #define LP8727_VBUS BIT(4) | ||
51 | |||
52 | /* STATUS1 register */ | ||
53 | #define LP8727_CHGSTAT (3 << 4) | ||
54 | #define LP8727_CHPORT BIT(6) | ||
55 | #define LP8727_DCPORT BIT(7) | ||
56 | #define LP8727_STAT_EOC 0x30 | ||
57 | |||
58 | /* STATUS2 register */ | ||
59 | #define LP8727_TEMP_STAT (3 << 5) | ||
60 | #define LP8727_TEMP_SHIFT 5 | ||
61 | |||
62 | /* CHGCTRL2 register */ | ||
63 | #define LP8727_ICHG_SHIFT 4 | ||
64 | |||
65 | enum lp8727_dev_id { | ||
66 | LP8727_ID_NONE, | ||
67 | LP8727_ID_TA, | ||
68 | LP8727_ID_DEDICATED_CHG, | ||
69 | LP8727_ID_USB_CHG, | ||
70 | LP8727_ID_USB_DS, | ||
71 | LP8727_ID_MAX, | ||
72 | }; | ||
73 | |||
74 | enum lp8727_die_temp { | ||
75 | LP8788_TEMP_75C, | ||
76 | LP8788_TEMP_95C, | ||
77 | LP8788_TEMP_115C, | ||
78 | LP8788_TEMP_135C, | ||
79 | }; | ||
80 | |||
81 | struct lp8727_psy { | ||
82 | struct power_supply ac; | ||
83 | struct power_supply usb; | ||
84 | struct power_supply batt; | ||
85 | }; | ||
86 | |||
87 | struct lp8727_chg { | ||
88 | struct device *dev; | ||
89 | struct i2c_client *client; | ||
90 | struct mutex xfer_lock; | ||
91 | struct lp8727_psy *psy; | ||
92 | struct lp8727_platform_data *pdata; | ||
93 | |||
94 | /* Charger Data */ | ||
95 | enum lp8727_dev_id devid; | ||
96 | struct lp8727_chg_param *chg_param; | ||
97 | |||
98 | /* Interrupt Handling */ | ||
99 | int irq; | ||
100 | struct delayed_work work; | ||
101 | unsigned long debounce_jiffies; | ||
102 | }; | ||
103 | |||
104 | static int lp8727_read_bytes(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len) | ||
105 | { | ||
106 | s32 ret; | ||
107 | |||
108 | mutex_lock(&pchg->xfer_lock); | ||
109 | ret = i2c_smbus_read_i2c_block_data(pchg->client, reg, len, data); | ||
110 | mutex_unlock(&pchg->xfer_lock); | ||
111 | |||
112 | return (ret != len) ? -EIO : 0; | ||
113 | } | ||
114 | |||
115 | static inline int lp8727_read_byte(struct lp8727_chg *pchg, u8 reg, u8 *data) | ||
116 | { | ||
117 | return lp8727_read_bytes(pchg, reg, data, 1); | ||
118 | } | ||
119 | |||
120 | static int lp8727_write_byte(struct lp8727_chg *pchg, u8 reg, u8 data) | ||
121 | { | ||
122 | int ret; | ||
123 | |||
124 | mutex_lock(&pchg->xfer_lock); | ||
125 | ret = i2c_smbus_write_byte_data(pchg->client, reg, data); | ||
126 | mutex_unlock(&pchg->xfer_lock); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | static bool lp8727_is_charger_attached(const char *name, int id) | ||
132 | { | ||
133 | if (!strcmp(name, "ac")) | ||
134 | return id == LP8727_ID_TA || id == LP8727_ID_DEDICATED_CHG; | ||
135 | else if (!strcmp(name, "usb")) | ||
136 | return id == LP8727_ID_USB_CHG; | ||
137 | |||
138 | return id >= LP8727_ID_TA && id <= LP8727_ID_USB_CHG; | ||
139 | } | ||
140 | |||
141 | static int lp8727_init_device(struct lp8727_chg *pchg) | ||
142 | { | ||
143 | u8 val; | ||
144 | int ret; | ||
145 | u8 intstat[LP8788_NUM_INTREGS]; | ||
146 | |||
147 | /* clear interrupts */ | ||
148 | ret = lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS); | ||
149 | if (ret) | ||
150 | return ret; | ||
151 | |||
152 | val = LP8727_ID200_EN | LP8727_ADC_EN | LP8727_CP_EN; | ||
153 | ret = lp8727_write_byte(pchg, LP8727_CTRL1, val); | ||
154 | if (ret) | ||
155 | return ret; | ||
156 | |||
157 | val = LP8727_INT_EN | LP8727_CHGDET_EN; | ||
158 | return lp8727_write_byte(pchg, LP8727_CTRL2, val); | ||
159 | } | ||
160 | |||
161 | static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg) | ||
162 | { | ||
163 | u8 val; | ||
164 | |||
165 | lp8727_read_byte(pchg, LP8727_STATUS1, &val); | ||
166 | return val & LP8727_DCPORT; | ||
167 | } | ||
168 | |||
169 | static int lp8727_is_usb_charger(struct lp8727_chg *pchg) | ||
170 | { | ||
171 | u8 val; | ||
172 | |||
173 | lp8727_read_byte(pchg, LP8727_STATUS1, &val); | ||
174 | return val & LP8727_CHPORT; | ||
175 | } | ||
176 | |||
177 | static inline void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw) | ||
178 | { | ||
179 | lp8727_write_byte(pchg, LP8727_SWCTRL, sw); | ||
180 | } | ||
181 | |||
182 | static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin) | ||
183 | { | ||
184 | struct lp8727_platform_data *pdata = pchg->pdata; | ||
185 | u8 devid = LP8727_ID_NONE; | ||
186 | u8 swctrl = LP8727_SW_DM1_HiZ | LP8727_SW_DP2_HiZ; | ||
187 | |||
188 | switch (id) { | ||
189 | case 0x5: | ||
190 | devid = LP8727_ID_TA; | ||
191 | pchg->chg_param = pdata ? pdata->ac : NULL; | ||
192 | break; | ||
193 | case 0xB: | ||
194 | if (lp8727_is_dedicated_charger(pchg)) { | ||
195 | pchg->chg_param = pdata ? pdata->ac : NULL; | ||
196 | devid = LP8727_ID_DEDICATED_CHG; | ||
197 | } else if (lp8727_is_usb_charger(pchg)) { | ||
198 | pchg->chg_param = pdata ? pdata->usb : NULL; | ||
199 | devid = LP8727_ID_USB_CHG; | ||
200 | swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP; | ||
201 | } else if (vbusin) { | ||
202 | devid = LP8727_ID_USB_DS; | ||
203 | swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP; | ||
204 | } | ||
205 | break; | ||
206 | default: | ||
207 | devid = LP8727_ID_NONE; | ||
208 | pchg->chg_param = NULL; | ||
209 | break; | ||
210 | } | ||
211 | |||
212 | pchg->devid = devid; | ||
213 | lp8727_ctrl_switch(pchg, swctrl); | ||
214 | } | ||
215 | |||
216 | static void lp8727_enable_chgdet(struct lp8727_chg *pchg) | ||
217 | { | ||
218 | u8 val; | ||
219 | |||
220 | lp8727_read_byte(pchg, LP8727_CTRL2, &val); | ||
221 | val |= LP8727_CHGDET_EN; | ||
222 | lp8727_write_byte(pchg, LP8727_CTRL2, val); | ||
223 | } | ||
224 | |||
225 | static void lp8727_delayed_func(struct work_struct *_work) | ||
226 | { | ||
227 | struct lp8727_chg *pchg = container_of(_work, struct lp8727_chg, | ||
228 | work.work); | ||
229 | u8 intstat[LP8788_NUM_INTREGS]; | ||
230 | u8 idno; | ||
231 | u8 vbus; | ||
232 | |||
233 | if (lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS)) { | ||
234 | dev_err(pchg->dev, "can not read INT registers\n"); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | idno = intstat[0] & LP8727_IDNO; | ||
239 | vbus = intstat[0] & LP8727_VBUS; | ||
240 | |||
241 | lp8727_id_detection(pchg, idno, vbus); | ||
242 | lp8727_enable_chgdet(pchg); | ||
243 | |||
244 | power_supply_changed(&pchg->psy->ac); | ||
245 | power_supply_changed(&pchg->psy->usb); | ||
246 | power_supply_changed(&pchg->psy->batt); | ||
247 | } | ||
248 | |||
249 | static irqreturn_t lp8727_isr_func(int irq, void *ptr) | ||
250 | { | ||
251 | struct lp8727_chg *pchg = ptr; | ||
252 | |||
253 | schedule_delayed_work(&pchg->work, pchg->debounce_jiffies); | ||
254 | return IRQ_HANDLED; | ||
255 | } | ||
256 | |||
257 | static int lp8727_setup_irq(struct lp8727_chg *pchg) | ||
258 | { | ||
259 | int ret; | ||
260 | int irq = pchg->client->irq; | ||
261 | unsigned delay_msec = pchg->pdata ? pchg->pdata->debounce_msec : | ||
262 | DEFAULT_DEBOUNCE_MSEC; | ||
263 | |||
264 | INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func); | ||
265 | |||
266 | if (irq <= 0) { | ||
267 | dev_warn(pchg->dev, "invalid irq number: %d\n", irq); | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | ret = request_threaded_irq(irq, NULL, lp8727_isr_func, | ||
272 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
273 | "lp8727_irq", pchg); | ||
274 | |||
275 | if (ret) | ||
276 | return ret; | ||
277 | |||
278 | pchg->irq = irq; | ||
279 | pchg->debounce_jiffies = msecs_to_jiffies(delay_msec); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static void lp8727_release_irq(struct lp8727_chg *pchg) | ||
285 | { | ||
286 | cancel_delayed_work_sync(&pchg->work); | ||
287 | |||
288 | if (pchg->irq) | ||
289 | free_irq(pchg->irq, pchg); | ||
290 | } | ||
291 | |||
292 | static enum power_supply_property lp8727_charger_prop[] = { | ||
293 | POWER_SUPPLY_PROP_ONLINE, | ||
294 | }; | ||
295 | |||
296 | static enum power_supply_property lp8727_battery_prop[] = { | ||
297 | POWER_SUPPLY_PROP_STATUS, | ||
298 | POWER_SUPPLY_PROP_HEALTH, | ||
299 | POWER_SUPPLY_PROP_PRESENT, | ||
300 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
301 | POWER_SUPPLY_PROP_CAPACITY, | ||
302 | POWER_SUPPLY_PROP_TEMP, | ||
303 | }; | ||
304 | |||
305 | static char *battery_supplied_to[] = { | ||
306 | "main_batt", | ||
307 | }; | ||
308 | |||
309 | static int lp8727_charger_get_property(struct power_supply *psy, | ||
310 | enum power_supply_property psp, | ||
311 | union power_supply_propval *val) | ||
312 | { | ||
313 | struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); | ||
314 | |||
315 | if (psp != POWER_SUPPLY_PROP_ONLINE) | ||
316 | return -EINVAL; | ||
317 | |||
318 | val->intval = lp8727_is_charger_attached(psy->name, pchg->devid); | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static bool lp8727_is_high_temperature(enum lp8727_die_temp temp) | ||
324 | { | ||
325 | switch (temp) { | ||
326 | case LP8788_TEMP_95C: | ||
327 | case LP8788_TEMP_115C: | ||
328 | case LP8788_TEMP_135C: | ||
329 | return true; | ||
330 | default: | ||
331 | return false; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | static int lp8727_battery_get_property(struct power_supply *psy, | ||
336 | enum power_supply_property psp, | ||
337 | union power_supply_propval *val) | ||
338 | { | ||
339 | struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); | ||
340 | struct lp8727_platform_data *pdata = pchg->pdata; | ||
341 | enum lp8727_die_temp temp; | ||
342 | u8 read; | ||
343 | |||
344 | switch (psp) { | ||
345 | case POWER_SUPPLY_PROP_STATUS: | ||
346 | if (!lp8727_is_charger_attached(psy->name, pchg->devid)) { | ||
347 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | lp8727_read_byte(pchg, LP8727_STATUS1, &read); | ||
352 | |||
353 | val->intval = (read & LP8727_CHGSTAT) == LP8727_STAT_EOC ? | ||
354 | POWER_SUPPLY_STATUS_FULL : | ||
355 | POWER_SUPPLY_STATUS_CHARGING; | ||
356 | break; | ||
357 | case POWER_SUPPLY_PROP_HEALTH: | ||
358 | lp8727_read_byte(pchg, LP8727_STATUS2, &read); | ||
359 | temp = (read & LP8727_TEMP_STAT) >> LP8727_TEMP_SHIFT; | ||
360 | |||
361 | val->intval = lp8727_is_high_temperature(temp) ? | ||
362 | POWER_SUPPLY_HEALTH_OVERHEAT : | ||
363 | POWER_SUPPLY_HEALTH_GOOD; | ||
364 | break; | ||
365 | case POWER_SUPPLY_PROP_PRESENT: | ||
366 | if (!pdata) | ||
367 | return -EINVAL; | ||
368 | |||
369 | if (pdata->get_batt_present) | ||
370 | val->intval = pchg->pdata->get_batt_present(); | ||
371 | break; | ||
372 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
373 | if (!pdata) | ||
374 | return -EINVAL; | ||
375 | |||
376 | if (pdata->get_batt_level) | ||
377 | val->intval = pchg->pdata->get_batt_level(); | ||
378 | break; | ||
379 | case POWER_SUPPLY_PROP_CAPACITY: | ||
380 | if (!pdata) | ||
381 | return -EINVAL; | ||
382 | |||
383 | if (pdata->get_batt_capacity) | ||
384 | val->intval = pchg->pdata->get_batt_capacity(); | ||
385 | break; | ||
386 | case POWER_SUPPLY_PROP_TEMP: | ||
387 | if (!pdata) | ||
388 | return -EINVAL; | ||
389 | |||
390 | if (pdata->get_batt_temp) | ||
391 | val->intval = pchg->pdata->get_batt_temp(); | ||
392 | break; | ||
393 | default: | ||
394 | break; | ||
395 | } | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static void lp8727_charger_changed(struct power_supply *psy) | ||
401 | { | ||
402 | struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent); | ||
403 | u8 eoc_level; | ||
404 | u8 ichg; | ||
405 | u8 val; | ||
406 | |||
407 | /* skip if no charger exists */ | ||
408 | if (!lp8727_is_charger_attached(psy->name, pchg->devid)) | ||
409 | return; | ||
410 | |||
411 | /* update charging parameters */ | ||
412 | if (pchg->chg_param) { | ||
413 | eoc_level = pchg->chg_param->eoc_level; | ||
414 | ichg = pchg->chg_param->ichg; | ||
415 | val = (ichg << LP8727_ICHG_SHIFT) | eoc_level; | ||
416 | lp8727_write_byte(pchg, LP8727_CHGCTRL2, val); | ||
417 | } | ||
418 | } | ||
419 | |||
420 | static int lp8727_register_psy(struct lp8727_chg *pchg) | ||
421 | { | ||
422 | struct lp8727_psy *psy; | ||
423 | |||
424 | psy = devm_kzalloc(pchg->dev, sizeof(*psy), GFP_KERNEL); | ||
425 | if (!psy) | ||
426 | return -ENOMEM; | ||
427 | |||
428 | pchg->psy = psy; | ||
429 | |||
430 | psy->ac.name = "ac"; | ||
431 | psy->ac.type = POWER_SUPPLY_TYPE_MAINS; | ||
432 | psy->ac.properties = lp8727_charger_prop; | ||
433 | psy->ac.num_properties = ARRAY_SIZE(lp8727_charger_prop); | ||
434 | psy->ac.get_property = lp8727_charger_get_property; | ||
435 | psy->ac.supplied_to = battery_supplied_to; | ||
436 | psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to); | ||
437 | |||
438 | if (power_supply_register(pchg->dev, &psy->ac)) | ||
439 | goto err_psy_ac; | ||
440 | |||
441 | psy->usb.name = "usb"; | ||
442 | psy->usb.type = POWER_SUPPLY_TYPE_USB; | ||
443 | psy->usb.properties = lp8727_charger_prop; | ||
444 | psy->usb.num_properties = ARRAY_SIZE(lp8727_charger_prop); | ||
445 | psy->usb.get_property = lp8727_charger_get_property; | ||
446 | psy->usb.supplied_to = battery_supplied_to; | ||
447 | psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to); | ||
448 | |||
449 | if (power_supply_register(pchg->dev, &psy->usb)) | ||
450 | goto err_psy_usb; | ||
451 | |||
452 | psy->batt.name = "main_batt"; | ||
453 | psy->batt.type = POWER_SUPPLY_TYPE_BATTERY; | ||
454 | psy->batt.properties = lp8727_battery_prop; | ||
455 | psy->batt.num_properties = ARRAY_SIZE(lp8727_battery_prop); | ||
456 | psy->batt.get_property = lp8727_battery_get_property; | ||
457 | psy->batt.external_power_changed = lp8727_charger_changed; | ||
458 | |||
459 | if (power_supply_register(pchg->dev, &psy->batt)) | ||
460 | goto err_psy_batt; | ||
461 | |||
462 | return 0; | ||
463 | |||
464 | err_psy_batt: | ||
465 | power_supply_unregister(&psy->usb); | ||
466 | err_psy_usb: | ||
467 | power_supply_unregister(&psy->ac); | ||
468 | err_psy_ac: | ||
469 | return -EPERM; | ||
470 | } | ||
471 | |||
472 | static void lp8727_unregister_psy(struct lp8727_chg *pchg) | ||
473 | { | ||
474 | struct lp8727_psy *psy = pchg->psy; | ||
475 | |||
476 | if (!psy) | ||
477 | return; | ||
478 | |||
479 | power_supply_unregister(&psy->ac); | ||
480 | power_supply_unregister(&psy->usb); | ||
481 | power_supply_unregister(&psy->batt); | ||
482 | } | ||
483 | |||
484 | static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) | ||
485 | { | ||
486 | struct lp8727_chg *pchg; | ||
487 | int ret; | ||
488 | |||
489 | if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
490 | return -EIO; | ||
491 | |||
492 | pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL); | ||
493 | if (!pchg) | ||
494 | return -ENOMEM; | ||
495 | |||
496 | pchg->client = cl; | ||
497 | pchg->dev = &cl->dev; | ||
498 | pchg->pdata = cl->dev.platform_data; | ||
499 | i2c_set_clientdata(cl, pchg); | ||
500 | |||
501 | mutex_init(&pchg->xfer_lock); | ||
502 | |||
503 | ret = lp8727_init_device(pchg); | ||
504 | if (ret) { | ||
505 | dev_err(pchg->dev, "i2c communication err: %d", ret); | ||
506 | return ret; | ||
507 | } | ||
508 | |||
509 | ret = lp8727_register_psy(pchg); | ||
510 | if (ret) { | ||
511 | dev_err(pchg->dev, "power supplies register err: %d", ret); | ||
512 | return ret; | ||
513 | } | ||
514 | |||
515 | ret = lp8727_setup_irq(pchg); | ||
516 | if (ret) { | ||
517 | dev_err(pchg->dev, "irq handler err: %d", ret); | ||
518 | lp8727_unregister_psy(pchg); | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int lp8727_remove(struct i2c_client *cl) | ||
526 | { | ||
527 | struct lp8727_chg *pchg = i2c_get_clientdata(cl); | ||
528 | |||
529 | lp8727_release_irq(pchg); | ||
530 | lp8727_unregister_psy(pchg); | ||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static const struct i2c_device_id lp8727_ids[] = { | ||
535 | {"lp8727", 0}, | ||
536 | { } | ||
537 | }; | ||
538 | MODULE_DEVICE_TABLE(i2c, lp8727_ids); | ||
539 | |||
540 | static struct i2c_driver lp8727_driver = { | ||
541 | .driver = { | ||
542 | .name = "lp8727", | ||
543 | }, | ||
544 | .probe = lp8727_probe, | ||
545 | .remove = lp8727_remove, | ||
546 | .id_table = lp8727_ids, | ||
547 | }; | ||
548 | module_i2c_driver(lp8727_driver); | ||
549 | |||
550 | MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver"); | ||
551 | MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>"); | ||
552 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c deleted file mode 100644 index 22b6407c9ca..00000000000 --- a/drivers/power/lp8788-charger.c +++ /dev/null | |||
@@ -1,752 +0,0 @@ | |||
1 | /* | ||
2 | * TI LP8788 MFD - battery charger driver | ||
3 | * | ||
4 | * Copyright 2012 Texas Instruments | ||
5 | * | ||
6 | * Author: Milo(Woogyom) Kim <milo.kim@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/err.h> | ||
15 | #include <linux/iio/consumer.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/irqdomain.h> | ||
18 | #include <linux/mfd/lp8788.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/power_supply.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | |||
25 | /* register address */ | ||
26 | #define LP8788_CHG_STATUS 0x07 | ||
27 | #define LP8788_CHG_IDCIN 0x13 | ||
28 | #define LP8788_CHG_IBATT 0x14 | ||
29 | #define LP8788_CHG_VTERM 0x15 | ||
30 | #define LP8788_CHG_EOC 0x16 | ||
31 | |||
32 | /* mask/shift bits */ | ||
33 | #define LP8788_CHG_INPUT_STATE_M 0x03 /* Addr 07h */ | ||
34 | #define LP8788_CHG_STATE_M 0x3C | ||
35 | #define LP8788_CHG_STATE_S 2 | ||
36 | #define LP8788_NO_BATT_M BIT(6) | ||
37 | #define LP8788_BAD_BATT_M BIT(7) | ||
38 | #define LP8788_CHG_IBATT_M 0x1F /* Addr 14h */ | ||
39 | #define LP8788_CHG_VTERM_M 0x0F /* Addr 15h */ | ||
40 | #define LP8788_CHG_EOC_LEVEL_M 0x30 /* Addr 16h */ | ||
41 | #define LP8788_CHG_EOC_LEVEL_S 4 | ||
42 | #define LP8788_CHG_EOC_TIME_M 0x0E | ||
43 | #define LP8788_CHG_EOC_TIME_S 1 | ||
44 | #define LP8788_CHG_EOC_MODE_M BIT(0) | ||
45 | |||
46 | #define LP8788_CHARGER_NAME "charger" | ||
47 | #define LP8788_BATTERY_NAME "main_batt" | ||
48 | |||
49 | #define LP8788_CHG_START 0x11 | ||
50 | #define LP8788_CHG_END 0x1C | ||
51 | |||
52 | #define LP8788_BUF_SIZE 40 | ||
53 | #define LP8788_ISEL_MAX 23 | ||
54 | #define LP8788_ISEL_STEP 50 | ||
55 | #define LP8788_VTERM_MIN 4100 | ||
56 | #define LP8788_VTERM_STEP 25 | ||
57 | #define LP8788_MAX_BATT_CAPACITY 100 | ||
58 | #define LP8788_MAX_CHG_IRQS 11 | ||
59 | |||
60 | enum lp8788_charging_state { | ||
61 | LP8788_OFF, | ||
62 | LP8788_WARM_UP, | ||
63 | LP8788_LOW_INPUT = 0x3, | ||
64 | LP8788_PRECHARGE, | ||
65 | LP8788_CC, | ||
66 | LP8788_CV, | ||
67 | LP8788_MAINTENANCE, | ||
68 | LP8788_BATTERY_FAULT, | ||
69 | LP8788_SYSTEM_SUPPORT = 0xC, | ||
70 | LP8788_HIGH_CURRENT = 0xF, | ||
71 | LP8788_MAX_CHG_STATE, | ||
72 | }; | ||
73 | |||
74 | enum lp8788_charger_adc_sel { | ||
75 | LP8788_VBATT, | ||
76 | LP8788_BATT_TEMP, | ||
77 | LP8788_NUM_CHG_ADC, | ||
78 | }; | ||
79 | |||
80 | enum lp8788_charger_input_state { | ||
81 | LP8788_SYSTEM_SUPPLY = 1, | ||
82 | LP8788_FULL_FUNCTION, | ||
83 | }; | ||
84 | |||
85 | /* | ||
86 | * struct lp8788_chg_irq | ||
87 | * @which : lp8788 interrupt id | ||
88 | * @virq : Linux IRQ number from irq_domain | ||
89 | */ | ||
90 | struct lp8788_chg_irq { | ||
91 | enum lp8788_int_id which; | ||
92 | int virq; | ||
93 | }; | ||
94 | |||
95 | /* | ||
96 | * struct lp8788_charger | ||
97 | * @lp : used for accessing the registers of mfd lp8788 device | ||
98 | * @charger : power supply driver for the battery charger | ||
99 | * @battery : power supply driver for the battery | ||
100 | * @charger_work : work queue for charger input interrupts | ||
101 | * @chan : iio channels for getting adc values | ||
102 | * eg) battery voltage, capacity and temperature | ||
103 | * @irqs : charger dedicated interrupts | ||
104 | * @num_irqs : total numbers of charger interrupts | ||
105 | * @pdata : charger platform specific data | ||
106 | */ | ||
107 | struct lp8788_charger { | ||
108 | struct lp8788 *lp; | ||
109 | struct power_supply charger; | ||
110 | struct power_supply battery; | ||
111 | struct work_struct charger_work; | ||
112 | struct iio_channel *chan[LP8788_NUM_CHG_ADC]; | ||
113 | struct lp8788_chg_irq irqs[LP8788_MAX_CHG_IRQS]; | ||
114 | int num_irqs; | ||
115 | struct lp8788_charger_platform_data *pdata; | ||
116 | }; | ||
117 | |||
118 | static char *battery_supplied_to[] = { | ||
119 | LP8788_BATTERY_NAME, | ||
120 | }; | ||
121 | |||
122 | static enum power_supply_property lp8788_charger_prop[] = { | ||
123 | POWER_SUPPLY_PROP_ONLINE, | ||
124 | POWER_SUPPLY_PROP_CURRENT_MAX, | ||
125 | }; | ||
126 | |||
127 | static enum power_supply_property lp8788_battery_prop[] = { | ||
128 | POWER_SUPPLY_PROP_STATUS, | ||
129 | POWER_SUPPLY_PROP_HEALTH, | ||
130 | POWER_SUPPLY_PROP_PRESENT, | ||
131 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
132 | POWER_SUPPLY_PROP_CAPACITY, | ||
133 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | ||
134 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, | ||
135 | POWER_SUPPLY_PROP_TEMP, | ||
136 | }; | ||
137 | |||
138 | static bool lp8788_is_charger_detected(struct lp8788_charger *pchg) | ||
139 | { | ||
140 | u8 data; | ||
141 | |||
142 | lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); | ||
143 | data &= LP8788_CHG_INPUT_STATE_M; | ||
144 | |||
145 | return data == LP8788_SYSTEM_SUPPLY || data == LP8788_FULL_FUNCTION; | ||
146 | } | ||
147 | |||
148 | static int lp8788_charger_get_property(struct power_supply *psy, | ||
149 | enum power_supply_property psp, | ||
150 | union power_supply_propval *val) | ||
151 | { | ||
152 | struct lp8788_charger *pchg = dev_get_drvdata(psy->dev->parent); | ||
153 | u8 read; | ||
154 | |||
155 | switch (psp) { | ||
156 | case POWER_SUPPLY_PROP_ONLINE: | ||
157 | val->intval = lp8788_is_charger_detected(pchg); | ||
158 | break; | ||
159 | case POWER_SUPPLY_PROP_CURRENT_MAX: | ||
160 | lp8788_read_byte(pchg->lp, LP8788_CHG_IDCIN, &read); | ||
161 | val->intval = LP8788_ISEL_STEP * | ||
162 | (min_t(int, read, LP8788_ISEL_MAX) + 1); | ||
163 | break; | ||
164 | default: | ||
165 | return -EINVAL; | ||
166 | } | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int lp8788_get_battery_status(struct lp8788_charger *pchg, | ||
172 | union power_supply_propval *val) | ||
173 | { | ||
174 | enum lp8788_charging_state state; | ||
175 | u8 data; | ||
176 | int ret; | ||
177 | |||
178 | ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); | ||
179 | if (ret) | ||
180 | return ret; | ||
181 | |||
182 | state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S; | ||
183 | switch (state) { | ||
184 | case LP8788_OFF: | ||
185 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
186 | break; | ||
187 | case LP8788_PRECHARGE: | ||
188 | case LP8788_CC: | ||
189 | case LP8788_CV: | ||
190 | case LP8788_HIGH_CURRENT: | ||
191 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
192 | break; | ||
193 | case LP8788_MAINTENANCE: | ||
194 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
195 | break; | ||
196 | default: | ||
197 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int lp8788_get_battery_health(struct lp8788_charger *pchg, | ||
205 | union power_supply_propval *val) | ||
206 | { | ||
207 | u8 data; | ||
208 | int ret; | ||
209 | |||
210 | ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); | ||
211 | if (ret) | ||
212 | return ret; | ||
213 | |||
214 | if (data & LP8788_NO_BATT_M) | ||
215 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
216 | else if (data & LP8788_BAD_BATT_M) | ||
217 | val->intval = POWER_SUPPLY_HEALTH_DEAD; | ||
218 | else | ||
219 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int lp8788_get_battery_present(struct lp8788_charger *pchg, | ||
225 | union power_supply_propval *val) | ||
226 | { | ||
227 | u8 data; | ||
228 | int ret; | ||
229 | |||
230 | ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); | ||
231 | if (ret) | ||
232 | return ret; | ||
233 | |||
234 | val->intval = !(data & LP8788_NO_BATT_M); | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg, int *result) | ||
239 | { | ||
240 | struct iio_channel *channel = pchg->chan[LP8788_VBATT]; | ||
241 | |||
242 | if (!channel) | ||
243 | return -EINVAL; | ||
244 | |||
245 | return iio_read_channel_processed(channel, result); | ||
246 | } | ||
247 | |||
248 | static int lp8788_get_battery_voltage(struct lp8788_charger *pchg, | ||
249 | union power_supply_propval *val) | ||
250 | { | ||
251 | return lp8788_get_vbatt_adc(pchg, &val->intval); | ||
252 | } | ||
253 | |||
254 | static int lp8788_get_battery_capacity(struct lp8788_charger *pchg, | ||
255 | union power_supply_propval *val) | ||
256 | { | ||
257 | struct lp8788 *lp = pchg->lp; | ||
258 | struct lp8788_charger_platform_data *pdata = pchg->pdata; | ||
259 | unsigned int max_vbatt; | ||
260 | int vbatt; | ||
261 | enum lp8788_charging_state state; | ||
262 | u8 data; | ||
263 | int ret; | ||
264 | |||
265 | if (!pdata) | ||
266 | return -EINVAL; | ||
267 | |||
268 | max_vbatt = pdata->max_vbatt_mv; | ||
269 | if (max_vbatt == 0) | ||
270 | return -EINVAL; | ||
271 | |||
272 | ret = lp8788_read_byte(lp, LP8788_CHG_STATUS, &data); | ||
273 | if (ret) | ||
274 | return ret; | ||
275 | |||
276 | state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S; | ||
277 | |||
278 | if (state == LP8788_MAINTENANCE) { | ||
279 | val->intval = LP8788_MAX_BATT_CAPACITY; | ||
280 | } else { | ||
281 | ret = lp8788_get_vbatt_adc(pchg, &vbatt); | ||
282 | if (ret) | ||
283 | return ret; | ||
284 | |||
285 | val->intval = (vbatt * LP8788_MAX_BATT_CAPACITY) / max_vbatt; | ||
286 | val->intval = min(val->intval, LP8788_MAX_BATT_CAPACITY); | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int lp8788_get_battery_temperature(struct lp8788_charger *pchg, | ||
293 | union power_supply_propval *val) | ||
294 | { | ||
295 | struct iio_channel *channel = pchg->chan[LP8788_BATT_TEMP]; | ||
296 | int result; | ||
297 | int ret; | ||
298 | |||
299 | if (!channel) | ||
300 | return -EINVAL; | ||
301 | |||
302 | ret = iio_read_channel_processed(channel, &result); | ||
303 | if (ret < 0) | ||
304 | return -EINVAL; | ||
305 | |||
306 | /* unit: 0.1 'C */ | ||
307 | val->intval = result * 10; | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int lp8788_get_battery_charging_current(struct lp8788_charger *pchg, | ||
313 | union power_supply_propval *val) | ||
314 | { | ||
315 | u8 read; | ||
316 | |||
317 | lp8788_read_byte(pchg->lp, LP8788_CHG_IBATT, &read); | ||
318 | read &= LP8788_CHG_IBATT_M; | ||
319 | val->intval = LP8788_ISEL_STEP * | ||
320 | (min_t(int, read, LP8788_ISEL_MAX) + 1); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int lp8788_get_charging_termination_voltage(struct lp8788_charger *pchg, | ||
326 | union power_supply_propval *val) | ||
327 | { | ||
328 | u8 read; | ||
329 | |||
330 | lp8788_read_byte(pchg->lp, LP8788_CHG_VTERM, &read); | ||
331 | read &= LP8788_CHG_VTERM_M; | ||
332 | val->intval = LP8788_VTERM_MIN + LP8788_VTERM_STEP * read; | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static int lp8788_battery_get_property(struct power_supply *psy, | ||
338 | enum power_supply_property psp, | ||
339 | union power_supply_propval *val) | ||
340 | { | ||
341 | struct lp8788_charger *pchg = dev_get_drvdata(psy->dev->parent); | ||
342 | |||
343 | switch (psp) { | ||
344 | case POWER_SUPPLY_PROP_STATUS: | ||
345 | return lp8788_get_battery_status(pchg, val); | ||
346 | case POWER_SUPPLY_PROP_HEALTH: | ||
347 | return lp8788_get_battery_health(pchg, val); | ||
348 | case POWER_SUPPLY_PROP_PRESENT: | ||
349 | return lp8788_get_battery_present(pchg, val); | ||
350 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
351 | return lp8788_get_battery_voltage(pchg, val); | ||
352 | case POWER_SUPPLY_PROP_CAPACITY: | ||
353 | return lp8788_get_battery_capacity(pchg, val); | ||
354 | case POWER_SUPPLY_PROP_TEMP: | ||
355 | return lp8788_get_battery_temperature(pchg, val); | ||
356 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
357 | return lp8788_get_battery_charging_current(pchg, val); | ||
358 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: | ||
359 | return lp8788_get_charging_termination_voltage(pchg, val); | ||
360 | default: | ||
361 | return -EINVAL; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | static inline bool lp8788_is_valid_charger_register(u8 addr) | ||
366 | { | ||
367 | return addr >= LP8788_CHG_START && addr <= LP8788_CHG_END; | ||
368 | } | ||
369 | |||
370 | static int lp8788_update_charger_params(struct lp8788_charger *pchg) | ||
371 | { | ||
372 | struct lp8788 *lp = pchg->lp; | ||
373 | struct lp8788_charger_platform_data *pdata = pchg->pdata; | ||
374 | struct lp8788_chg_param *param; | ||
375 | int i; | ||
376 | int ret; | ||
377 | |||
378 | if (!pdata || !pdata->chg_params) { | ||
379 | dev_info(lp->dev, "skip updating charger parameters\n"); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /* settting charging parameters */ | ||
384 | for (i = 0; i < pdata->num_chg_params; i++) { | ||
385 | param = pdata->chg_params + i; | ||
386 | |||
387 | if (!param) | ||
388 | continue; | ||
389 | |||
390 | if (lp8788_is_valid_charger_register(param->addr)) { | ||
391 | ret = lp8788_write_byte(lp, param->addr, param->val); | ||
392 | if (ret) | ||
393 | return ret; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static int lp8788_psy_register(struct platform_device *pdev, | ||
401 | struct lp8788_charger *pchg) | ||
402 | { | ||
403 | pchg->charger.name = LP8788_CHARGER_NAME; | ||
404 | pchg->charger.type = POWER_SUPPLY_TYPE_MAINS; | ||
405 | pchg->charger.properties = lp8788_charger_prop; | ||
406 | pchg->charger.num_properties = ARRAY_SIZE(lp8788_charger_prop); | ||
407 | pchg->charger.get_property = lp8788_charger_get_property; | ||
408 | pchg->charger.supplied_to = battery_supplied_to; | ||
409 | pchg->charger.num_supplicants = ARRAY_SIZE(battery_supplied_to); | ||
410 | |||
411 | if (power_supply_register(&pdev->dev, &pchg->charger)) | ||
412 | return -EPERM; | ||
413 | |||
414 | pchg->battery.name = LP8788_BATTERY_NAME; | ||
415 | pchg->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
416 | pchg->battery.properties = lp8788_battery_prop; | ||
417 | pchg->battery.num_properties = ARRAY_SIZE(lp8788_battery_prop); | ||
418 | pchg->battery.get_property = lp8788_battery_get_property; | ||
419 | |||
420 | if (power_supply_register(&pdev->dev, &pchg->battery)) | ||
421 | return -EPERM; | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static void lp8788_psy_unregister(struct lp8788_charger *pchg) | ||
427 | { | ||
428 | power_supply_unregister(&pchg->battery); | ||
429 | power_supply_unregister(&pchg->charger); | ||
430 | } | ||
431 | |||
432 | static void lp8788_charger_event(struct work_struct *work) | ||
433 | { | ||
434 | struct lp8788_charger *pchg = | ||
435 | container_of(work, struct lp8788_charger, charger_work); | ||
436 | struct lp8788_charger_platform_data *pdata = pchg->pdata; | ||
437 | enum lp8788_charger_event event = lp8788_is_charger_detected(pchg); | ||
438 | |||
439 | pdata->charger_event(pchg->lp, event); | ||
440 | } | ||
441 | |||
442 | static bool lp8788_find_irq_id(struct lp8788_charger *pchg, int virq, int *id) | ||
443 | { | ||
444 | bool found; | ||
445 | int i; | ||
446 | |||
447 | for (i = 0; i < pchg->num_irqs; i++) { | ||
448 | if (pchg->irqs[i].virq == virq) { | ||
449 | *id = pchg->irqs[i].which; | ||
450 | found = true; | ||
451 | break; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | return found; | ||
456 | } | ||
457 | |||
458 | static irqreturn_t lp8788_charger_irq_thread(int virq, void *ptr) | ||
459 | { | ||
460 | struct lp8788_charger *pchg = ptr; | ||
461 | struct lp8788_charger_platform_data *pdata = pchg->pdata; | ||
462 | int id = -1; | ||
463 | |||
464 | if (!lp8788_find_irq_id(pchg, virq, &id)) | ||
465 | return IRQ_NONE; | ||
466 | |||
467 | switch (id) { | ||
468 | case LP8788_INT_CHG_INPUT_STATE: | ||
469 | case LP8788_INT_CHG_STATE: | ||
470 | case LP8788_INT_EOC: | ||
471 | case LP8788_INT_BATT_LOW: | ||
472 | case LP8788_INT_NO_BATT: | ||
473 | power_supply_changed(&pchg->charger); | ||
474 | power_supply_changed(&pchg->battery); | ||
475 | break; | ||
476 | default: | ||
477 | break; | ||
478 | } | ||
479 | |||
480 | /* report charger dectection event if used */ | ||
481 | if (!pdata) | ||
482 | goto irq_handled; | ||
483 | |||
484 | if (pdata->charger_event && id == LP8788_INT_CHG_INPUT_STATE) | ||
485 | schedule_work(&pchg->charger_work); | ||
486 | |||
487 | irq_handled: | ||
488 | return IRQ_HANDLED; | ||
489 | } | ||
490 | |||
491 | static int lp8788_set_irqs(struct platform_device *pdev, | ||
492 | struct lp8788_charger *pchg, const char *name) | ||
493 | { | ||
494 | struct resource *r; | ||
495 | struct irq_domain *irqdm = pchg->lp->irqdm; | ||
496 | int irq_start; | ||
497 | int irq_end; | ||
498 | int virq; | ||
499 | int nr_irq; | ||
500 | int i; | ||
501 | int ret; | ||
502 | |||
503 | /* no error even if no irq resource */ | ||
504 | r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, name); | ||
505 | if (!r) | ||
506 | return 0; | ||
507 | |||
508 | irq_start = r->start; | ||
509 | irq_end = r->end; | ||
510 | |||
511 | for (i = irq_start; i <= irq_end; i++) { | ||
512 | nr_irq = pchg->num_irqs; | ||
513 | |||
514 | virq = irq_create_mapping(irqdm, i); | ||
515 | pchg->irqs[nr_irq].virq = virq; | ||
516 | pchg->irqs[nr_irq].which = i; | ||
517 | pchg->num_irqs++; | ||
518 | |||
519 | ret = request_threaded_irq(virq, NULL, | ||
520 | lp8788_charger_irq_thread, | ||
521 | 0, name, pchg); | ||
522 | if (ret) | ||
523 | break; | ||
524 | } | ||
525 | |||
526 | if (i <= irq_end) | ||
527 | goto err_free_irq; | ||
528 | |||
529 | return 0; | ||
530 | |||
531 | err_free_irq: | ||
532 | for (i = 0; i < pchg->num_irqs; i++) | ||
533 | free_irq(pchg->irqs[i].virq, pchg); | ||
534 | return ret; | ||
535 | } | ||
536 | |||
537 | static int lp8788_irq_register(struct platform_device *pdev, | ||
538 | struct lp8788_charger *pchg) | ||
539 | { | ||
540 | struct lp8788 *lp = pchg->lp; | ||
541 | const char *name[] = { | ||
542 | LP8788_CHG_IRQ, LP8788_PRSW_IRQ, LP8788_BATT_IRQ | ||
543 | }; | ||
544 | int i; | ||
545 | int ret; | ||
546 | |||
547 | INIT_WORK(&pchg->charger_work, lp8788_charger_event); | ||
548 | pchg->num_irqs = 0; | ||
549 | |||
550 | for (i = 0; i < ARRAY_SIZE(name); i++) { | ||
551 | ret = lp8788_set_irqs(pdev, pchg, name[i]); | ||
552 | if (ret) { | ||
553 | dev_warn(lp->dev, "irq setup failed: %s\n", name[i]); | ||
554 | return ret; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | if (pchg->num_irqs > LP8788_MAX_CHG_IRQS) { | ||
559 | dev_err(lp->dev, "invalid total number of irqs: %d\n", | ||
560 | pchg->num_irqs); | ||
561 | return -EINVAL; | ||
562 | } | ||
563 | |||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | static void lp8788_irq_unregister(struct platform_device *pdev, | ||
569 | struct lp8788_charger *pchg) | ||
570 | { | ||
571 | int i; | ||
572 | int irq; | ||
573 | |||
574 | for (i = 0; i < pchg->num_irqs; i++) { | ||
575 | irq = pchg->irqs[i].virq; | ||
576 | if (!irq) | ||
577 | continue; | ||
578 | |||
579 | free_irq(irq, pchg); | ||
580 | } | ||
581 | } | ||
582 | |||
583 | static void lp8788_setup_adc_channel(const char *consumer_name, | ||
584 | struct lp8788_charger *pchg) | ||
585 | { | ||
586 | struct lp8788_charger_platform_data *pdata = pchg->pdata; | ||
587 | struct iio_channel *chan; | ||
588 | |||
589 | if (!pdata) | ||
590 | return; | ||
591 | |||
592 | /* ADC channel for battery voltage */ | ||
593 | chan = iio_channel_get(consumer_name, pdata->adc_vbatt); | ||
594 | pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan; | ||
595 | |||
596 | /* ADC channel for battery temperature */ | ||
597 | chan = iio_channel_get(consumer_name, pdata->adc_batt_temp); | ||
598 | pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan; | ||
599 | } | ||
600 | |||
601 | static void lp8788_release_adc_channel(struct lp8788_charger *pchg) | ||
602 | { | ||
603 | int i; | ||
604 | |||
605 | for (i = 0; i < LP8788_NUM_CHG_ADC; i++) { | ||
606 | if (!pchg->chan[i]) | ||
607 | continue; | ||
608 | |||
609 | iio_channel_release(pchg->chan[i]); | ||
610 | pchg->chan[i] = NULL; | ||
611 | } | ||
612 | } | ||
613 | |||
614 | static ssize_t lp8788_show_charger_status(struct device *dev, | ||
615 | struct device_attribute *attr, char *buf) | ||
616 | { | ||
617 | struct lp8788_charger *pchg = dev_get_drvdata(dev); | ||
618 | enum lp8788_charging_state state; | ||
619 | char *desc[LP8788_MAX_CHG_STATE] = { | ||
620 | [LP8788_OFF] = "CHARGER OFF", | ||
621 | [LP8788_WARM_UP] = "WARM UP", | ||
622 | [LP8788_LOW_INPUT] = "LOW INPUT STATE", | ||
623 | [LP8788_PRECHARGE] = "CHARGING - PRECHARGE", | ||
624 | [LP8788_CC] = "CHARGING - CC", | ||
625 | [LP8788_CV] = "CHARGING - CV", | ||
626 | [LP8788_MAINTENANCE] = "NO CHARGING - MAINTENANCE", | ||
627 | [LP8788_BATTERY_FAULT] = "BATTERY FAULT", | ||
628 | [LP8788_SYSTEM_SUPPORT] = "SYSTEM SUPPORT", | ||
629 | [LP8788_HIGH_CURRENT] = "HIGH CURRENT", | ||
630 | }; | ||
631 | u8 data; | ||
632 | |||
633 | lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); | ||
634 | state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S; | ||
635 | |||
636 | return scnprintf(buf, LP8788_BUF_SIZE, "%s\n", desc[state]); | ||
637 | } | ||
638 | |||
639 | static ssize_t lp8788_show_eoc_time(struct device *dev, | ||
640 | struct device_attribute *attr, char *buf) | ||
641 | { | ||
642 | struct lp8788_charger *pchg = dev_get_drvdata(dev); | ||
643 | char *stime[] = { "400ms", "5min", "10min", "15min", | ||
644 | "20min", "25min", "30min" "No timeout" }; | ||
645 | u8 val; | ||
646 | |||
647 | lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val); | ||
648 | val = (val & LP8788_CHG_EOC_TIME_M) >> LP8788_CHG_EOC_TIME_S; | ||
649 | |||
650 | return scnprintf(buf, LP8788_BUF_SIZE, "End Of Charge Time: %s\n", | ||
651 | stime[val]); | ||
652 | } | ||
653 | |||
654 | static ssize_t lp8788_show_eoc_level(struct device *dev, | ||
655 | struct device_attribute *attr, char *buf) | ||
656 | { | ||
657 | struct lp8788_charger *pchg = dev_get_drvdata(dev); | ||
658 | char *abs_level[] = { "25mA", "49mA", "75mA", "98mA" }; | ||
659 | char *relative_level[] = { "5%", "10%", "15%", "20%" }; | ||
660 | char *level; | ||
661 | u8 val; | ||
662 | u8 mode; | ||
663 | |||
664 | lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val); | ||
665 | |||
666 | mode = val & LP8788_CHG_EOC_MODE_M; | ||
667 | val = (val & LP8788_CHG_EOC_LEVEL_M) >> LP8788_CHG_EOC_LEVEL_S; | ||
668 | level = mode ? abs_level[val] : relative_level[val]; | ||
669 | |||
670 | return scnprintf(buf, LP8788_BUF_SIZE, "End Of Charge Level: %s\n", | ||
671 | level); | ||
672 | } | ||
673 | |||
674 | static DEVICE_ATTR(charger_status, S_IRUSR, lp8788_show_charger_status, NULL); | ||
675 | static DEVICE_ATTR(eoc_time, S_IRUSR, lp8788_show_eoc_time, NULL); | ||
676 | static DEVICE_ATTR(eoc_level, S_IRUSR, lp8788_show_eoc_level, NULL); | ||
677 | |||
678 | static struct attribute *lp8788_charger_attr[] = { | ||
679 | &dev_attr_charger_status.attr, | ||
680 | &dev_attr_eoc_time.attr, | ||
681 | &dev_attr_eoc_level.attr, | ||
682 | NULL, | ||
683 | }; | ||
684 | |||
685 | static const struct attribute_group lp8788_attr_group = { | ||
686 | .attrs = lp8788_charger_attr, | ||
687 | }; | ||
688 | |||
689 | static int lp8788_charger_probe(struct platform_device *pdev) | ||
690 | { | ||
691 | struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); | ||
692 | struct lp8788_charger *pchg; | ||
693 | int ret; | ||
694 | |||
695 | pchg = devm_kzalloc(lp->dev, sizeof(struct lp8788_charger), GFP_KERNEL); | ||
696 | if (!pchg) | ||
697 | return -ENOMEM; | ||
698 | |||
699 | pchg->lp = lp; | ||
700 | pchg->pdata = lp->pdata ? lp->pdata->chg_pdata : NULL; | ||
701 | platform_set_drvdata(pdev, pchg); | ||
702 | |||
703 | ret = lp8788_update_charger_params(pchg); | ||
704 | if (ret) | ||
705 | return ret; | ||
706 | |||
707 | lp8788_setup_adc_channel(pdev->name, pchg); | ||
708 | |||
709 | ret = lp8788_psy_register(pdev, pchg); | ||
710 | if (ret) | ||
711 | return ret; | ||
712 | |||
713 | ret = sysfs_create_group(&pdev->dev.kobj, &lp8788_attr_group); | ||
714 | if (ret) { | ||
715 | lp8788_psy_unregister(pchg); | ||
716 | return ret; | ||
717 | } | ||
718 | |||
719 | ret = lp8788_irq_register(pdev, pchg); | ||
720 | if (ret) | ||
721 | dev_warn(lp->dev, "failed to register charger irq: %d\n", ret); | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static int lp8788_charger_remove(struct platform_device *pdev) | ||
727 | { | ||
728 | struct lp8788_charger *pchg = platform_get_drvdata(pdev); | ||
729 | |||
730 | flush_work(&pchg->charger_work); | ||
731 | lp8788_irq_unregister(pdev, pchg); | ||
732 | sysfs_remove_group(&pdev->dev.kobj, &lp8788_attr_group); | ||
733 | lp8788_psy_unregister(pchg); | ||
734 | lp8788_release_adc_channel(pchg); | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static struct platform_driver lp8788_charger_driver = { | ||
740 | .probe = lp8788_charger_probe, | ||
741 | .remove = lp8788_charger_remove, | ||
742 | .driver = { | ||
743 | .name = LP8788_DEV_CHARGER, | ||
744 | .owner = THIS_MODULE, | ||
745 | }, | ||
746 | }; | ||
747 | module_platform_driver(lp8788_charger_driver); | ||
748 | |||
749 | MODULE_DESCRIPTION("TI LP8788 Charger Driver"); | ||
750 | MODULE_AUTHOR("Milo Kim"); | ||
751 | MODULE_LICENSE("GPL"); | ||
752 | MODULE_ALIAS("platform:lp8788-charger"); | ||
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c index 22cfe9cc472..2f2f9a6f54f 100644 --- a/drivers/power/max17040_battery.c +++ b/drivers/power/max17040_battery.c | |||
@@ -197,7 +197,7 @@ static enum power_supply_property max17040_battery_props[] = { | |||
197 | POWER_SUPPLY_PROP_CAPACITY, | 197 | POWER_SUPPLY_PROP_CAPACITY, |
198 | }; | 198 | }; |
199 | 199 | ||
200 | static int max17040_probe(struct i2c_client *client, | 200 | static int __devinit max17040_probe(struct i2c_client *client, |
201 | const struct i2c_device_id *id) | 201 | const struct i2c_device_id *id) |
202 | { | 202 | { |
203 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 203 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
@@ -232,13 +232,13 @@ static int max17040_probe(struct i2c_client *client, | |||
232 | max17040_reset(client); | 232 | max17040_reset(client); |
233 | max17040_get_version(client); | 233 | max17040_get_version(client); |
234 | 234 | ||
235 | INIT_DEFERRABLE_WORK(&chip->work, max17040_work); | 235 | INIT_DELAYED_WORK_DEFERRABLE(&chip->work, max17040_work); |
236 | schedule_delayed_work(&chip->work, MAX17040_DELAY); | 236 | schedule_delayed_work(&chip->work, MAX17040_DELAY); |
237 | 237 | ||
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | static int max17040_remove(struct i2c_client *client) | 241 | static int __devexit max17040_remove(struct i2c_client *client) |
242 | { | 242 | { |
243 | struct max17040_chip *chip = i2c_get_clientdata(client); | 243 | struct max17040_chip *chip = i2c_get_clientdata(client); |
244 | 244 | ||
@@ -285,12 +285,23 @@ static struct i2c_driver max17040_i2c_driver = { | |||
285 | .name = "max17040", | 285 | .name = "max17040", |
286 | }, | 286 | }, |
287 | .probe = max17040_probe, | 287 | .probe = max17040_probe, |
288 | .remove = max17040_remove, | 288 | .remove = __devexit_p(max17040_remove), |
289 | .suspend = max17040_suspend, | 289 | .suspend = max17040_suspend, |
290 | .resume = max17040_resume, | 290 | .resume = max17040_resume, |
291 | .id_table = max17040_id, | 291 | .id_table = max17040_id, |
292 | }; | 292 | }; |
293 | module_i2c_driver(max17040_i2c_driver); | 293 | |
294 | static int __init max17040_init(void) | ||
295 | { | ||
296 | return i2c_add_driver(&max17040_i2c_driver); | ||
297 | } | ||
298 | module_init(max17040_init); | ||
299 | |||
300 | static void __exit max17040_exit(void) | ||
301 | { | ||
302 | i2c_del_driver(&max17040_i2c_driver); | ||
303 | } | ||
304 | module_exit(max17040_exit); | ||
294 | 305 | ||
295 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); | 306 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); |
296 | MODULE_DESCRIPTION("MAX17040 Fuel Gauge"); | 307 | MODULE_DESCRIPTION("MAX17040 Fuel Gauge"); |
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c index d664ef58afa..98bfab35b8e 100644 --- a/drivers/power/max17042_battery.c +++ b/drivers/power/max17042_battery.c | |||
@@ -23,55 +23,16 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/module.h> | ||
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
29 | #include <linux/delay.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/pm.h> | ||
32 | #include <linux/mod_devicetable.h> | 28 | #include <linux/mod_devicetable.h> |
33 | #include <linux/power_supply.h> | 29 | #include <linux/power_supply.h> |
34 | #include <linux/power/max17042_battery.h> | 30 | #include <linux/power/max17042_battery.h> |
35 | #include <linux/of.h> | ||
36 | |||
37 | /* Status register bits */ | ||
38 | #define STATUS_POR_BIT (1 << 1) | ||
39 | #define STATUS_BST_BIT (1 << 3) | ||
40 | #define STATUS_VMN_BIT (1 << 8) | ||
41 | #define STATUS_TMN_BIT (1 << 9) | ||
42 | #define STATUS_SMN_BIT (1 << 10) | ||
43 | #define STATUS_BI_BIT (1 << 11) | ||
44 | #define STATUS_VMX_BIT (1 << 12) | ||
45 | #define STATUS_TMX_BIT (1 << 13) | ||
46 | #define STATUS_SMX_BIT (1 << 14) | ||
47 | #define STATUS_BR_BIT (1 << 15) | ||
48 | |||
49 | /* Interrupt mask bits */ | ||
50 | #define CONFIG_ALRT_BIT_ENBL (1 << 2) | ||
51 | #define STATUS_INTR_SOCMIN_BIT (1 << 10) | ||
52 | #define STATUS_INTR_SOCMAX_BIT (1 << 14) | ||
53 | |||
54 | #define VFSOC0_LOCK 0x0000 | ||
55 | #define VFSOC0_UNLOCK 0x0080 | ||
56 | #define MODEL_UNLOCK1 0X0059 | ||
57 | #define MODEL_UNLOCK2 0X00C4 | ||
58 | #define MODEL_LOCK1 0X0000 | ||
59 | #define MODEL_LOCK2 0X0000 | ||
60 | |||
61 | #define dQ_ACC_DIV 0x4 | ||
62 | #define dP_ACC_100 0x1900 | ||
63 | #define dP_ACC_200 0x3200 | ||
64 | |||
65 | #define MAX17042_IC_VERSION 0x0092 | ||
66 | #define MAX17047_IC_VERSION 0x00AC /* same for max17050 */ | ||
67 | 31 | ||
68 | struct max17042_chip { | 32 | struct max17042_chip { |
69 | struct i2c_client *client; | 33 | struct i2c_client *client; |
70 | struct power_supply battery; | 34 | struct power_supply battery; |
71 | enum max170xx_chip_type chip_type; | ||
72 | struct max17042_platform_data *pdata; | 35 | struct max17042_platform_data *pdata; |
73 | struct work_struct work; | ||
74 | int init_complete; | ||
75 | }; | 36 | }; |
76 | 37 | ||
77 | static int max17042_write_reg(struct i2c_client *client, u8 reg, u16 value) | 38 | static int max17042_write_reg(struct i2c_client *client, u8 reg, u16 value) |
@@ -110,10 +71,8 @@ static enum power_supply_property max17042_battery_props[] = { | |||
110 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | 71 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, |
111 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 72 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
112 | POWER_SUPPLY_PROP_VOLTAGE_AVG, | 73 | POWER_SUPPLY_PROP_VOLTAGE_AVG, |
113 | POWER_SUPPLY_PROP_VOLTAGE_OCV, | ||
114 | POWER_SUPPLY_PROP_CAPACITY, | 74 | POWER_SUPPLY_PROP_CAPACITY, |
115 | POWER_SUPPLY_PROP_CHARGE_FULL, | 75 | POWER_SUPPLY_PROP_CHARGE_FULL, |
116 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | ||
117 | POWER_SUPPLY_PROP_TEMP, | 76 | POWER_SUPPLY_PROP_TEMP, |
118 | POWER_SUPPLY_PROP_CURRENT_NOW, | 77 | POWER_SUPPLY_PROP_CURRENT_NOW, |
119 | POWER_SUPPLY_PROP_CURRENT_AVG, | 78 | POWER_SUPPLY_PROP_CURRENT_AVG, |
@@ -125,96 +84,55 @@ static int max17042_get_property(struct power_supply *psy, | |||
125 | { | 84 | { |
126 | struct max17042_chip *chip = container_of(psy, | 85 | struct max17042_chip *chip = container_of(psy, |
127 | struct max17042_chip, battery); | 86 | struct max17042_chip, battery); |
128 | int ret; | ||
129 | |||
130 | if (!chip->init_complete) | ||
131 | return -EAGAIN; | ||
132 | 87 | ||
133 | switch (psp) { | 88 | switch (psp) { |
134 | case POWER_SUPPLY_PROP_PRESENT: | 89 | case POWER_SUPPLY_PROP_PRESENT: |
135 | ret = max17042_read_reg(chip->client, MAX17042_STATUS); | 90 | val->intval = max17042_read_reg(chip->client, |
136 | if (ret < 0) | 91 | MAX17042_STATUS); |
137 | return ret; | 92 | if (val->intval & MAX17042_STATUS_BattAbsent) |
138 | |||
139 | if (ret & MAX17042_STATUS_BattAbsent) | ||
140 | val->intval = 0; | 93 | val->intval = 0; |
141 | else | 94 | else |
142 | val->intval = 1; | 95 | val->intval = 1; |
143 | break; | 96 | break; |
144 | case POWER_SUPPLY_PROP_CYCLE_COUNT: | 97 | case POWER_SUPPLY_PROP_CYCLE_COUNT: |
145 | ret = max17042_read_reg(chip->client, MAX17042_Cycles); | 98 | val->intval = max17042_read_reg(chip->client, |
146 | if (ret < 0) | 99 | MAX17042_Cycles); |
147 | return ret; | ||
148 | |||
149 | val->intval = ret; | ||
150 | break; | 100 | break; |
151 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: | 101 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: |
152 | ret = max17042_read_reg(chip->client, MAX17042_MinMaxVolt); | 102 | val->intval = max17042_read_reg(chip->client, |
153 | if (ret < 0) | 103 | MAX17042_MinMaxVolt); |
154 | return ret; | 104 | val->intval >>= 8; |
155 | |||
156 | val->intval = ret >> 8; | ||
157 | val->intval *= 20000; /* Units of LSB = 20mV */ | 105 | val->intval *= 20000; /* Units of LSB = 20mV */ |
158 | break; | 106 | break; |
159 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | 107 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: |
160 | if (chip->chip_type == MAX17042) | 108 | val->intval = max17042_read_reg(chip->client, |
161 | ret = max17042_read_reg(chip->client, MAX17042_V_empty); | 109 | MAX17042_V_empty); |
162 | else | 110 | val->intval >>= 7; |
163 | ret = max17042_read_reg(chip->client, MAX17047_V_empty); | ||
164 | if (ret < 0) | ||
165 | return ret; | ||
166 | |||
167 | val->intval = ret >> 7; | ||
168 | val->intval *= 10000; /* Units of LSB = 10mV */ | 111 | val->intval *= 10000; /* Units of LSB = 10mV */ |
169 | break; | 112 | break; |
170 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 113 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
171 | ret = max17042_read_reg(chip->client, MAX17042_VCELL); | 114 | val->intval = max17042_read_reg(chip->client, |
172 | if (ret < 0) | 115 | MAX17042_VCELL) * 83; /* 1000 / 12 = 83 */ |
173 | return ret; | ||
174 | |||
175 | val->intval = ret * 625 / 8; | ||
176 | break; | 116 | break; |
177 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | 117 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: |
178 | ret = max17042_read_reg(chip->client, MAX17042_AvgVCELL); | 118 | val->intval = max17042_read_reg(chip->client, |
179 | if (ret < 0) | 119 | MAX17042_AvgVCELL) * 83; |
180 | return ret; | ||
181 | |||
182 | val->intval = ret * 625 / 8; | ||
183 | break; | ||
184 | case POWER_SUPPLY_PROP_VOLTAGE_OCV: | ||
185 | ret = max17042_read_reg(chip->client, MAX17042_OCVInternal); | ||
186 | if (ret < 0) | ||
187 | return ret; | ||
188 | |||
189 | val->intval = ret * 625 / 8; | ||
190 | break; | 120 | break; |
191 | case POWER_SUPPLY_PROP_CAPACITY: | 121 | case POWER_SUPPLY_PROP_CAPACITY: |
192 | ret = max17042_read_reg(chip->client, MAX17042_RepSOC); | 122 | val->intval = max17042_read_reg(chip->client, |
193 | if (ret < 0) | 123 | MAX17042_SOC) / 256; |
194 | return ret; | ||
195 | |||
196 | val->intval = ret >> 8; | ||
197 | break; | 124 | break; |
198 | case POWER_SUPPLY_PROP_CHARGE_FULL: | 125 | case POWER_SUPPLY_PROP_CHARGE_FULL: |
199 | ret = max17042_read_reg(chip->client, MAX17042_FullCAP); | 126 | val->intval = max17042_read_reg(chip->client, |
200 | if (ret < 0) | 127 | MAX17042_RepSOC); |
201 | return ret; | 128 | if ((val->intval / 256) >= MAX17042_BATTERY_FULL) |
202 | 129 | val->intval = 1; | |
203 | val->intval = ret * 1000 / 2; | 130 | else if (val->intval >= 0) |
204 | break; | 131 | val->intval = 0; |
205 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: | ||
206 | ret = max17042_read_reg(chip->client, MAX17042_QH); | ||
207 | if (ret < 0) | ||
208 | return ret; | ||
209 | |||
210 | val->intval = ret * 1000 / 2; | ||
211 | break; | 132 | break; |
212 | case POWER_SUPPLY_PROP_TEMP: | 133 | case POWER_SUPPLY_PROP_TEMP: |
213 | ret = max17042_read_reg(chip->client, MAX17042_TEMP); | 134 | val->intval = max17042_read_reg(chip->client, |
214 | if (ret < 0) | 135 | MAX17042_TEMP); |
215 | return ret; | ||
216 | |||
217 | val->intval = ret; | ||
218 | /* The value is signed. */ | 136 | /* The value is signed. */ |
219 | if (val->intval & 0x8000) { | 137 | if (val->intval & 0x8000) { |
220 | val->intval = (0x7fff & ~val->intval) + 1; | 138 | val->intval = (0x7fff & ~val->intval) + 1; |
@@ -226,30 +144,24 @@ static int max17042_get_property(struct power_supply *psy, | |||
226 | break; | 144 | break; |
227 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 145 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
228 | if (chip->pdata->enable_current_sense) { | 146 | if (chip->pdata->enable_current_sense) { |
229 | ret = max17042_read_reg(chip->client, MAX17042_Current); | 147 | val->intval = max17042_read_reg(chip->client, |
230 | if (ret < 0) | 148 | MAX17042_Current); |
231 | return ret; | ||
232 | |||
233 | val->intval = ret; | ||
234 | if (val->intval & 0x8000) { | 149 | if (val->intval & 0x8000) { |
235 | /* Negative */ | 150 | /* Negative */ |
236 | val->intval = ~val->intval & 0x7fff; | 151 | val->intval = ~val->intval & 0x7fff; |
237 | val->intval++; | 152 | val->intval++; |
238 | val->intval *= -1; | 153 | val->intval *= -1; |
239 | } | 154 | } |
240 | val->intval *= 1562500 / chip->pdata->r_sns; | 155 | val->intval >>= 4; |
156 | val->intval *= 1000000 * 25 / chip->pdata->r_sns; | ||
241 | } else { | 157 | } else { |
242 | return -EINVAL; | 158 | return -EINVAL; |
243 | } | 159 | } |
244 | break; | 160 | break; |
245 | case POWER_SUPPLY_PROP_CURRENT_AVG: | 161 | case POWER_SUPPLY_PROP_CURRENT_AVG: |
246 | if (chip->pdata->enable_current_sense) { | 162 | if (chip->pdata->enable_current_sense) { |
247 | ret = max17042_read_reg(chip->client, | 163 | val->intval = max17042_read_reg(chip->client, |
248 | MAX17042_AvgCurrent); | 164 | MAX17042_AvgCurrent); |
249 | if (ret < 0) | ||
250 | return ret; | ||
251 | |||
252 | val->intval = ret; | ||
253 | if (val->intval & 0x8000) { | 165 | if (val->intval & 0x8000) { |
254 | /* Negative */ | 166 | /* Negative */ |
255 | val->intval = ~val->intval & 0x7fff; | 167 | val->intval = ~val->intval & 0x7fff; |
@@ -267,458 +179,26 @@ static int max17042_get_property(struct power_supply *psy, | |||
267 | return 0; | 179 | return 0; |
268 | } | 180 | } |
269 | 181 | ||
270 | static int max17042_write_verify_reg(struct i2c_client *client, | 182 | static int __devinit max17042_probe(struct i2c_client *client, |
271 | u8 reg, u16 value) | ||
272 | { | ||
273 | int retries = 8; | ||
274 | int ret; | ||
275 | u16 read_value; | ||
276 | |||
277 | do { | ||
278 | ret = i2c_smbus_write_word_data(client, reg, value); | ||
279 | read_value = max17042_read_reg(client, reg); | ||
280 | if (read_value != value) { | ||
281 | ret = -EIO; | ||
282 | retries--; | ||
283 | } | ||
284 | } while (retries && read_value != value); | ||
285 | |||
286 | if (ret < 0) | ||
287 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
288 | |||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | static inline void max17042_override_por( | ||
293 | struct i2c_client *client, u8 reg, u16 value) | ||
294 | { | ||
295 | if (value) | ||
296 | max17042_write_reg(client, reg, value); | ||
297 | } | ||
298 | |||
299 | static inline void max10742_unlock_model(struct max17042_chip *chip) | ||
300 | { | ||
301 | struct i2c_client *client = chip->client; | ||
302 | max17042_write_reg(client, MAX17042_MLOCKReg1, MODEL_UNLOCK1); | ||
303 | max17042_write_reg(client, MAX17042_MLOCKReg2, MODEL_UNLOCK2); | ||
304 | } | ||
305 | |||
306 | static inline void max10742_lock_model(struct max17042_chip *chip) | ||
307 | { | ||
308 | struct i2c_client *client = chip->client; | ||
309 | max17042_write_reg(client, MAX17042_MLOCKReg1, MODEL_LOCK1); | ||
310 | max17042_write_reg(client, MAX17042_MLOCKReg2, MODEL_LOCK2); | ||
311 | } | ||
312 | |||
313 | static inline void max17042_write_model_data(struct max17042_chip *chip, | ||
314 | u8 addr, int size) | ||
315 | { | ||
316 | struct i2c_client *client = chip->client; | ||
317 | int i; | ||
318 | for (i = 0; i < size; i++) | ||
319 | max17042_write_reg(client, addr + i, | ||
320 | chip->pdata->config_data->cell_char_tbl[i]); | ||
321 | } | ||
322 | |||
323 | static inline void max17042_read_model_data(struct max17042_chip *chip, | ||
324 | u8 addr, u16 *data, int size) | ||
325 | { | ||
326 | struct i2c_client *client = chip->client; | ||
327 | int i; | ||
328 | |||
329 | for (i = 0; i < size; i++) | ||
330 | data[i] = max17042_read_reg(client, addr + i); | ||
331 | } | ||
332 | |||
333 | static inline int max17042_model_data_compare(struct max17042_chip *chip, | ||
334 | u16 *data1, u16 *data2, int size) | ||
335 | { | ||
336 | int i; | ||
337 | |||
338 | if (memcmp(data1, data2, size)) { | ||
339 | dev_err(&chip->client->dev, "%s compare failed\n", __func__); | ||
340 | for (i = 0; i < size; i++) | ||
341 | dev_info(&chip->client->dev, "0x%x, 0x%x", | ||
342 | data1[i], data2[i]); | ||
343 | dev_info(&chip->client->dev, "\n"); | ||
344 | return -EINVAL; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int max17042_init_model(struct max17042_chip *chip) | ||
350 | { | ||
351 | int ret; | ||
352 | int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); | ||
353 | u16 *temp_data; | ||
354 | |||
355 | temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); | ||
356 | if (!temp_data) | ||
357 | return -ENOMEM; | ||
358 | |||
359 | max10742_unlock_model(chip); | ||
360 | max17042_write_model_data(chip, MAX17042_MODELChrTbl, | ||
361 | table_size); | ||
362 | max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data, | ||
363 | table_size); | ||
364 | |||
365 | ret = max17042_model_data_compare( | ||
366 | chip, | ||
367 | chip->pdata->config_data->cell_char_tbl, | ||
368 | temp_data, | ||
369 | table_size); | ||
370 | |||
371 | max10742_lock_model(chip); | ||
372 | kfree(temp_data); | ||
373 | |||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | static int max17042_verify_model_lock(struct max17042_chip *chip) | ||
378 | { | ||
379 | int i; | ||
380 | int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); | ||
381 | u16 *temp_data; | ||
382 | int ret = 0; | ||
383 | |||
384 | temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); | ||
385 | if (!temp_data) | ||
386 | return -ENOMEM; | ||
387 | |||
388 | max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data, | ||
389 | table_size); | ||
390 | for (i = 0; i < table_size; i++) | ||
391 | if (temp_data[i]) | ||
392 | ret = -EINVAL; | ||
393 | |||
394 | kfree(temp_data); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | static void max17042_write_config_regs(struct max17042_chip *chip) | ||
399 | { | ||
400 | struct max17042_config_data *config = chip->pdata->config_data; | ||
401 | |||
402 | max17042_write_reg(chip->client, MAX17042_CONFIG, config->config); | ||
403 | max17042_write_reg(chip->client, MAX17042_LearnCFG, config->learn_cfg); | ||
404 | max17042_write_reg(chip->client, MAX17042_FilterCFG, | ||
405 | config->filter_cfg); | ||
406 | max17042_write_reg(chip->client, MAX17042_RelaxCFG, config->relax_cfg); | ||
407 | if (chip->chip_type == MAX17047) | ||
408 | max17042_write_reg(chip->client, MAX17047_FullSOCThr, | ||
409 | config->full_soc_thresh); | ||
410 | } | ||
411 | |||
412 | static void max17042_write_custom_regs(struct max17042_chip *chip) | ||
413 | { | ||
414 | struct max17042_config_data *config = chip->pdata->config_data; | ||
415 | |||
416 | max17042_write_verify_reg(chip->client, MAX17042_RCOMP0, | ||
417 | config->rcomp0); | ||
418 | max17042_write_verify_reg(chip->client, MAX17042_TempCo, | ||
419 | config->tcompc0); | ||
420 | max17042_write_verify_reg(chip->client, MAX17042_ICHGTerm, | ||
421 | config->ichgt_term); | ||
422 | if (chip->chip_type == MAX17042) { | ||
423 | max17042_write_reg(chip->client, MAX17042_EmptyTempCo, | ||
424 | config->empty_tempco); | ||
425 | max17042_write_verify_reg(chip->client, MAX17042_K_empty0, | ||
426 | config->kempty0); | ||
427 | } else { | ||
428 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl00, | ||
429 | config->qrtbl00); | ||
430 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl10, | ||
431 | config->qrtbl10); | ||
432 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl20, | ||
433 | config->qrtbl20); | ||
434 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl30, | ||
435 | config->qrtbl30); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | static void max17042_update_capacity_regs(struct max17042_chip *chip) | ||
440 | { | ||
441 | struct max17042_config_data *config = chip->pdata->config_data; | ||
442 | |||
443 | max17042_write_verify_reg(chip->client, MAX17042_FullCAP, | ||
444 | config->fullcap); | ||
445 | max17042_write_reg(chip->client, MAX17042_DesignCap, | ||
446 | config->design_cap); | ||
447 | max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom, | ||
448 | config->fullcapnom); | ||
449 | } | ||
450 | |||
451 | static void max17042_reset_vfsoc0_reg(struct max17042_chip *chip) | ||
452 | { | ||
453 | u16 vfSoc; | ||
454 | |||
455 | vfSoc = max17042_read_reg(chip->client, MAX17042_VFSOC); | ||
456 | max17042_write_reg(chip->client, MAX17042_VFSOC0Enable, VFSOC0_UNLOCK); | ||
457 | max17042_write_verify_reg(chip->client, MAX17042_VFSOC0, vfSoc); | ||
458 | max17042_write_reg(chip->client, MAX17042_VFSOC0Enable, VFSOC0_LOCK); | ||
459 | } | ||
460 | |||
461 | static void max17042_load_new_capacity_params(struct max17042_chip *chip) | ||
462 | { | ||
463 | u16 full_cap0, rep_cap, dq_acc, vfSoc; | ||
464 | u32 rem_cap; | ||
465 | |||
466 | struct max17042_config_data *config = chip->pdata->config_data; | ||
467 | |||
468 | full_cap0 = max17042_read_reg(chip->client, MAX17042_FullCAP0); | ||
469 | vfSoc = max17042_read_reg(chip->client, MAX17042_VFSOC); | ||
470 | |||
471 | /* fg_vfSoc needs to shifted by 8 bits to get the | ||
472 | * perc in 1% accuracy, to get the right rem_cap multiply | ||
473 | * full_cap0, fg_vfSoc and devide by 100 | ||
474 | */ | ||
475 | rem_cap = ((vfSoc >> 8) * full_cap0) / 100; | ||
476 | max17042_write_verify_reg(chip->client, MAX17042_RemCap, (u16)rem_cap); | ||
477 | |||
478 | rep_cap = (u16)rem_cap; | ||
479 | max17042_write_verify_reg(chip->client, MAX17042_RepCap, rep_cap); | ||
480 | |||
481 | /* Write dQ_acc to 200% of Capacity and dP_acc to 200% */ | ||
482 | dq_acc = config->fullcap / dQ_ACC_DIV; | ||
483 | max17042_write_verify_reg(chip->client, MAX17042_dQacc, dq_acc); | ||
484 | max17042_write_verify_reg(chip->client, MAX17042_dPacc, dP_ACC_200); | ||
485 | |||
486 | max17042_write_verify_reg(chip->client, MAX17042_FullCAP, | ||
487 | config->fullcap); | ||
488 | max17042_write_reg(chip->client, MAX17042_DesignCap, | ||
489 | config->design_cap); | ||
490 | max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom, | ||
491 | config->fullcapnom); | ||
492 | /* Update SOC register with new SOC */ | ||
493 | max17042_write_reg(chip->client, MAX17042_RepSOC, vfSoc); | ||
494 | } | ||
495 | |||
496 | /* | ||
497 | * Block write all the override values coming from platform data. | ||
498 | * This function MUST be called before the POR initialization proceedure | ||
499 | * specified by maxim. | ||
500 | */ | ||
501 | static inline void max17042_override_por_values(struct max17042_chip *chip) | ||
502 | { | ||
503 | struct i2c_client *client = chip->client; | ||
504 | struct max17042_config_data *config = chip->pdata->config_data; | ||
505 | |||
506 | max17042_override_por(client, MAX17042_TGAIN, config->tgain); | ||
507 | max17042_override_por(client, MAx17042_TOFF, config->toff); | ||
508 | max17042_override_por(client, MAX17042_CGAIN, config->cgain); | ||
509 | max17042_override_por(client, MAX17042_COFF, config->coff); | ||
510 | |||
511 | max17042_override_por(client, MAX17042_VALRT_Th, config->valrt_thresh); | ||
512 | max17042_override_por(client, MAX17042_TALRT_Th, config->talrt_thresh); | ||
513 | max17042_override_por(client, MAX17042_SALRT_Th, | ||
514 | config->soc_alrt_thresh); | ||
515 | max17042_override_por(client, MAX17042_CONFIG, config->config); | ||
516 | max17042_override_por(client, MAX17042_SHDNTIMER, config->shdntimer); | ||
517 | |||
518 | max17042_override_por(client, MAX17042_DesignCap, config->design_cap); | ||
519 | max17042_override_por(client, MAX17042_ICHGTerm, config->ichgt_term); | ||
520 | |||
521 | max17042_override_por(client, MAX17042_AtRate, config->at_rate); | ||
522 | max17042_override_por(client, MAX17042_LearnCFG, config->learn_cfg); | ||
523 | max17042_override_por(client, MAX17042_FilterCFG, config->filter_cfg); | ||
524 | max17042_override_por(client, MAX17042_RelaxCFG, config->relax_cfg); | ||
525 | max17042_override_por(client, MAX17042_MiscCFG, config->misc_cfg); | ||
526 | max17042_override_por(client, MAX17042_MaskSOC, config->masksoc); | ||
527 | |||
528 | max17042_override_por(client, MAX17042_FullCAP, config->fullcap); | ||
529 | max17042_override_por(client, MAX17042_FullCAPNom, config->fullcapnom); | ||
530 | if (chip->chip_type == MAX17042) | ||
531 | max17042_override_por(client, MAX17042_SOC_empty, | ||
532 | config->socempty); | ||
533 | max17042_override_por(client, MAX17042_LAvg_empty, config->lavg_empty); | ||
534 | max17042_override_por(client, MAX17042_dQacc, config->dqacc); | ||
535 | max17042_override_por(client, MAX17042_dPacc, config->dpacc); | ||
536 | |||
537 | if (chip->chip_type == MAX17042) | ||
538 | max17042_override_por(client, MAX17042_V_empty, config->vempty); | ||
539 | else | ||
540 | max17042_override_por(client, MAX17047_V_empty, config->vempty); | ||
541 | max17042_override_por(client, MAX17042_TempNom, config->temp_nom); | ||
542 | max17042_override_por(client, MAX17042_TempLim, config->temp_lim); | ||
543 | max17042_override_por(client, MAX17042_FCTC, config->fctc); | ||
544 | max17042_override_por(client, MAX17042_RCOMP0, config->rcomp0); | ||
545 | max17042_override_por(client, MAX17042_TempCo, config->tcompc0); | ||
546 | if (chip->chip_type) { | ||
547 | max17042_override_por(client, MAX17042_EmptyTempCo, | ||
548 | config->empty_tempco); | ||
549 | max17042_override_por(client, MAX17042_K_empty0, | ||
550 | config->kempty0); | ||
551 | } | ||
552 | } | ||
553 | |||
554 | static int max17042_init_chip(struct max17042_chip *chip) | ||
555 | { | ||
556 | int ret; | ||
557 | int val; | ||
558 | |||
559 | max17042_override_por_values(chip); | ||
560 | /* After Power up, the MAX17042 requires 500mS in order | ||
561 | * to perform signal debouncing and initial SOC reporting | ||
562 | */ | ||
563 | msleep(500); | ||
564 | |||
565 | /* Initialize configaration */ | ||
566 | max17042_write_config_regs(chip); | ||
567 | |||
568 | /* write cell characterization data */ | ||
569 | ret = max17042_init_model(chip); | ||
570 | if (ret) { | ||
571 | dev_err(&chip->client->dev, "%s init failed\n", | ||
572 | __func__); | ||
573 | return -EIO; | ||
574 | } | ||
575 | |||
576 | ret = max17042_verify_model_lock(chip); | ||
577 | if (ret) { | ||
578 | dev_err(&chip->client->dev, "%s lock verify failed\n", | ||
579 | __func__); | ||
580 | return -EIO; | ||
581 | } | ||
582 | /* write custom parameters */ | ||
583 | max17042_write_custom_regs(chip); | ||
584 | |||
585 | /* update capacity params */ | ||
586 | max17042_update_capacity_regs(chip); | ||
587 | |||
588 | /* delay must be atleast 350mS to allow VFSOC | ||
589 | * to be calculated from the new configuration | ||
590 | */ | ||
591 | msleep(350); | ||
592 | |||
593 | /* reset vfsoc0 reg */ | ||
594 | max17042_reset_vfsoc0_reg(chip); | ||
595 | |||
596 | /* load new capacity params */ | ||
597 | max17042_load_new_capacity_params(chip); | ||
598 | |||
599 | /* Init complete, Clear the POR bit */ | ||
600 | val = max17042_read_reg(chip->client, MAX17042_STATUS); | ||
601 | max17042_write_reg(chip->client, MAX17042_STATUS, | ||
602 | val & (~STATUS_POR_BIT)); | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) | ||
607 | { | ||
608 | u16 soc, soc_tr; | ||
609 | |||
610 | /* program interrupt thesholds such that we should | ||
611 | * get interrupt for every 'off' perc change in the soc | ||
612 | */ | ||
613 | soc = max17042_read_reg(chip->client, MAX17042_RepSOC) >> 8; | ||
614 | soc_tr = (soc + off) << 8; | ||
615 | soc_tr |= (soc - off); | ||
616 | max17042_write_reg(chip->client, MAX17042_SALRT_Th, soc_tr); | ||
617 | } | ||
618 | |||
619 | static irqreturn_t max17042_thread_handler(int id, void *dev) | ||
620 | { | ||
621 | struct max17042_chip *chip = dev; | ||
622 | u16 val; | ||
623 | |||
624 | val = max17042_read_reg(chip->client, MAX17042_STATUS); | ||
625 | if ((val & STATUS_INTR_SOCMIN_BIT) || | ||
626 | (val & STATUS_INTR_SOCMAX_BIT)) { | ||
627 | dev_info(&chip->client->dev, "SOC threshold INTR\n"); | ||
628 | max17042_set_soc_threshold(chip, 1); | ||
629 | } | ||
630 | |||
631 | power_supply_changed(&chip->battery); | ||
632 | return IRQ_HANDLED; | ||
633 | } | ||
634 | |||
635 | static void max17042_init_worker(struct work_struct *work) | ||
636 | { | ||
637 | struct max17042_chip *chip = container_of(work, | ||
638 | struct max17042_chip, work); | ||
639 | int ret; | ||
640 | |||
641 | /* Initialize registers according to values from the platform data */ | ||
642 | if (chip->pdata->enable_por_init && chip->pdata->config_data) { | ||
643 | ret = max17042_init_chip(chip); | ||
644 | if (ret) | ||
645 | return; | ||
646 | } | ||
647 | |||
648 | chip->init_complete = 1; | ||
649 | } | ||
650 | |||
651 | #ifdef CONFIG_OF | ||
652 | static struct max17042_platform_data * | ||
653 | max17042_get_pdata(struct device *dev) | ||
654 | { | ||
655 | struct device_node *np = dev->of_node; | ||
656 | u32 prop; | ||
657 | struct max17042_platform_data *pdata; | ||
658 | |||
659 | if (!np) | ||
660 | return dev->platform_data; | ||
661 | |||
662 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
663 | if (!pdata) | ||
664 | return NULL; | ||
665 | |||
666 | /* | ||
667 | * Require current sense resistor value to be specified for | ||
668 | * current-sense functionality to be enabled at all. | ||
669 | */ | ||
670 | if (of_property_read_u32(np, "maxim,rsns-microohm", &prop) == 0) { | ||
671 | pdata->r_sns = prop; | ||
672 | pdata->enable_current_sense = true; | ||
673 | } | ||
674 | |||
675 | return pdata; | ||
676 | } | ||
677 | #else | ||
678 | static struct max17042_platform_data * | ||
679 | max17042_get_pdata(struct device *dev) | ||
680 | { | ||
681 | return dev->platform_data; | ||
682 | } | ||
683 | #endif | ||
684 | |||
685 | static int max17042_probe(struct i2c_client *client, | ||
686 | const struct i2c_device_id *id) | 183 | const struct i2c_device_id *id) |
687 | { | 184 | { |
688 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 185 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
689 | struct max17042_chip *chip; | 186 | struct max17042_chip *chip; |
690 | int ret; | 187 | int ret; |
691 | int reg; | ||
692 | 188 | ||
693 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) | 189 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) |
694 | return -EIO; | 190 | return -EIO; |
695 | 191 | ||
696 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); | 192 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
697 | if (!chip) | 193 | if (!chip) |
698 | return -ENOMEM; | 194 | return -ENOMEM; |
699 | 195 | ||
700 | chip->client = client; | 196 | chip->client = client; |
701 | chip->pdata = max17042_get_pdata(&client->dev); | 197 | chip->pdata = client->dev.platform_data; |
702 | if (!chip->pdata) { | ||
703 | dev_err(&client->dev, "no platform data provided\n"); | ||
704 | return -EINVAL; | ||
705 | } | ||
706 | 198 | ||
707 | i2c_set_clientdata(client, chip); | 199 | i2c_set_clientdata(client, chip); |
708 | 200 | ||
709 | ret = max17042_read_reg(chip->client, MAX17042_DevName); | 201 | chip->battery.name = "max17042_battery"; |
710 | if (ret == MAX17042_IC_VERSION) { | ||
711 | dev_dbg(&client->dev, "chip type max17042 detected\n"); | ||
712 | chip->chip_type = MAX17042; | ||
713 | } else if (ret == MAX17047_IC_VERSION) { | ||
714 | dev_dbg(&client->dev, "chip type max17047/50 detected\n"); | ||
715 | chip->chip_type = MAX17047; | ||
716 | } else { | ||
717 | dev_err(&client->dev, "device version mismatch: %x\n", ret); | ||
718 | return -EIO; | ||
719 | } | ||
720 | |||
721 | chip->battery.name = "max170xx_battery"; | ||
722 | chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; | 202 | chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; |
723 | chip->battery.get_property = max17042_get_property; | 203 | chip->battery.get_property = max17042_get_property; |
724 | chip->battery.properties = max17042_battery_props; | 204 | chip->battery.properties = max17042_battery_props; |
@@ -729,118 +209,41 @@ static int max17042_probe(struct i2c_client *client, | |||
729 | if (!chip->pdata->enable_current_sense) | 209 | if (!chip->pdata->enable_current_sense) |
730 | chip->battery.num_properties -= 2; | 210 | chip->battery.num_properties -= 2; |
731 | 211 | ||
732 | if (chip->pdata->r_sns == 0) | 212 | ret = power_supply_register(&client->dev, &chip->battery); |
733 | chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR; | 213 | if (ret) { |
214 | dev_err(&client->dev, "failed: power supply register\n"); | ||
215 | kfree(chip); | ||
216 | return ret; | ||
217 | } | ||
734 | 218 | ||
219 | /* Initialize registers according to values from the platform data */ | ||
735 | if (chip->pdata->init_data) | 220 | if (chip->pdata->init_data) |
736 | max17042_set_reg(client, chip->pdata->init_data, | 221 | max17042_set_reg(client, chip->pdata->init_data, |
737 | chip->pdata->num_init_data); | 222 | chip->pdata->num_init_data); |
738 | 223 | ||
739 | if (!chip->pdata->enable_current_sense) { | 224 | if (!chip->pdata->enable_current_sense) { |
740 | max17042_write_reg(client, MAX17042_CGAIN, 0x0000); | 225 | max17042_write_reg(client, MAX17042_CGAIN, 0x0000); |
741 | max17042_write_reg(client, MAX17042_MiscCFG, 0x0003); | 226 | max17042_write_reg(client, MAX17042_MiscCFG, 0x0003); |
742 | max17042_write_reg(client, MAX17042_LearnCFG, 0x0007); | 227 | max17042_write_reg(client, MAX17042_LearnCFG, 0x0007); |
743 | } | ||
744 | |||
745 | ret = power_supply_register(&client->dev, &chip->battery); | ||
746 | if (ret) { | ||
747 | dev_err(&client->dev, "failed: power supply register\n"); | ||
748 | return ret; | ||
749 | } | ||
750 | |||
751 | if (client->irq) { | ||
752 | ret = request_threaded_irq(client->irq, NULL, | ||
753 | max17042_thread_handler, | ||
754 | IRQF_TRIGGER_FALLING, | ||
755 | chip->battery.name, chip); | ||
756 | if (!ret) { | ||
757 | reg = max17042_read_reg(client, MAX17042_CONFIG); | ||
758 | reg |= CONFIG_ALRT_BIT_ENBL; | ||
759 | max17042_write_reg(client, MAX17042_CONFIG, reg); | ||
760 | max17042_set_soc_threshold(chip, 1); | ||
761 | } else { | ||
762 | client->irq = 0; | ||
763 | dev_err(&client->dev, "%s(): cannot get IRQ\n", | ||
764 | __func__); | ||
765 | } | ||
766 | } | ||
767 | |||
768 | reg = max17042_read_reg(chip->client, MAX17042_STATUS); | ||
769 | if (reg & STATUS_POR_BIT) { | ||
770 | INIT_WORK(&chip->work, max17042_init_worker); | ||
771 | schedule_work(&chip->work); | ||
772 | } else { | 228 | } else { |
773 | chip->init_complete = 1; | 229 | if (chip->pdata->r_sns == 0) |
230 | chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR; | ||
774 | } | 231 | } |
775 | 232 | ||
776 | return 0; | 233 | return 0; |
777 | } | 234 | } |
778 | 235 | ||
779 | static int max17042_remove(struct i2c_client *client) | 236 | static int __devexit max17042_remove(struct i2c_client *client) |
780 | { | 237 | { |
781 | struct max17042_chip *chip = i2c_get_clientdata(client); | 238 | struct max17042_chip *chip = i2c_get_clientdata(client); |
782 | 239 | ||
783 | if (client->irq) | ||
784 | free_irq(client->irq, chip); | ||
785 | power_supply_unregister(&chip->battery); | 240 | power_supply_unregister(&chip->battery); |
241 | kfree(chip); | ||
786 | return 0; | 242 | return 0; |
787 | } | 243 | } |
788 | 244 | ||
789 | #ifdef CONFIG_PM | ||
790 | static int max17042_suspend(struct device *dev) | ||
791 | { | ||
792 | struct max17042_chip *chip = dev_get_drvdata(dev); | ||
793 | |||
794 | /* | ||
795 | * disable the irq and enable irq_wake | ||
796 | * capability to the interrupt line. | ||
797 | */ | ||
798 | if (chip->client->irq) { | ||
799 | disable_irq(chip->client->irq); | ||
800 | enable_irq_wake(chip->client->irq); | ||
801 | } | ||
802 | |||
803 | return 0; | ||
804 | } | ||
805 | |||
806 | static int max17042_resume(struct device *dev) | ||
807 | { | ||
808 | struct max17042_chip *chip = dev_get_drvdata(dev); | ||
809 | |||
810 | if (chip->client->irq) { | ||
811 | disable_irq_wake(chip->client->irq); | ||
812 | enable_irq(chip->client->irq); | ||
813 | /* re-program the SOC thresholds to 1% change */ | ||
814 | max17042_set_soc_threshold(chip, 1); | ||
815 | } | ||
816 | |||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | static const struct dev_pm_ops max17042_pm_ops = { | ||
821 | .suspend = max17042_suspend, | ||
822 | .resume = max17042_resume, | ||
823 | }; | ||
824 | |||
825 | #define MAX17042_PM_OPS (&max17042_pm_ops) | ||
826 | #else | ||
827 | #define MAX17042_PM_OPS NULL | ||
828 | #endif | ||
829 | |||
830 | #ifdef CONFIG_OF | ||
831 | static const struct of_device_id max17042_dt_match[] = { | ||
832 | { .compatible = "maxim,max17042" }, | ||
833 | { .compatible = "maxim,max17047" }, | ||
834 | { .compatible = "maxim,max17050" }, | ||
835 | { }, | ||
836 | }; | ||
837 | MODULE_DEVICE_TABLE(of, max17042_dt_match); | ||
838 | #endif | ||
839 | |||
840 | static const struct i2c_device_id max17042_id[] = { | 245 | static const struct i2c_device_id max17042_id[] = { |
841 | { "max17042", 0 }, | 246 | { "max17042", 0 }, |
842 | { "max17047", 1 }, | ||
843 | { "max17050", 2 }, | ||
844 | { } | 247 | { } |
845 | }; | 248 | }; |
846 | MODULE_DEVICE_TABLE(i2c, max17042_id); | 249 | MODULE_DEVICE_TABLE(i2c, max17042_id); |
@@ -848,14 +251,23 @@ MODULE_DEVICE_TABLE(i2c, max17042_id); | |||
848 | static struct i2c_driver max17042_i2c_driver = { | 251 | static struct i2c_driver max17042_i2c_driver = { |
849 | .driver = { | 252 | .driver = { |
850 | .name = "max17042", | 253 | .name = "max17042", |
851 | .of_match_table = of_match_ptr(max17042_dt_match), | ||
852 | .pm = MAX17042_PM_OPS, | ||
853 | }, | 254 | }, |
854 | .probe = max17042_probe, | 255 | .probe = max17042_probe, |
855 | .remove = max17042_remove, | 256 | .remove = __devexit_p(max17042_remove), |
856 | .id_table = max17042_id, | 257 | .id_table = max17042_id, |
857 | }; | 258 | }; |
858 | module_i2c_driver(max17042_i2c_driver); | 259 | |
260 | static int __init max17042_init(void) | ||
261 | { | ||
262 | return i2c_add_driver(&max17042_i2c_driver); | ||
263 | } | ||
264 | module_init(max17042_init); | ||
265 | |||
266 | static void __exit max17042_exit(void) | ||
267 | { | ||
268 | i2c_del_driver(&max17042_i2c_driver); | ||
269 | } | ||
270 | module_exit(max17042_exit); | ||
859 | 271 | ||
860 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | 272 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); |
861 | MODULE_DESCRIPTION("MAX17042 Fuel Gauge"); | 273 | MODULE_DESCRIPTION("MAX17042 Fuel Gauge"); |
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c index 14e2b96d93b..a9b0209a2f5 100644 --- a/drivers/power/max8903_charger.c +++ b/drivers/power/max8903_charger.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
27 | #include <linux/power_supply.h> | 26 | #include <linux/power_supply.h> |
28 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
@@ -179,7 +178,7 @@ static irqreturn_t max8903_fault(int irq, void *_data) | |||
179 | return IRQ_HANDLED; | 178 | return IRQ_HANDLED; |
180 | } | 179 | } |
181 | 180 | ||
182 | static int max8903_probe(struct platform_device *pdev) | 181 | static __devinit int max8903_probe(struct platform_device *pdev) |
183 | { | 182 | { |
184 | struct max8903_data *data; | 183 | struct max8903_data *data; |
185 | struct device *dev = &pdev->dev; | 184 | struct device *dev = &pdev->dev; |
@@ -345,7 +344,7 @@ err: | |||
345 | return ret; | 344 | return ret; |
346 | } | 345 | } |
347 | 346 | ||
348 | static int max8903_remove(struct platform_device *pdev) | 347 | static __devexit int max8903_remove(struct platform_device *pdev) |
349 | { | 348 | { |
350 | struct max8903_data *data = platform_get_drvdata(pdev); | 349 | struct max8903_data *data = platform_get_drvdata(pdev); |
351 | 350 | ||
@@ -367,16 +366,26 @@ static int max8903_remove(struct platform_device *pdev) | |||
367 | 366 | ||
368 | static struct platform_driver max8903_driver = { | 367 | static struct platform_driver max8903_driver = { |
369 | .probe = max8903_probe, | 368 | .probe = max8903_probe, |
370 | .remove = max8903_remove, | 369 | .remove = __devexit_p(max8903_remove), |
371 | .driver = { | 370 | .driver = { |
372 | .name = "max8903-charger", | 371 | .name = "max8903-charger", |
373 | .owner = THIS_MODULE, | 372 | .owner = THIS_MODULE, |
374 | }, | 373 | }, |
375 | }; | 374 | }; |
376 | 375 | ||
377 | module_platform_driver(max8903_driver); | 376 | static int __init max8903_init(void) |
377 | { | ||
378 | return platform_driver_register(&max8903_driver); | ||
379 | } | ||
380 | module_init(max8903_init); | ||
381 | |||
382 | static void __exit max8903_exit(void) | ||
383 | { | ||
384 | platform_driver_unregister(&max8903_driver); | ||
385 | } | ||
386 | module_exit(max8903_exit); | ||
378 | 387 | ||
379 | MODULE_LICENSE("GPL"); | 388 | MODULE_LICENSE("GPL"); |
380 | MODULE_DESCRIPTION("MAX8903 Charger Driver"); | 389 | MODULE_DESCRIPTION("MAX8903 Charger Driver"); |
381 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | 390 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); |
382 | MODULE_ALIAS("platform:max8903-charger"); | 391 | MODULE_ALIAS("max8903-charger"); |
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c index 665cdc76c26..a70e16d3a3d 100644 --- a/drivers/power/max8925_power.c +++ b/drivers/power/max8925_power.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/of.h> | ||
16 | #include <linux/i2c.h> | 15 | #include <linux/i2c.h> |
17 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
18 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
@@ -79,8 +78,6 @@ struct max8925_power_info { | |||
79 | unsigned batt_detect:1; /* detecing MB by ID pin */ | 78 | unsigned batt_detect:1; /* detecing MB by ID pin */ |
80 | unsigned topoff_threshold:2; | 79 | unsigned topoff_threshold:2; |
81 | unsigned fast_charge:3; | 80 | unsigned fast_charge:3; |
82 | unsigned no_temp_support:1; | ||
83 | unsigned no_insert_detect:1; | ||
84 | 81 | ||
85 | int (*set_charger) (int); | 82 | int (*set_charger) (int); |
86 | }; | 83 | }; |
@@ -119,7 +116,17 @@ static irqreturn_t max8925_charger_handler(int irq, void *data) | |||
119 | case MAX8925_IRQ_VCHG_DC_F: | 116 | case MAX8925_IRQ_VCHG_DC_F: |
120 | info->ac_online = 0; | 117 | info->ac_online = 0; |
121 | __set_charger(info, 0); | 118 | __set_charger(info, 0); |
122 | dev_dbg(chip->dev, "Adapter removed\n"); | 119 | dev_dbg(chip->dev, "Adapter is removal\n"); |
120 | break; | ||
121 | case MAX8925_IRQ_VCHG_USB_R: | ||
122 | info->usb_online = 1; | ||
123 | __set_charger(info, 1); | ||
124 | dev_dbg(chip->dev, "USB inserted\n"); | ||
125 | break; | ||
126 | case MAX8925_IRQ_VCHG_USB_F: | ||
127 | info->usb_online = 0; | ||
128 | __set_charger(info, 0); | ||
129 | dev_dbg(chip->dev, "USB is removal\n"); | ||
123 | break; | 130 | break; |
124 | case MAX8925_IRQ_VCHG_THM_OK_F: | 131 | case MAX8925_IRQ_VCHG_THM_OK_F: |
125 | /* Battery is not ready yet */ | 132 | /* Battery is not ready yet */ |
@@ -161,33 +168,27 @@ static irqreturn_t max8925_charger_handler(int irq, void *data) | |||
161 | static int start_measure(struct max8925_power_info *info, int type) | 168 | static int start_measure(struct max8925_power_info *info, int type) |
162 | { | 169 | { |
163 | unsigned char buf[2] = {0, 0}; | 170 | unsigned char buf[2] = {0, 0}; |
164 | int meas_cmd; | ||
165 | int meas_reg = 0, ret; | 171 | int meas_reg = 0, ret; |
166 | 172 | ||
167 | switch (type) { | 173 | switch (type) { |
168 | case MEASURE_VCHG: | 174 | case MEASURE_VCHG: |
169 | meas_cmd = MAX8925_CMD_VCHG; | ||
170 | meas_reg = MAX8925_ADC_VCHG; | 175 | meas_reg = MAX8925_ADC_VCHG; |
171 | break; | 176 | break; |
172 | case MEASURE_VBBATT: | 177 | case MEASURE_VBBATT: |
173 | meas_cmd = MAX8925_CMD_VBBATT; | ||
174 | meas_reg = MAX8925_ADC_VBBATT; | 178 | meas_reg = MAX8925_ADC_VBBATT; |
175 | break; | 179 | break; |
176 | case MEASURE_VMBATT: | 180 | case MEASURE_VMBATT: |
177 | meas_cmd = MAX8925_CMD_VMBATT; | ||
178 | meas_reg = MAX8925_ADC_VMBATT; | 181 | meas_reg = MAX8925_ADC_VMBATT; |
179 | break; | 182 | break; |
180 | case MEASURE_ISNS: | 183 | case MEASURE_ISNS: |
181 | meas_cmd = MAX8925_CMD_ISNS; | ||
182 | meas_reg = MAX8925_ADC_ISNS; | 184 | meas_reg = MAX8925_ADC_ISNS; |
183 | break; | 185 | break; |
184 | default: | 186 | default: |
185 | return -EINVAL; | 187 | return -EINVAL; |
186 | } | 188 | } |
187 | 189 | ||
188 | max8925_reg_write(info->adc, meas_cmd, 0); | ||
189 | max8925_bulk_read(info->adc, meas_reg, 2, buf); | 190 | max8925_bulk_read(info->adc, meas_reg, 2, buf); |
190 | ret = ((buf[0]<<8) | buf[1]) >> 4; | 191 | ret = (buf[0] << 4) | (buf[1] >> 4); |
191 | 192 | ||
192 | return ret; | 193 | return ret; |
193 | } | 194 | } |
@@ -207,7 +208,7 @@ static int max8925_ac_get_prop(struct power_supply *psy, | |||
207 | if (info->ac_online) { | 208 | if (info->ac_online) { |
208 | ret = start_measure(info, MEASURE_VCHG); | 209 | ret = start_measure(info, MEASURE_VCHG); |
209 | if (ret >= 0) { | 210 | if (ret >= 0) { |
210 | val->intval = ret * 2000; /* unit is uV */ | 211 | val->intval = ret << 1; /* unit is mV */ |
211 | goto out; | 212 | goto out; |
212 | } | 213 | } |
213 | } | 214 | } |
@@ -241,7 +242,7 @@ static int max8925_usb_get_prop(struct power_supply *psy, | |||
241 | if (info->usb_online) { | 242 | if (info->usb_online) { |
242 | ret = start_measure(info, MEASURE_VCHG); | 243 | ret = start_measure(info, MEASURE_VCHG); |
243 | if (ret >= 0) { | 244 | if (ret >= 0) { |
244 | val->intval = ret * 2000; /* unit is uV */ | 245 | val->intval = ret << 1; /* unit is mV */ |
245 | goto out; | 246 | goto out; |
246 | } | 247 | } |
247 | } | 248 | } |
@@ -265,6 +266,7 @@ static int max8925_bat_get_prop(struct power_supply *psy, | |||
265 | union power_supply_propval *val) | 266 | union power_supply_propval *val) |
266 | { | 267 | { |
267 | struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent); | 268 | struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent); |
269 | long long int tmp = 0; | ||
268 | int ret = 0; | 270 | int ret = 0; |
269 | 271 | ||
270 | switch (psp) { | 272 | switch (psp) { |
@@ -275,7 +277,7 @@ static int max8925_bat_get_prop(struct power_supply *psy, | |||
275 | if (info->bat_online) { | 277 | if (info->bat_online) { |
276 | ret = start_measure(info, MEASURE_VMBATT); | 278 | ret = start_measure(info, MEASURE_VMBATT); |
277 | if (ret >= 0) { | 279 | if (ret >= 0) { |
278 | val->intval = ret * 2000; /* unit is uV */ | 280 | val->intval = ret << 1; /* unit is mV */ |
279 | ret = 0; | 281 | ret = 0; |
280 | break; | 282 | break; |
281 | } | 283 | } |
@@ -286,8 +288,8 @@ static int max8925_bat_get_prop(struct power_supply *psy, | |||
286 | if (info->bat_online) { | 288 | if (info->bat_online) { |
287 | ret = start_measure(info, MEASURE_ISNS); | 289 | ret = start_measure(info, MEASURE_ISNS); |
288 | if (ret >= 0) { | 290 | if (ret >= 0) { |
289 | /* assume r_sns is 0.02 */ | 291 | tmp = (long long int)ret * 6250 / 4096 - 3125; |
290 | ret = ((ret * 6250) - 3125) /* uA */; | 292 | ret = (int)tmp; |
291 | val->intval = 0; | 293 | val->intval = 0; |
292 | if (ret > 0) | 294 | if (ret > 0) |
293 | val->intval = ret; /* unit is mA */ | 295 | val->intval = ret; /* unit is mA */ |
@@ -357,20 +359,19 @@ do { \ | |||
357 | _irq, ret); \ | 359 | _irq, ret); \ |
358 | } while (0) | 360 | } while (0) |
359 | 361 | ||
360 | static int max8925_init_charger(struct max8925_chip *chip, | 362 | static __devinit int max8925_init_charger(struct max8925_chip *chip, |
361 | struct max8925_power_info *info) | 363 | struct max8925_power_info *info) |
362 | { | 364 | { |
363 | int ret; | 365 | int ret; |
364 | 366 | ||
365 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp"); | 367 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp"); |
366 | if (!info->no_insert_detect) { | 368 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove"); |
367 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove"); | 369 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert"); |
368 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert"); | 370 | REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_OVP, "usb-ovp"); |
369 | } | 371 | REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_F, "usb-remove"); |
370 | if (!info->no_temp_support) { | 372 | REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_R, "usb-insert"); |
371 | REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range"); | 373 | REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range"); |
372 | REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range"); | 374 | REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range"); |
373 | } | ||
374 | REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high"); | 375 | REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high"); |
375 | REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low"); | 376 | REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low"); |
376 | REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset"); | 377 | REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset"); |
@@ -378,15 +379,9 @@ static int max8925_init_charger(struct max8925_chip *chip, | |||
378 | REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff"); | 379 | REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff"); |
379 | REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire"); | 380 | REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire"); |
380 | 381 | ||
382 | info->ac_online = 0; | ||
381 | info->usb_online = 0; | 383 | info->usb_online = 0; |
382 | info->bat_online = 0; | 384 | info->bat_online = 0; |
383 | |||
384 | /* check for power - can miss interrupt at boot time */ | ||
385 | if (start_measure(info, MEASURE_VCHG) * 2000 > 500000) | ||
386 | info->ac_online = 1; | ||
387 | else | ||
388 | info->ac_online = 0; | ||
389 | |||
390 | ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); | 385 | ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); |
391 | if (ret >= 0) { | 386 | if (ret >= 0) { |
392 | /* | 387 | /* |
@@ -415,7 +410,7 @@ static int max8925_init_charger(struct max8925_chip *chip, | |||
415 | return 0; | 410 | return 0; |
416 | } | 411 | } |
417 | 412 | ||
418 | static int max8925_deinit_charger(struct max8925_power_info *info) | 413 | static __devexit int max8925_deinit_charger(struct max8925_power_info *info) |
419 | { | 414 | { |
420 | struct max8925_chip *chip = info->chip; | 415 | struct max8925_chip *chip = info->chip; |
421 | int irq; | 416 | int irq; |
@@ -427,62 +422,14 @@ static int max8925_deinit_charger(struct max8925_power_info *info) | |||
427 | return 0; | 422 | return 0; |
428 | } | 423 | } |
429 | 424 | ||
430 | #ifdef CONFIG_OF | 425 | static __devinit int max8925_power_probe(struct platform_device *pdev) |
431 | static struct max8925_power_pdata * | ||
432 | max8925_power_dt_init(struct platform_device *pdev) | ||
433 | { | ||
434 | struct device_node *nproot = pdev->dev.parent->of_node; | ||
435 | struct device_node *np; | ||
436 | int batt_detect; | ||
437 | int topoff_threshold; | ||
438 | int fast_charge; | ||
439 | int no_temp_support; | ||
440 | int no_insert_detect; | ||
441 | struct max8925_power_pdata *pdata; | ||
442 | |||
443 | if (!nproot) | ||
444 | return pdev->dev.platform_data; | ||
445 | |||
446 | np = of_find_node_by_name(nproot, "charger"); | ||
447 | if (!np) { | ||
448 | dev_err(&pdev->dev, "failed to find charger node\n"); | ||
449 | return NULL; | ||
450 | } | ||
451 | |||
452 | pdata = devm_kzalloc(&pdev->dev, | ||
453 | sizeof(struct max8925_power_pdata), | ||
454 | GFP_KERNEL); | ||
455 | |||
456 | of_property_read_u32(np, "topoff-threshold", &topoff_threshold); | ||
457 | of_property_read_u32(np, "batt-detect", &batt_detect); | ||
458 | of_property_read_u32(np, "fast-charge", &fast_charge); | ||
459 | of_property_read_u32(np, "no-insert-detect", &no_insert_detect); | ||
460 | of_property_read_u32(np, "no-temp-support", &no_temp_support); | ||
461 | |||
462 | pdata->batt_detect = batt_detect; | ||
463 | pdata->fast_charge = fast_charge; | ||
464 | pdata->topoff_threshold = topoff_threshold; | ||
465 | pdata->no_insert_detect = no_insert_detect; | ||
466 | pdata->no_temp_support = no_temp_support; | ||
467 | |||
468 | return pdata; | ||
469 | } | ||
470 | #else | ||
471 | static struct max8925_power_pdata * | ||
472 | max8925_power_dt_init(struct platform_device *pdev) | ||
473 | { | ||
474 | return pdev->dev.platform_data; | ||
475 | } | ||
476 | #endif | ||
477 | |||
478 | static int max8925_power_probe(struct platform_device *pdev) | ||
479 | { | 426 | { |
480 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | 427 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); |
481 | struct max8925_power_pdata *pdata = NULL; | 428 | struct max8925_power_pdata *pdata = NULL; |
482 | struct max8925_power_info *info; | 429 | struct max8925_power_info *info; |
483 | int ret; | 430 | int ret; |
484 | 431 | ||
485 | pdata = max8925_power_dt_init(pdev); | 432 | pdata = pdev->dev.platform_data; |
486 | if (!pdata) { | 433 | if (!pdata) { |
487 | dev_err(&pdev->dev, "platform data isn't assigned to " | 434 | dev_err(&pdev->dev, "platform data isn't assigned to " |
488 | "power supply\n"); | 435 | "power supply\n"); |
@@ -502,8 +449,6 @@ static int max8925_power_probe(struct platform_device *pdev) | |||
502 | info->ac.properties = max8925_ac_props; | 449 | info->ac.properties = max8925_ac_props; |
503 | info->ac.num_properties = ARRAY_SIZE(max8925_ac_props); | 450 | info->ac.num_properties = ARRAY_SIZE(max8925_ac_props); |
504 | info->ac.get_property = max8925_ac_get_prop; | 451 | info->ac.get_property = max8925_ac_get_prop; |
505 | info->ac.supplied_to = pdata->supplied_to; | ||
506 | info->ac.num_supplicants = pdata->num_supplicants; | ||
507 | ret = power_supply_register(&pdev->dev, &info->ac); | 452 | ret = power_supply_register(&pdev->dev, &info->ac); |
508 | if (ret) | 453 | if (ret) |
509 | goto out; | 454 | goto out; |
@@ -514,9 +459,6 @@ static int max8925_power_probe(struct platform_device *pdev) | |||
514 | info->usb.properties = max8925_usb_props; | 459 | info->usb.properties = max8925_usb_props; |
515 | info->usb.num_properties = ARRAY_SIZE(max8925_usb_props); | 460 | info->usb.num_properties = ARRAY_SIZE(max8925_usb_props); |
516 | info->usb.get_property = max8925_usb_get_prop; | 461 | info->usb.get_property = max8925_usb_get_prop; |
517 | info->usb.supplied_to = pdata->supplied_to; | ||
518 | info->usb.num_supplicants = pdata->num_supplicants; | ||
519 | |||
520 | ret = power_supply_register(&pdev->dev, &info->usb); | 462 | ret = power_supply_register(&pdev->dev, &info->usb); |
521 | if (ret) | 463 | if (ret) |
522 | goto out_usb; | 464 | goto out_usb; |
@@ -536,8 +478,6 @@ static int max8925_power_probe(struct platform_device *pdev) | |||
536 | info->topoff_threshold = pdata->topoff_threshold; | 478 | info->topoff_threshold = pdata->topoff_threshold; |
537 | info->fast_charge = pdata->fast_charge; | 479 | info->fast_charge = pdata->fast_charge; |
538 | info->set_charger = pdata->set_charger; | 480 | info->set_charger = pdata->set_charger; |
539 | info->no_temp_support = pdata->no_temp_support; | ||
540 | info->no_insert_detect = pdata->no_insert_detect; | ||
541 | 481 | ||
542 | max8925_init_charger(chip, info); | 482 | max8925_init_charger(chip, info); |
543 | return 0; | 483 | return 0; |
@@ -550,7 +490,7 @@ out: | |||
550 | return ret; | 490 | return ret; |
551 | } | 491 | } |
552 | 492 | ||
553 | static int max8925_power_remove(struct platform_device *pdev) | 493 | static __devexit int max8925_power_remove(struct platform_device *pdev) |
554 | { | 494 | { |
555 | struct max8925_power_info *info = platform_get_drvdata(pdev); | 495 | struct max8925_power_info *info = platform_get_drvdata(pdev); |
556 | 496 | ||
@@ -566,13 +506,23 @@ static int max8925_power_remove(struct platform_device *pdev) | |||
566 | 506 | ||
567 | static struct platform_driver max8925_power_driver = { | 507 | static struct platform_driver max8925_power_driver = { |
568 | .probe = max8925_power_probe, | 508 | .probe = max8925_power_probe, |
569 | .remove = max8925_power_remove, | 509 | .remove = __devexit_p(max8925_power_remove), |
570 | .driver = { | 510 | .driver = { |
571 | .name = "max8925-power", | 511 | .name = "max8925-power", |
572 | }, | 512 | }, |
573 | }; | 513 | }; |
574 | 514 | ||
575 | module_platform_driver(max8925_power_driver); | 515 | static int __init max8925_power_init(void) |
516 | { | ||
517 | return platform_driver_register(&max8925_power_driver); | ||
518 | } | ||
519 | module_init(max8925_power_init); | ||
520 | |||
521 | static void __exit max8925_power_exit(void) | ||
522 | { | ||
523 | platform_driver_unregister(&max8925_power_driver); | ||
524 | } | ||
525 | module_exit(max8925_power_exit); | ||
576 | 526 | ||
577 | MODULE_LICENSE("GPL"); | 527 | MODULE_LICENSE("GPL"); |
578 | MODULE_DESCRIPTION("Power supply driver for MAX8925"); | 528 | MODULE_DESCRIPTION("Power supply driver for MAX8925"); |
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c index e757885b620..ffc5033ea9c 100644 --- a/drivers/power/max8997_charger.c +++ b/drivers/power/max8997_charger.c | |||
@@ -86,7 +86,7 @@ static int max8997_battery_get_property(struct power_supply *psy, | |||
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
88 | 88 | ||
89 | static int max8997_battery_probe(struct platform_device *pdev) | 89 | static __devinit int max8997_battery_probe(struct platform_device *pdev) |
90 | { | 90 | { |
91 | int ret = 0; | 91 | int ret = 0; |
92 | struct charger_data *charger; | 92 | struct charger_data *charger; |
@@ -97,7 +97,7 @@ static int max8997_battery_probe(struct platform_device *pdev) | |||
97 | return -EINVAL; | 97 | return -EINVAL; |
98 | 98 | ||
99 | if (pdata->eoc_mA) { | 99 | if (pdata->eoc_mA) { |
100 | int val = (pdata->eoc_mA - 50) / 10; | 100 | u8 val = (pdata->eoc_mA - 50) / 10; |
101 | if (val < 0) | 101 | if (val < 0) |
102 | val = 0; | 102 | val = 0; |
103 | if (val > 0xf) | 103 | if (val > 0xf) |
@@ -167,7 +167,7 @@ err: | |||
167 | return ret; | 167 | return ret; |
168 | } | 168 | } |
169 | 169 | ||
170 | static int max8997_battery_remove(struct platform_device *pdev) | 170 | static int __devexit max8997_battery_remove(struct platform_device *pdev) |
171 | { | 171 | { |
172 | struct charger_data *charger = platform_get_drvdata(pdev); | 172 | struct charger_data *charger = platform_get_drvdata(pdev); |
173 | 173 | ||
@@ -178,7 +178,6 @@ static int max8997_battery_remove(struct platform_device *pdev) | |||
178 | 178 | ||
179 | static const struct platform_device_id max8997_battery_id[] = { | 179 | static const struct platform_device_id max8997_battery_id[] = { |
180 | { "max8997-battery", 0 }, | 180 | { "max8997-battery", 0 }, |
181 | { } | ||
182 | }; | 181 | }; |
183 | 182 | ||
184 | static struct platform_driver max8997_battery_driver = { | 183 | static struct platform_driver max8997_battery_driver = { |
@@ -187,7 +186,7 @@ static struct platform_driver max8997_battery_driver = { | |||
187 | .owner = THIS_MODULE, | 186 | .owner = THIS_MODULE, |
188 | }, | 187 | }, |
189 | .probe = max8997_battery_probe, | 188 | .probe = max8997_battery_probe, |
190 | .remove = max8997_battery_remove, | 189 | .remove = __devexit_p(max8997_battery_remove), |
191 | .id_table = max8997_battery_id, | 190 | .id_table = max8997_battery_id, |
192 | }; | 191 | }; |
193 | 192 | ||
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c index bf677e3daec..ef8efadb58c 100644 --- a/drivers/power/max8998_charger.c +++ b/drivers/power/max8998_charger.c | |||
@@ -75,7 +75,7 @@ static int max8998_battery_get_property(struct power_supply *psy, | |||
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
77 | 77 | ||
78 | static int max8998_battery_probe(struct platform_device *pdev) | 78 | static __devinit int max8998_battery_probe(struct platform_device *pdev) |
79 | { | 79 | { |
80 | struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 80 | struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); |
81 | struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); | 81 | struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); |
@@ -153,7 +153,6 @@ static int max8998_battery_probe(struct platform_device *pdev) | |||
153 | case 0: | 153 | case 0: |
154 | dev_dbg(max8998->dev, | 154 | dev_dbg(max8998->dev, |
155 | "Full Timeout not set: leave it unchanged.\n"); | 155 | "Full Timeout not set: leave it unchanged.\n"); |
156 | break; | ||
157 | default: | 156 | default: |
158 | dev_err(max8998->dev, "Invalid Full Timeout value\n"); | 157 | dev_err(max8998->dev, "Invalid Full Timeout value\n"); |
159 | ret = -EINVAL; | 158 | ret = -EINVAL; |
@@ -178,7 +177,7 @@ err: | |||
178 | return ret; | 177 | return ret; |
179 | } | 178 | } |
180 | 179 | ||
181 | static int max8998_battery_remove(struct platform_device *pdev) | 180 | static int __devexit max8998_battery_remove(struct platform_device *pdev) |
182 | { | 181 | { |
183 | struct max8998_battery_data *max8998 = platform_get_drvdata(pdev); | 182 | struct max8998_battery_data *max8998 = platform_get_drvdata(pdev); |
184 | 183 | ||
@@ -190,7 +189,6 @@ static int max8998_battery_remove(struct platform_device *pdev) | |||
190 | 189 | ||
191 | static const struct platform_device_id max8998_battery_id[] = { | 190 | static const struct platform_device_id max8998_battery_id[] = { |
192 | { "max8998-battery", TYPE_MAX8998 }, | 191 | { "max8998-battery", TYPE_MAX8998 }, |
193 | { } | ||
194 | }; | 192 | }; |
195 | 193 | ||
196 | static struct platform_driver max8998_battery_driver = { | 194 | static struct platform_driver max8998_battery_driver = { |
@@ -199,11 +197,21 @@ static struct platform_driver max8998_battery_driver = { | |||
199 | .owner = THIS_MODULE, | 197 | .owner = THIS_MODULE, |
200 | }, | 198 | }, |
201 | .probe = max8998_battery_probe, | 199 | .probe = max8998_battery_probe, |
202 | .remove = max8998_battery_remove, | 200 | .remove = __devexit_p(max8998_battery_remove), |
203 | .id_table = max8998_battery_id, | 201 | .id_table = max8998_battery_id, |
204 | }; | 202 | }; |
205 | 203 | ||
206 | module_platform_driver(max8998_battery_driver); | 204 | static int __init max8998_battery_init(void) |
205 | { | ||
206 | return platform_driver_register(&max8998_battery_driver); | ||
207 | } | ||
208 | module_init(max8998_battery_init); | ||
209 | |||
210 | static void __exit max8998_battery_cleanup(void) | ||
211 | { | ||
212 | platform_driver_unregister(&max8998_battery_driver); | ||
213 | } | ||
214 | module_exit(max8998_battery_cleanup); | ||
207 | 215 | ||
208 | MODULE_DESCRIPTION("MAXIM 8998 battery control driver"); | 216 | MODULE_DESCRIPTION("MAXIM 8998 battery control driver"); |
209 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | 217 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); |
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c index 1ec810ada5e..0b0ff3a936a 100644 --- a/drivers/power/olpc_battery.c +++ b/drivers/power/olpc_battery.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/power_supply.h> | 17 | #include <linux/power_supply.h> |
18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/olpc-ec.h> | ||
21 | #include <asm/olpc.h> | 20 | #include <asm/olpc.h> |
22 | 21 | ||
23 | 22 | ||
@@ -232,10 +231,12 @@ static int olpc_bat_get_charge_full_design(union power_supply_propval *val) | |||
232 | 231 | ||
233 | case POWER_SUPPLY_TECHNOLOGY_LiFe: | 232 | case POWER_SUPPLY_TECHNOLOGY_LiFe: |
234 | switch (mfr) { | 233 | switch (mfr) { |
235 | case 1: /* Gold Peak, fall through */ | 234 | case 1: /* Gold Peak */ |
236 | case 2: /* BYD */ | ||
237 | val->intval = 2800000; | 235 | val->intval = 2800000; |
238 | break; | 236 | break; |
237 | case 2: /* BYD */ | ||
238 | val->intval = 3100000; | ||
239 | break; | ||
239 | default: | 240 | default: |
240 | return -EIO; | 241 | return -EIO; |
241 | } | 242 | } |
@@ -266,55 +267,6 @@ static int olpc_bat_get_charge_now(union power_supply_propval *val) | |||
266 | return 0; | 267 | return 0; |
267 | } | 268 | } |
268 | 269 | ||
269 | static int olpc_bat_get_voltage_max_design(union power_supply_propval *val) | ||
270 | { | ||
271 | uint8_t ec_byte; | ||
272 | union power_supply_propval tech; | ||
273 | int mfr; | ||
274 | int ret; | ||
275 | |||
276 | ret = olpc_bat_get_tech(&tech); | ||
277 | if (ret) | ||
278 | return ret; | ||
279 | |||
280 | ec_byte = BAT_ADDR_MFR_TYPE; | ||
281 | ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1); | ||
282 | if (ret) | ||
283 | return ret; | ||
284 | |||
285 | mfr = ec_byte >> 4; | ||
286 | |||
287 | switch (tech.intval) { | ||
288 | case POWER_SUPPLY_TECHNOLOGY_NiMH: | ||
289 | switch (mfr) { | ||
290 | case 1: /* Gold Peak */ | ||
291 | val->intval = 6000000; | ||
292 | break; | ||
293 | default: | ||
294 | return -EIO; | ||
295 | } | ||
296 | break; | ||
297 | |||
298 | case POWER_SUPPLY_TECHNOLOGY_LiFe: | ||
299 | switch (mfr) { | ||
300 | case 1: /* Gold Peak */ | ||
301 | val->intval = 6400000; | ||
302 | break; | ||
303 | case 2: /* BYD */ | ||
304 | val->intval = 6500000; | ||
305 | break; | ||
306 | default: | ||
307 | return -EIO; | ||
308 | } | ||
309 | break; | ||
310 | |||
311 | default: | ||
312 | return -EIO; | ||
313 | } | ||
314 | |||
315 | return ret; | ||
316 | } | ||
317 | |||
318 | /********************************************************************* | 270 | /********************************************************************* |
319 | * Battery properties | 271 | * Battery properties |
320 | *********************************************************************/ | 272 | *********************************************************************/ |
@@ -449,11 +401,6 @@ static int olpc_bat_get_property(struct power_supply *psy, | |||
449 | sprintf(bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf)); | 401 | sprintf(bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf)); |
450 | val->strval = bat_serial; | 402 | val->strval = bat_serial; |
451 | break; | 403 | break; |
452 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
453 | ret = olpc_bat_get_voltage_max_design(val); | ||
454 | if (ret) | ||
455 | return ret; | ||
456 | break; | ||
457 | default: | 404 | default: |
458 | ret = -EINVAL; | 405 | ret = -EINVAL; |
459 | break; | 406 | break; |
@@ -481,7 +428,6 @@ static enum power_supply_property olpc_xo1_bat_props[] = { | |||
481 | POWER_SUPPLY_PROP_MANUFACTURER, | 428 | POWER_SUPPLY_PROP_MANUFACTURER, |
482 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 429 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
483 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | 430 | POWER_SUPPLY_PROP_CHARGE_COUNTER, |
484 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
485 | }; | 431 | }; |
486 | 432 | ||
487 | /* XO-1.5 does not have ambient temperature property */ | 433 | /* XO-1.5 does not have ambient temperature property */ |
@@ -503,7 +449,6 @@ static enum power_supply_property olpc_xo15_bat_props[] = { | |||
503 | POWER_SUPPLY_PROP_MANUFACTURER, | 449 | POWER_SUPPLY_PROP_MANUFACTURER, |
504 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 450 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
505 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | 451 | POWER_SUPPLY_PROP_CHARGE_COUNTER, |
506 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
507 | }; | 452 | }; |
508 | 453 | ||
509 | /* EEPROM reading goes completely around the power_supply API, sadly */ | 454 | /* EEPROM reading goes completely around the power_supply API, sadly */ |
@@ -574,35 +519,29 @@ static struct device_attribute olpc_bat_error = { | |||
574 | * Initialisation | 519 | * Initialisation |
575 | *********************************************************************/ | 520 | *********************************************************************/ |
576 | 521 | ||
522 | static struct platform_device *bat_pdev; | ||
523 | |||
577 | static struct power_supply olpc_bat = { | 524 | static struct power_supply olpc_bat = { |
578 | .name = "olpc-battery", | ||
579 | .get_property = olpc_bat_get_property, | 525 | .get_property = olpc_bat_get_property, |
580 | .use_for_apm = 1, | 526 | .use_for_apm = 1, |
581 | }; | 527 | }; |
582 | 528 | ||
583 | static int olpc_battery_suspend(struct platform_device *pdev, | 529 | void olpc_battery_trigger_uevent(unsigned long cause) |
584 | pm_message_t state) | ||
585 | { | 530 | { |
586 | if (device_may_wakeup(olpc_ac.dev)) | 531 | if (cause & EC_SCI_SRC_ACPWR) |
587 | olpc_ec_wakeup_set(EC_SCI_SRC_ACPWR); | 532 | kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE); |
588 | else | 533 | if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY)) |
589 | olpc_ec_wakeup_clear(EC_SCI_SRC_ACPWR); | 534 | kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE); |
590 | |||
591 | if (device_may_wakeup(olpc_bat.dev)) | ||
592 | olpc_ec_wakeup_set(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC | ||
593 | | EC_SCI_SRC_BATERR); | ||
594 | else | ||
595 | olpc_ec_wakeup_clear(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC | ||
596 | | EC_SCI_SRC_BATERR); | ||
597 | |||
598 | return 0; | ||
599 | } | 535 | } |
600 | 536 | ||
601 | static int olpc_battery_probe(struct platform_device *pdev) | 537 | static int __init olpc_bat_init(void) |
602 | { | 538 | { |
603 | int ret; | 539 | int ret = 0; |
604 | uint8_t status; | 540 | uint8_t status; |
605 | 541 | ||
542 | if (!olpc_platform_info.ecver) | ||
543 | return -ENXIO; | ||
544 | |||
606 | /* | 545 | /* |
607 | * We've seen a number of EC protocol changes; this driver requires | 546 | * We've seen a number of EC protocol changes; this driver requires |
608 | * the latest EC protocol, supported by 0x44 and above. | 547 | * the latest EC protocol, supported by 0x44 and above. |
@@ -619,10 +558,15 @@ static int olpc_battery_probe(struct platform_device *pdev) | |||
619 | 558 | ||
620 | /* Ignore the status. It doesn't actually matter */ | 559 | /* Ignore the status. It doesn't actually matter */ |
621 | 560 | ||
622 | ret = power_supply_register(&pdev->dev, &olpc_ac); | 561 | bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0); |
562 | if (IS_ERR(bat_pdev)) | ||
563 | return PTR_ERR(bat_pdev); | ||
564 | |||
565 | ret = power_supply_register(&bat_pdev->dev, &olpc_ac); | ||
623 | if (ret) | 566 | if (ret) |
624 | return ret; | 567 | goto ac_failed; |
625 | 568 | ||
569 | olpc_bat.name = bat_pdev->name; | ||
626 | if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */ | 570 | if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */ |
627 | olpc_bat.properties = olpc_xo15_bat_props; | 571 | olpc_bat.properties = olpc_xo15_bat_props; |
628 | olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props); | 572 | olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props); |
@@ -631,7 +575,7 @@ static int olpc_battery_probe(struct platform_device *pdev) | |||
631 | olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props); | 575 | olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props); |
632 | } | 576 | } |
633 | 577 | ||
634 | ret = power_supply_register(&pdev->dev, &olpc_bat); | 578 | ret = power_supply_register(&bat_pdev->dev, &olpc_bat); |
635 | if (ret) | 579 | if (ret) |
636 | goto battery_failed; | 580 | goto battery_failed; |
637 | 581 | ||
@@ -643,12 +587,7 @@ static int olpc_battery_probe(struct platform_device *pdev) | |||
643 | if (ret) | 587 | if (ret) |
644 | goto error_failed; | 588 | goto error_failed; |
645 | 589 | ||
646 | if (olpc_ec_wakeup_available()) { | 590 | goto success; |
647 | device_set_wakeup_capable(olpc_ac.dev, true); | ||
648 | device_set_wakeup_capable(olpc_bat.dev, true); | ||
649 | } | ||
650 | |||
651 | return 0; | ||
652 | 591 | ||
653 | error_failed: | 592 | error_failed: |
654 | device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); | 593 | device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); |
@@ -656,36 +595,23 @@ eeprom_failed: | |||
656 | power_supply_unregister(&olpc_bat); | 595 | power_supply_unregister(&olpc_bat); |
657 | battery_failed: | 596 | battery_failed: |
658 | power_supply_unregister(&olpc_ac); | 597 | power_supply_unregister(&olpc_ac); |
598 | ac_failed: | ||
599 | platform_device_unregister(bat_pdev); | ||
600 | success: | ||
659 | return ret; | 601 | return ret; |
660 | } | 602 | } |
661 | 603 | ||
662 | static int olpc_battery_remove(struct platform_device *pdev) | 604 | static void __exit olpc_bat_exit(void) |
663 | { | 605 | { |
664 | device_remove_file(olpc_bat.dev, &olpc_bat_error); | 606 | device_remove_file(olpc_bat.dev, &olpc_bat_error); |
665 | device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); | 607 | device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); |
666 | power_supply_unregister(&olpc_bat); | 608 | power_supply_unregister(&olpc_bat); |
667 | power_supply_unregister(&olpc_ac); | 609 | power_supply_unregister(&olpc_ac); |
668 | return 0; | 610 | platform_device_unregister(bat_pdev); |
669 | } | 611 | } |
670 | 612 | ||
671 | static const struct of_device_id olpc_battery_ids[] = { | 613 | module_init(olpc_bat_init); |
672 | { .compatible = "olpc,xo1-battery" }, | 614 | module_exit(olpc_bat_exit); |
673 | {} | ||
674 | }; | ||
675 | MODULE_DEVICE_TABLE(of, olpc_battery_ids); | ||
676 | |||
677 | static struct platform_driver olpc_battery_driver = { | ||
678 | .driver = { | ||
679 | .name = "olpc-battery", | ||
680 | .owner = THIS_MODULE, | ||
681 | .of_match_table = olpc_battery_ids, | ||
682 | }, | ||
683 | .probe = olpc_battery_probe, | ||
684 | .remove = olpc_battery_remove, | ||
685 | .suspend = olpc_battery_suspend, | ||
686 | }; | ||
687 | |||
688 | module_platform_driver(olpc_battery_driver); | ||
689 | 615 | ||
690 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | 616 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); |
691 | MODULE_LICENSE("GPL"); | 617 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index c2122a7ad06..4fa52e1781a 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c | |||
@@ -366,7 +366,7 @@ static const u8 mbc_irq_handlers[] = { | |||
366 | PCF50633_IRQ_LOWBAT, | 366 | PCF50633_IRQ_LOWBAT, |
367 | }; | 367 | }; |
368 | 368 | ||
369 | static int pcf50633_mbc_probe(struct platform_device *pdev) | 369 | static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) |
370 | { | 370 | { |
371 | struct pcf50633_mbc *mbc; | 371 | struct pcf50633_mbc *mbc; |
372 | int ret; | 372 | int ret; |
@@ -447,7 +447,7 @@ static int pcf50633_mbc_probe(struct platform_device *pdev) | |||
447 | return 0; | 447 | return 0; |
448 | } | 448 | } |
449 | 449 | ||
450 | static int pcf50633_mbc_remove(struct platform_device *pdev) | 450 | static int __devexit pcf50633_mbc_remove(struct platform_device *pdev) |
451 | { | 451 | { |
452 | struct pcf50633_mbc *mbc = platform_get_drvdata(pdev); | 452 | struct pcf50633_mbc *mbc = platform_get_drvdata(pdev); |
453 | int i; | 453 | int i; |
@@ -471,10 +471,20 @@ static struct platform_driver pcf50633_mbc_driver = { | |||
471 | .name = "pcf50633-mbc", | 471 | .name = "pcf50633-mbc", |
472 | }, | 472 | }, |
473 | .probe = pcf50633_mbc_probe, | 473 | .probe = pcf50633_mbc_probe, |
474 | .remove = pcf50633_mbc_remove, | 474 | .remove = __devexit_p(pcf50633_mbc_remove), |
475 | }; | 475 | }; |
476 | 476 | ||
477 | module_platform_driver(pcf50633_mbc_driver); | 477 | static int __init pcf50633_mbc_init(void) |
478 | { | ||
479 | return platform_driver_register(&pcf50633_mbc_driver); | ||
480 | } | ||
481 | module_init(pcf50633_mbc_init); | ||
482 | |||
483 | static void __exit pcf50633_mbc_exit(void) | ||
484 | { | ||
485 | platform_driver_unregister(&pcf50633_mbc_driver); | ||
486 | } | ||
487 | module_exit(pcf50633_mbc_exit); | ||
478 | 488 | ||
479 | MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); | 489 | MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); |
480 | MODULE_DESCRIPTION("PCF50633 mbc driver"); | 490 | MODULE_DESCRIPTION("PCF50633 mbc driver"); |
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index 7df7c5facc1..81b720107c3 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c | |||
@@ -24,7 +24,11 @@ | |||
24 | 24 | ||
25 | static inline unsigned int get_irq_flags(struct resource *res) | 25 | static inline unsigned int get_irq_flags(struct resource *res) |
26 | { | 26 | { |
27 | return IRQF_SHARED | (res->flags & IRQF_TRIGGER_MASK); | 27 | unsigned int flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED; |
28 | |||
29 | flags |= res->flags & IRQF_TRIGGER_MASK; | ||
30 | |||
31 | return flags; | ||
28 | } | 32 | } |
29 | 33 | ||
30 | static struct device *dev; | 34 | static struct device *dev; |
@@ -35,11 +39,8 @@ static struct timer_list supply_timer; | |||
35 | static struct timer_list polling_timer; | 39 | static struct timer_list polling_timer; |
36 | static int polling; | 40 | static int polling; |
37 | 41 | ||
38 | #ifdef CONFIG_USB_OTG_UTILS | 42 | static struct otg_transceiver *transceiver; |
39 | static struct usb_phy *transceiver; | ||
40 | static struct notifier_block otg_nb; | 43 | static struct notifier_block otg_nb; |
41 | #endif | ||
42 | |||
43 | static struct regulator *ac_draw; | 44 | static struct regulator *ac_draw; |
44 | 45 | ||
45 | enum { | 46 | enum { |
@@ -130,13 +131,13 @@ static void update_charger(void) | |||
130 | regulator_set_current_limit(ac_draw, max_uA, max_uA); | 131 | regulator_set_current_limit(ac_draw, max_uA, max_uA); |
131 | if (!regulator_enabled) { | 132 | if (!regulator_enabled) { |
132 | dev_dbg(dev, "charger on (AC)\n"); | 133 | dev_dbg(dev, "charger on (AC)\n"); |
133 | WARN_ON(regulator_enable(ac_draw)); | 134 | regulator_enable(ac_draw); |
134 | regulator_enabled = 1; | 135 | regulator_enabled = 1; |
135 | } | 136 | } |
136 | } else { | 137 | } else { |
137 | if (regulator_enabled) { | 138 | if (regulator_enabled) { |
138 | dev_dbg(dev, "charger off\n"); | 139 | dev_dbg(dev, "charger off\n"); |
139 | WARN_ON(regulator_disable(ac_draw)); | 140 | regulator_disable(ac_draw); |
140 | regulator_enabled = 0; | 141 | regulator_enabled = 0; |
141 | } | 142 | } |
142 | } | 143 | } |
@@ -281,12 +282,6 @@ static int pda_power_probe(struct platform_device *pdev) | |||
281 | goto init_failed; | 282 | goto init_failed; |
282 | } | 283 | } |
283 | 284 | ||
284 | ac_draw = regulator_get(dev, "ac_draw"); | ||
285 | if (IS_ERR(ac_draw)) { | ||
286 | dev_dbg(dev, "couldn't get ac_draw regulator\n"); | ||
287 | ac_draw = NULL; | ||
288 | } | ||
289 | |||
290 | update_status(); | 285 | update_status(); |
291 | update_charger(); | 286 | update_charger(); |
292 | 287 | ||
@@ -315,15 +310,20 @@ static int pda_power_probe(struct platform_device *pdev) | |||
315 | pda_psy_usb.num_supplicants = pdata->num_supplicants; | 310 | pda_psy_usb.num_supplicants = pdata->num_supplicants; |
316 | } | 311 | } |
317 | 312 | ||
318 | #ifdef CONFIG_USB_OTG_UTILS | 313 | ac_draw = regulator_get(dev, "ac_draw"); |
319 | transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | 314 | if (IS_ERR(ac_draw)) { |
320 | if (!IS_ERR_OR_NULL(transceiver)) { | 315 | dev_dbg(dev, "couldn't get ac_draw regulator\n"); |
321 | if (!pdata->is_usb_online) | 316 | ac_draw = NULL; |
322 | pdata->is_usb_online = otg_is_usb_online; | 317 | ret = PTR_ERR(ac_draw); |
323 | if (!pdata->is_ac_online) | 318 | } |
324 | pdata->is_ac_online = otg_is_ac_online; | 319 | |
320 | transceiver = otg_get_transceiver(); | ||
321 | if (transceiver && !pdata->is_usb_online) { | ||
322 | pdata->is_usb_online = otg_is_usb_online; | ||
323 | } | ||
324 | if (transceiver && !pdata->is_ac_online) { | ||
325 | pdata->is_ac_online = otg_is_ac_online; | ||
325 | } | 326 | } |
326 | #endif | ||
327 | 327 | ||
328 | if (pdata->is_ac_online) { | 328 | if (pdata->is_ac_online) { |
329 | ret = power_supply_register(&pdev->dev, &pda_psy_ac); | 329 | ret = power_supply_register(&pdev->dev, &pda_psy_ac); |
@@ -367,17 +367,15 @@ static int pda_power_probe(struct platform_device *pdev) | |||
367 | } | 367 | } |
368 | } | 368 | } |
369 | 369 | ||
370 | #ifdef CONFIG_USB_OTG_UTILS | 370 | if (transceiver && pdata->use_otg_notifier) { |
371 | if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) { | ||
372 | otg_nb.notifier_call = otg_handle_notification; | 371 | otg_nb.notifier_call = otg_handle_notification; |
373 | ret = usb_register_notifier(transceiver, &otg_nb); | 372 | ret = otg_register_notifier(transceiver, &otg_nb); |
374 | if (ret) { | 373 | if (ret) { |
375 | dev_err(dev, "failure to register otg notifier\n"); | 374 | dev_err(dev, "failure to register otg notifier\n"); |
376 | goto otg_reg_notifier_failed; | 375 | goto otg_reg_notifier_failed; |
377 | } | 376 | } |
378 | polling = 0; | 377 | polling = 0; |
379 | } | 378 | } |
380 | #endif | ||
381 | 379 | ||
382 | if (polling) { | 380 | if (polling) { |
383 | dev_dbg(dev, "will poll for status\n"); | 381 | dev_dbg(dev, "will poll for status\n"); |
@@ -391,21 +389,17 @@ static int pda_power_probe(struct platform_device *pdev) | |||
391 | 389 | ||
392 | return 0; | 390 | return 0; |
393 | 391 | ||
394 | #ifdef CONFIG_USB_OTG_UTILS | ||
395 | otg_reg_notifier_failed: | 392 | otg_reg_notifier_failed: |
396 | if (pdata->is_usb_online && usb_irq) | 393 | if (pdata->is_usb_online && usb_irq) |
397 | free_irq(usb_irq->start, &pda_psy_usb); | 394 | free_irq(usb_irq->start, &pda_psy_usb); |
398 | #endif | ||
399 | usb_irq_failed: | 395 | usb_irq_failed: |
400 | if (pdata->is_usb_online) | 396 | if (pdata->is_usb_online) |
401 | power_supply_unregister(&pda_psy_usb); | 397 | power_supply_unregister(&pda_psy_usb); |
402 | usb_supply_failed: | 398 | usb_supply_failed: |
403 | if (pdata->is_ac_online && ac_irq) | 399 | if (pdata->is_ac_online && ac_irq) |
404 | free_irq(ac_irq->start, &pda_psy_ac); | 400 | free_irq(ac_irq->start, &pda_psy_ac); |
405 | #ifdef CONFIG_USB_OTG_UTILS | 401 | if (transceiver) |
406 | if (!IS_ERR_OR_NULL(transceiver)) | 402 | otg_put_transceiver(transceiver); |
407 | usb_put_phy(transceiver); | ||
408 | #endif | ||
409 | ac_irq_failed: | 403 | ac_irq_failed: |
410 | if (pdata->is_ac_online) | 404 | if (pdata->is_ac_online) |
411 | power_supply_unregister(&pda_psy_ac); | 405 | power_supply_unregister(&pda_psy_ac); |
@@ -438,8 +432,8 @@ static int pda_power_remove(struct platform_device *pdev) | |||
438 | if (pdata->is_ac_online) | 432 | if (pdata->is_ac_online) |
439 | power_supply_unregister(&pda_psy_ac); | 433 | power_supply_unregister(&pda_psy_ac); |
440 | #ifdef CONFIG_USB_OTG_UTILS | 434 | #ifdef CONFIG_USB_OTG_UTILS |
441 | if (!IS_ERR_OR_NULL(transceiver)) | 435 | if (transceiver) |
442 | usb_put_phy(transceiver); | 436 | otg_put_transceiver(transceiver); |
443 | #endif | 437 | #endif |
444 | if (ac_draw) { | 438 | if (ac_draw) { |
445 | regulator_put(ac_draw); | 439 | regulator_put(ac_draw); |
@@ -493,6 +487,8 @@ static int pda_power_resume(struct platform_device *pdev) | |||
493 | #define pda_power_resume NULL | 487 | #define pda_power_resume NULL |
494 | #endif /* CONFIG_PM */ | 488 | #endif /* CONFIG_PM */ |
495 | 489 | ||
490 | MODULE_ALIAS("platform:pda-power"); | ||
491 | |||
496 | static struct platform_driver pda_power_pdrv = { | 492 | static struct platform_driver pda_power_pdrv = { |
497 | .driver = { | 493 | .driver = { |
498 | .name = "pda-power", | 494 | .name = "pda-power", |
@@ -503,8 +499,17 @@ static struct platform_driver pda_power_pdrv = { | |||
503 | .resume = pda_power_resume, | 499 | .resume = pda_power_resume, |
504 | }; | 500 | }; |
505 | 501 | ||
506 | module_platform_driver(pda_power_pdrv); | 502 | static int __init pda_power_init(void) |
503 | { | ||
504 | return platform_driver_register(&pda_power_pdrv); | ||
505 | } | ||
506 | |||
507 | static void __exit pda_power_exit(void) | ||
508 | { | ||
509 | platform_driver_unregister(&pda_power_pdrv); | ||
510 | } | ||
507 | 511 | ||
512 | module_init(pda_power_init); | ||
513 | module_exit(pda_power_exit); | ||
508 | MODULE_LICENSE("GPL"); | 514 | MODULE_LICENSE("GPL"); |
509 | MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>"); | 515 | MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>"); |
510 | MODULE_ALIAS("platform:pda-power"); | ||
diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h index cc439fd89d8..018de2b2699 100644 --- a/drivers/power/power_supply.h +++ b/drivers/power/power_supply.h | |||
@@ -10,10 +10,6 @@ | |||
10 | * You may use this code as per GPL version 2 | 10 | * You may use this code as per GPL version 2 |
11 | */ | 11 | */ |
12 | 12 | ||
13 | struct device; | ||
14 | struct device_type; | ||
15 | struct power_supply; | ||
16 | |||
17 | #ifdef CONFIG_SYSFS | 13 | #ifdef CONFIG_SYSFS |
18 | 14 | ||
19 | extern void power_supply_init_attrs(struct device_type *dev_type); | 15 | extern void power_supply_init_attrs(struct device_type *dev_type); |
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 8a7cfb3cc16..03810ce5633 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/power_supply.h> | 19 | #include <linux/power_supply.h> |
20 | #include <linux/thermal.h> | ||
21 | #include "power_supply.h" | 20 | #include "power_supply.h" |
22 | 21 | ||
23 | /* exported for the APM Power driver, APM emulation */ | 22 | /* exported for the APM Power driver, APM emulation */ |
@@ -42,23 +41,40 @@ static int __power_supply_changed_work(struct device *dev, void *data) | |||
42 | 41 | ||
43 | static void power_supply_changed_work(struct work_struct *work) | 42 | static void power_supply_changed_work(struct work_struct *work) |
44 | { | 43 | { |
44 | unsigned long flags; | ||
45 | struct power_supply *psy = container_of(work, struct power_supply, | 45 | struct power_supply *psy = container_of(work, struct power_supply, |
46 | changed_work); | 46 | changed_work); |
47 | 47 | ||
48 | dev_dbg(psy->dev, "%s\n", __func__); | 48 | dev_dbg(psy->dev, "%s\n", __func__); |
49 | 49 | ||
50 | class_for_each_device(power_supply_class, NULL, psy, | 50 | spin_lock_irqsave(&psy->changed_lock, flags); |
51 | __power_supply_changed_work); | 51 | if (psy->changed) { |
52 | psy->changed = false; | ||
53 | spin_unlock_irqrestore(&psy->changed_lock, flags); | ||
52 | 54 | ||
53 | power_supply_update_leds(psy); | 55 | class_for_each_device(power_supply_class, NULL, psy, |
56 | __power_supply_changed_work); | ||
54 | 57 | ||
55 | kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE); | 58 | power_supply_update_leds(psy); |
59 | |||
60 | kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE); | ||
61 | spin_lock_irqsave(&psy->changed_lock, flags); | ||
62 | } | ||
63 | if (!psy->changed) | ||
64 | wake_unlock(&psy->work_wake_lock); | ||
65 | spin_unlock_irqrestore(&psy->changed_lock, flags); | ||
56 | } | 66 | } |
57 | 67 | ||
58 | void power_supply_changed(struct power_supply *psy) | 68 | void power_supply_changed(struct power_supply *psy) |
59 | { | 69 | { |
70 | unsigned long flags; | ||
71 | |||
60 | dev_dbg(psy->dev, "%s\n", __func__); | 72 | dev_dbg(psy->dev, "%s\n", __func__); |
61 | 73 | ||
74 | spin_lock_irqsave(&psy->changed_lock, flags); | ||
75 | psy->changed = true; | ||
76 | wake_lock(&psy->work_wake_lock); | ||
77 | spin_unlock_irqrestore(&psy->changed_lock, flags); | ||
62 | schedule_work(&psy->changed_work); | 78 | schedule_work(&psy->changed_work); |
63 | } | 79 | } |
64 | EXPORT_SYMBOL_GPL(power_supply_changed); | 80 | EXPORT_SYMBOL_GPL(power_supply_changed); |
@@ -99,9 +115,7 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data) | |||
99 | { | 115 | { |
100 | union power_supply_propval ret = {0,}; | 116 | union power_supply_propval ret = {0,}; |
101 | struct power_supply *psy = dev_get_drvdata(dev); | 117 | struct power_supply *psy = dev_get_drvdata(dev); |
102 | unsigned int *count = data; | ||
103 | 118 | ||
104 | (*count)++; | ||
105 | if (psy->type != POWER_SUPPLY_TYPE_BATTERY) { | 119 | if (psy->type != POWER_SUPPLY_TYPE_BATTERY) { |
106 | if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret)) | 120 | if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret)) |
107 | return 0; | 121 | return 0; |
@@ -114,18 +128,10 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data) | |||
114 | int power_supply_is_system_supplied(void) | 128 | int power_supply_is_system_supplied(void) |
115 | { | 129 | { |
116 | int error; | 130 | int error; |
117 | unsigned int count = 0; | ||
118 | 131 | ||
119 | error = class_for_each_device(power_supply_class, NULL, &count, | 132 | error = class_for_each_device(power_supply_class, NULL, NULL, |
120 | __power_supply_is_system_supplied); | 133 | __power_supply_is_system_supplied); |
121 | 134 | ||
122 | /* | ||
123 | * If no power class device was found at all, most probably we are | ||
124 | * running on a desktop system, so assume we are on mains power. | ||
125 | */ | ||
126 | if (count == 0) | ||
127 | return 1; | ||
128 | |||
129 | return error; | 135 | return error; |
130 | } | 136 | } |
131 | EXPORT_SYMBOL_GPL(power_supply_is_system_supplied); | 137 | EXPORT_SYMBOL_GPL(power_supply_is_system_supplied); |
@@ -158,164 +164,12 @@ struct power_supply *power_supply_get_by_name(char *name) | |||
158 | } | 164 | } |
159 | EXPORT_SYMBOL_GPL(power_supply_get_by_name); | 165 | EXPORT_SYMBOL_GPL(power_supply_get_by_name); |
160 | 166 | ||
161 | int power_supply_powers(struct power_supply *psy, struct device *dev) | ||
162 | { | ||
163 | return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers"); | ||
164 | } | ||
165 | EXPORT_SYMBOL_GPL(power_supply_powers); | ||
166 | |||
167 | static void power_supply_dev_release(struct device *dev) | 167 | static void power_supply_dev_release(struct device *dev) |
168 | { | 168 | { |
169 | pr_debug("device: '%s': %s\n", dev_name(dev), __func__); | 169 | pr_debug("device: '%s': %s\n", dev_name(dev), __func__); |
170 | kfree(dev); | 170 | kfree(dev); |
171 | } | 171 | } |
172 | 172 | ||
173 | #ifdef CONFIG_THERMAL | ||
174 | static int power_supply_read_temp(struct thermal_zone_device *tzd, | ||
175 | unsigned long *temp) | ||
176 | { | ||
177 | struct power_supply *psy; | ||
178 | union power_supply_propval val; | ||
179 | int ret; | ||
180 | |||
181 | WARN_ON(tzd == NULL); | ||
182 | psy = tzd->devdata; | ||
183 | ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val); | ||
184 | |||
185 | /* Convert tenths of degree Celsius to milli degree Celsius. */ | ||
186 | if (!ret) | ||
187 | *temp = val.intval * 100; | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static struct thermal_zone_device_ops psy_tzd_ops = { | ||
193 | .get_temp = power_supply_read_temp, | ||
194 | }; | ||
195 | |||
196 | static int psy_register_thermal(struct power_supply *psy) | ||
197 | { | ||
198 | int i; | ||
199 | |||
200 | /* Register battery zone device psy reports temperature */ | ||
201 | for (i = 0; i < psy->num_properties; i++) { | ||
202 | if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) { | ||
203 | psy->tzd = thermal_zone_device_register(psy->name, 0, 0, | ||
204 | psy, &psy_tzd_ops, NULL, 0, 0); | ||
205 | if (IS_ERR(psy->tzd)) | ||
206 | return PTR_ERR(psy->tzd); | ||
207 | break; | ||
208 | } | ||
209 | } | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static void psy_unregister_thermal(struct power_supply *psy) | ||
214 | { | ||
215 | if (IS_ERR_OR_NULL(psy->tzd)) | ||
216 | return; | ||
217 | thermal_zone_device_unregister(psy->tzd); | ||
218 | } | ||
219 | |||
220 | /* thermal cooling device callbacks */ | ||
221 | static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device *tcd, | ||
222 | unsigned long *state) | ||
223 | { | ||
224 | struct power_supply *psy; | ||
225 | union power_supply_propval val; | ||
226 | int ret; | ||
227 | |||
228 | psy = tcd->devdata; | ||
229 | ret = psy->get_property(psy, | ||
230 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val); | ||
231 | if (!ret) | ||
232 | *state = val.intval; | ||
233 | |||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device *tcd, | ||
238 | unsigned long *state) | ||
239 | { | ||
240 | struct power_supply *psy; | ||
241 | union power_supply_propval val; | ||
242 | int ret; | ||
243 | |||
244 | psy = tcd->devdata; | ||
245 | ret = psy->get_property(psy, | ||
246 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val); | ||
247 | if (!ret) | ||
248 | *state = val.intval; | ||
249 | |||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device *tcd, | ||
254 | unsigned long state) | ||
255 | { | ||
256 | struct power_supply *psy; | ||
257 | union power_supply_propval val; | ||
258 | int ret; | ||
259 | |||
260 | psy = tcd->devdata; | ||
261 | val.intval = state; | ||
262 | ret = psy->set_property(psy, | ||
263 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val); | ||
264 | |||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | static struct thermal_cooling_device_ops psy_tcd_ops = { | ||
269 | .get_max_state = ps_get_max_charge_cntl_limit, | ||
270 | .get_cur_state = ps_get_cur_chrage_cntl_limit, | ||
271 | .set_cur_state = ps_set_cur_charge_cntl_limit, | ||
272 | }; | ||
273 | |||
274 | static int psy_register_cooler(struct power_supply *psy) | ||
275 | { | ||
276 | int i; | ||
277 | |||
278 | /* Register for cooling device if psy can control charging */ | ||
279 | for (i = 0; i < psy->num_properties; i++) { | ||
280 | if (psy->properties[i] == | ||
281 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT) { | ||
282 | psy->tcd = thermal_cooling_device_register( | ||
283 | (char *)psy->name, | ||
284 | psy, &psy_tcd_ops); | ||
285 | if (IS_ERR(psy->tcd)) | ||
286 | return PTR_ERR(psy->tcd); | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static void psy_unregister_cooler(struct power_supply *psy) | ||
294 | { | ||
295 | if (IS_ERR_OR_NULL(psy->tcd)) | ||
296 | return; | ||
297 | thermal_cooling_device_unregister(psy->tcd); | ||
298 | } | ||
299 | #else | ||
300 | static int psy_register_thermal(struct power_supply *psy) | ||
301 | { | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static void psy_unregister_thermal(struct power_supply *psy) | ||
306 | { | ||
307 | } | ||
308 | |||
309 | static int psy_register_cooler(struct power_supply *psy) | ||
310 | { | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static void psy_unregister_cooler(struct power_supply *psy) | ||
315 | { | ||
316 | } | ||
317 | #endif | ||
318 | |||
319 | int power_supply_register(struct device *parent, struct power_supply *psy) | 173 | int power_supply_register(struct device *parent, struct power_supply *psy) |
320 | { | 174 | { |
321 | struct device *dev; | 175 | struct device *dev; |
@@ -344,13 +198,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy) | |||
344 | if (rc) | 198 | if (rc) |
345 | goto device_add_failed; | 199 | goto device_add_failed; |
346 | 200 | ||
347 | rc = psy_register_thermal(psy); | 201 | spin_lock_init(&psy->changed_lock); |
348 | if (rc) | 202 | wake_lock_init(&psy->work_wake_lock, WAKE_LOCK_SUSPEND, "power-supply"); |
349 | goto register_thermal_failed; | ||
350 | |||
351 | rc = psy_register_cooler(psy); | ||
352 | if (rc) | ||
353 | goto register_cooler_failed; | ||
354 | 203 | ||
355 | rc = power_supply_create_triggers(psy); | 204 | rc = power_supply_create_triggers(psy); |
356 | if (rc) | 205 | if (rc) |
@@ -361,10 +210,7 @@ int power_supply_register(struct device *parent, struct power_supply *psy) | |||
361 | goto success; | 210 | goto success; |
362 | 211 | ||
363 | create_triggers_failed: | 212 | create_triggers_failed: |
364 | psy_unregister_cooler(psy); | 213 | wake_lock_destroy(&psy->work_wake_lock); |
365 | register_cooler_failed: | ||
366 | psy_unregister_thermal(psy); | ||
367 | register_thermal_failed: | ||
368 | device_del(dev); | 214 | device_del(dev); |
369 | kobject_set_name_failed: | 215 | kobject_set_name_failed: |
370 | device_add_failed: | 216 | device_add_failed: |
@@ -377,10 +223,8 @@ EXPORT_SYMBOL_GPL(power_supply_register); | |||
377 | void power_supply_unregister(struct power_supply *psy) | 223 | void power_supply_unregister(struct power_supply *psy) |
378 | { | 224 | { |
379 | cancel_work_sync(&psy->changed_work); | 225 | cancel_work_sync(&psy->changed_work); |
380 | sysfs_remove_link(&psy->dev->kobj, "powers"); | ||
381 | power_supply_remove_triggers(psy); | 226 | power_supply_remove_triggers(psy); |
382 | psy_unregister_cooler(psy); | 227 | wake_lock_destroy(&psy->work_wake_lock); |
383 | psy_unregister_thermal(psy); | ||
384 | device_unregister(psy->dev); | 228 | device_unregister(psy->dev); |
385 | } | 229 | } |
386 | EXPORT_SYMBOL_GPL(power_supply_unregister); | 230 | EXPORT_SYMBOL_GPL(power_supply_unregister); |
diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c index 995f966ed5b..da25eb94e5c 100644 --- a/drivers/power/power_supply_leds.c +++ b/drivers/power/power_supply_leds.c | |||
@@ -11,7 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/device.h> | ||
15 | #include <linux/power_supply.h> | 14 | #include <linux/power_supply.h> |
16 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
17 | 16 | ||
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 40fa3b7cae5..605514afc29 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c | |||
@@ -12,10 +12,8 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
15 | #include <linux/device.h> | ||
16 | #include <linux/power_supply.h> | 15 | #include <linux/power_supply.h> |
17 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
18 | #include <linux/stat.h> | ||
19 | 17 | ||
20 | #include "power_supply.h" | 18 | #include "power_supply.h" |
21 | 19 | ||
@@ -44,7 +42,7 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
44 | struct device_attribute *attr, | 42 | struct device_attribute *attr, |
45 | char *buf) { | 43 | char *buf) { |
46 | static char *type_text[] = { | 44 | static char *type_text[] = { |
47 | "Unknown", "Battery", "UPS", "Mains", "USB", | 45 | "Battery", "UPS", "Mains", "USB", |
48 | "USB_DCP", "USB_CDP", "USB_ACA" | 46 | "USB_DCP", "USB_CDP", "USB_ACA" |
49 | }; | 47 | }; |
50 | static char *status_text[] = { | 48 | static char *status_text[] = { |
@@ -64,9 +62,6 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
64 | static char *capacity_level_text[] = { | 62 | static char *capacity_level_text[] = { |
65 | "Unknown", "Critical", "Low", "Normal", "High", "Full" | 63 | "Unknown", "Critical", "Low", "Normal", "High", "Full" |
66 | }; | 64 | }; |
67 | static char *scope_text[] = { | ||
68 | "Unknown", "System", "Device" | ||
69 | }; | ||
70 | ssize_t ret = 0; | 65 | ssize_t ret = 0; |
71 | struct power_supply *psy = dev_get_drvdata(dev); | 66 | struct power_supply *psy = dev_get_drvdata(dev); |
72 | const ptrdiff_t off = attr - power_supply_attrs; | 67 | const ptrdiff_t off = attr - power_supply_attrs; |
@@ -82,8 +77,8 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
82 | dev_dbg(dev, "driver has no data for `%s' property\n", | 77 | dev_dbg(dev, "driver has no data for `%s' property\n", |
83 | attr->attr.name); | 78 | attr->attr.name); |
84 | else if (ret != -ENODEV) | 79 | else if (ret != -ENODEV) |
85 | dev_err(dev, "driver failed to report `%s' property: %zd\n", | 80 | dev_err(dev, "driver failed to report `%s' property\n", |
86 | attr->attr.name, ret); | 81 | attr->attr.name); |
87 | return ret; | 82 | return ret; |
88 | } | 83 | } |
89 | 84 | ||
@@ -99,8 +94,6 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
99 | return sprintf(buf, "%s\n", capacity_level_text[value.intval]); | 94 | return sprintf(buf, "%s\n", capacity_level_text[value.intval]); |
100 | else if (off == POWER_SUPPLY_PROP_TYPE) | 95 | else if (off == POWER_SUPPLY_PROP_TYPE) |
101 | return sprintf(buf, "%s\n", type_text[value.intval]); | 96 | return sprintf(buf, "%s\n", type_text[value.intval]); |
102 | else if (off == POWER_SUPPLY_PROP_SCOPE) | ||
103 | return sprintf(buf, "%s\n", scope_text[value.intval]); | ||
104 | else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) | 97 | else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) |
105 | return sprintf(buf, "%s\n", value.strval); | 98 | return sprintf(buf, "%s\n", value.strval); |
106 | 99 | ||
@@ -138,7 +131,6 @@ static struct device_attribute power_supply_attrs[] = { | |||
138 | POWER_SUPPLY_ATTR(health), | 131 | POWER_SUPPLY_ATTR(health), |
139 | POWER_SUPPLY_ATTR(present), | 132 | POWER_SUPPLY_ATTR(present), |
140 | POWER_SUPPLY_ATTR(online), | 133 | POWER_SUPPLY_ATTR(online), |
141 | POWER_SUPPLY_ATTR(authentic), | ||
142 | POWER_SUPPLY_ATTR(technology), | 134 | POWER_SUPPLY_ATTR(technology), |
143 | POWER_SUPPLY_ATTR(cycle_count), | 135 | POWER_SUPPLY_ATTR(cycle_count), |
144 | POWER_SUPPLY_ATTR(voltage_max), | 136 | POWER_SUPPLY_ATTR(voltage_max), |
@@ -147,7 +139,6 @@ static struct device_attribute power_supply_attrs[] = { | |||
147 | POWER_SUPPLY_ATTR(voltage_min_design), | 139 | POWER_SUPPLY_ATTR(voltage_min_design), |
148 | POWER_SUPPLY_ATTR(voltage_now), | 140 | POWER_SUPPLY_ATTR(voltage_now), |
149 | POWER_SUPPLY_ATTR(voltage_avg), | 141 | POWER_SUPPLY_ATTR(voltage_avg), |
150 | POWER_SUPPLY_ATTR(voltage_ocv), | ||
151 | POWER_SUPPLY_ATTR(current_max), | 142 | POWER_SUPPLY_ATTR(current_max), |
152 | POWER_SUPPLY_ATTR(current_now), | 143 | POWER_SUPPLY_ATTR(current_now), |
153 | POWER_SUPPLY_ATTR(current_avg), | 144 | POWER_SUPPLY_ATTR(current_avg), |
@@ -160,12 +151,6 @@ static struct device_attribute power_supply_attrs[] = { | |||
160 | POWER_SUPPLY_ATTR(charge_now), | 151 | POWER_SUPPLY_ATTR(charge_now), |
161 | POWER_SUPPLY_ATTR(charge_avg), | 152 | POWER_SUPPLY_ATTR(charge_avg), |
162 | POWER_SUPPLY_ATTR(charge_counter), | 153 | POWER_SUPPLY_ATTR(charge_counter), |
163 | POWER_SUPPLY_ATTR(constant_charge_current), | ||
164 | POWER_SUPPLY_ATTR(constant_charge_current_max), | ||
165 | POWER_SUPPLY_ATTR(constant_charge_voltage), | ||
166 | POWER_SUPPLY_ATTR(constant_charge_voltage_max), | ||
167 | POWER_SUPPLY_ATTR(charge_control_limit), | ||
168 | POWER_SUPPLY_ATTR(charge_control_limit_max), | ||
169 | POWER_SUPPLY_ATTR(energy_full_design), | 154 | POWER_SUPPLY_ATTR(energy_full_design), |
170 | POWER_SUPPLY_ATTR(energy_empty_design), | 155 | POWER_SUPPLY_ATTR(energy_empty_design), |
171 | POWER_SUPPLY_ATTR(energy_full), | 156 | POWER_SUPPLY_ATTR(energy_full), |
@@ -173,21 +158,14 @@ static struct device_attribute power_supply_attrs[] = { | |||
173 | POWER_SUPPLY_ATTR(energy_now), | 158 | POWER_SUPPLY_ATTR(energy_now), |
174 | POWER_SUPPLY_ATTR(energy_avg), | 159 | POWER_SUPPLY_ATTR(energy_avg), |
175 | POWER_SUPPLY_ATTR(capacity), | 160 | POWER_SUPPLY_ATTR(capacity), |
176 | POWER_SUPPLY_ATTR(capacity_alert_min), | ||
177 | POWER_SUPPLY_ATTR(capacity_alert_max), | ||
178 | POWER_SUPPLY_ATTR(capacity_level), | 161 | POWER_SUPPLY_ATTR(capacity_level), |
179 | POWER_SUPPLY_ATTR(temp), | 162 | POWER_SUPPLY_ATTR(temp), |
180 | POWER_SUPPLY_ATTR(temp_alert_min), | ||
181 | POWER_SUPPLY_ATTR(temp_alert_max), | ||
182 | POWER_SUPPLY_ATTR(temp_ambient), | 163 | POWER_SUPPLY_ATTR(temp_ambient), |
183 | POWER_SUPPLY_ATTR(temp_ambient_alert_min), | ||
184 | POWER_SUPPLY_ATTR(temp_ambient_alert_max), | ||
185 | POWER_SUPPLY_ATTR(time_to_empty_now), | 164 | POWER_SUPPLY_ATTR(time_to_empty_now), |
186 | POWER_SUPPLY_ATTR(time_to_empty_avg), | 165 | POWER_SUPPLY_ATTR(time_to_empty_avg), |
187 | POWER_SUPPLY_ATTR(time_to_full_now), | 166 | POWER_SUPPLY_ATTR(time_to_full_now), |
188 | POWER_SUPPLY_ATTR(time_to_full_avg), | 167 | POWER_SUPPLY_ATTR(time_to_full_avg), |
189 | POWER_SUPPLY_ATTR(type), | 168 | POWER_SUPPLY_ATTR(type), |
190 | POWER_SUPPLY_ATTR(scope), | ||
191 | /* Properties of type `const char *' */ | 169 | /* Properties of type `const char *' */ |
192 | POWER_SUPPLY_ATTR(model_name), | 170 | POWER_SUPPLY_ATTR(model_name), |
193 | POWER_SUPPLY_ATTR(manufacturer), | 171 | POWER_SUPPLY_ATTR(manufacturer), |
@@ -197,13 +175,13 @@ static struct device_attribute power_supply_attrs[] = { | |||
197 | static struct attribute * | 175 | static struct attribute * |
198 | __power_supply_attrs[ARRAY_SIZE(power_supply_attrs) + 1]; | 176 | __power_supply_attrs[ARRAY_SIZE(power_supply_attrs) + 1]; |
199 | 177 | ||
200 | static umode_t power_supply_attr_is_visible(struct kobject *kobj, | 178 | static mode_t power_supply_attr_is_visible(struct kobject *kobj, |
201 | struct attribute *attr, | 179 | struct attribute *attr, |
202 | int attrno) | 180 | int attrno) |
203 | { | 181 | { |
204 | struct device *dev = container_of(kobj, struct device, kobj); | 182 | struct device *dev = container_of(kobj, struct device, kobj); |
205 | struct power_supply *psy = dev_get_drvdata(dev); | 183 | struct power_supply *psy = dev_get_drvdata(dev); |
206 | umode_t mode = S_IRUSR | S_IRGRP | S_IROTH; | 184 | mode_t mode = S_IRUSR | S_IRGRP | S_IROTH; |
207 | int i; | 185 | int i; |
208 | 186 | ||
209 | if (attrno == POWER_SUPPLY_PROP_TYPE) | 187 | if (attrno == POWER_SUPPLY_PROP_TYPE) |
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig deleted file mode 100644 index 6461b489fb0..00000000000 --- a/drivers/power/reset/Kconfig +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | menuconfig POWER_RESET | ||
2 | bool "Board level reset or power off" | ||
3 | help | ||
4 | Provides a number of drivers which either reset a complete board | ||
5 | or shut it down, by manipulating the main power supply on the board. | ||
6 | |||
7 | Say Y here to enable board reset and power off | ||
8 | |||
9 | config POWER_RESET_GPIO | ||
10 | bool "GPIO power-off driver" | ||
11 | depends on OF_GPIO && POWER_RESET | ||
12 | help | ||
13 | This driver supports turning off your board via a GPIO line. | ||
14 | If your board needs a GPIO high/low to power down, say Y and | ||
15 | create a binding in your devicetree. | ||
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile deleted file mode 100644 index 751488a4a0c..00000000000 --- a/drivers/power/reset/Makefile +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o | ||
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c deleted file mode 100644 index e290d48ddd9..00000000000 --- a/drivers/power/reset/gpio-poweroff.c +++ /dev/null | |||
@@ -1,126 +0,0 @@ | |||
1 | /* | ||
2 | * Toggles a GPIO pin to power down a device | ||
3 | * | ||
4 | * Jamie Lentin <jm@lentin.co.uk> | ||
5 | * Andrew Lunn <andrew@lunn.ch> | ||
6 | * | ||
7 | * Copyright (C) 2012 Jamie Lentin | ||
8 | * | ||
9 | * This program 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 | */ | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/of_gpio.h> | ||
21 | #include <linux/module.h> | ||
22 | |||
23 | /* | ||
24 | * Hold configuration here, cannot be more than one instance of the driver | ||
25 | * since pm_power_off itself is global. | ||
26 | */ | ||
27 | static int gpio_num = -1; | ||
28 | static int gpio_active_low; | ||
29 | |||
30 | static void gpio_poweroff_do_poweroff(void) | ||
31 | { | ||
32 | BUG_ON(!gpio_is_valid(gpio_num)); | ||
33 | |||
34 | /* drive it active, also inactive->active edge */ | ||
35 | gpio_direction_output(gpio_num, !gpio_active_low); | ||
36 | mdelay(100); | ||
37 | /* drive inactive, also active->inactive edge */ | ||
38 | gpio_set_value(gpio_num, gpio_active_low); | ||
39 | mdelay(100); | ||
40 | |||
41 | /* drive it active, also inactive->active edge */ | ||
42 | gpio_set_value(gpio_num, !gpio_active_low); | ||
43 | |||
44 | /* give it some time */ | ||
45 | mdelay(3000); | ||
46 | |||
47 | WARN_ON(1); | ||
48 | } | ||
49 | |||
50 | static int gpio_poweroff_probe(struct platform_device *pdev) | ||
51 | { | ||
52 | enum of_gpio_flags flags; | ||
53 | bool input = false; | ||
54 | int ret; | ||
55 | |||
56 | /* If a pm_power_off function has already been added, leave it alone */ | ||
57 | if (pm_power_off != NULL) { | ||
58 | pr_err("%s: pm_power_off function already registered", | ||
59 | __func__); | ||
60 | return -EBUSY; | ||
61 | } | ||
62 | |||
63 | gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags); | ||
64 | if (!gpio_is_valid(gpio_num)) | ||
65 | return gpio_num; | ||
66 | |||
67 | gpio_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
68 | |||
69 | input = of_property_read_bool(pdev->dev.of_node, "input"); | ||
70 | |||
71 | ret = gpio_request(gpio_num, "poweroff-gpio"); | ||
72 | if (ret) { | ||
73 | pr_err("%s: Could not get GPIO %d", __func__, gpio_num); | ||
74 | return ret; | ||
75 | } | ||
76 | if (input) { | ||
77 | if (gpio_direction_input(gpio_num)) { | ||
78 | pr_err("Could not set direction of GPIO %d to input", | ||
79 | gpio_num); | ||
80 | goto err; | ||
81 | } | ||
82 | } else { | ||
83 | if (gpio_direction_output(gpio_num, gpio_active_low)) { | ||
84 | pr_err("Could not set direction of GPIO %d", gpio_num); | ||
85 | goto err; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | pm_power_off = &gpio_poweroff_do_poweroff; | ||
90 | return 0; | ||
91 | |||
92 | err: | ||
93 | gpio_free(gpio_num); | ||
94 | return -ENODEV; | ||
95 | } | ||
96 | |||
97 | static int gpio_poweroff_remove(struct platform_device *pdev) | ||
98 | { | ||
99 | gpio_free(gpio_num); | ||
100 | if (pm_power_off == &gpio_poweroff_do_poweroff) | ||
101 | pm_power_off = NULL; | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static const struct of_device_id of_gpio_poweroff_match[] = { | ||
107 | { .compatible = "gpio-poweroff", }, | ||
108 | {}, | ||
109 | }; | ||
110 | |||
111 | static struct platform_driver gpio_poweroff_driver = { | ||
112 | .probe = gpio_poweroff_probe, | ||
113 | .remove = gpio_poweroff_remove, | ||
114 | .driver = { | ||
115 | .name = "poweroff-gpio", | ||
116 | .owner = THIS_MODULE, | ||
117 | .of_match_table = of_gpio_poweroff_match, | ||
118 | }, | ||
119 | }; | ||
120 | |||
121 | module_platform_driver(gpio_poweroff_driver); | ||
122 | |||
123 | MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>"); | ||
124 | MODULE_DESCRIPTION("GPIO poweroff driver"); | ||
125 | MODULE_LICENSE("GPL v2"); | ||
126 | MODULE_ALIAS("platform:poweroff-gpio"); | ||
diff --git a/drivers/power/rx51_battery.c b/drivers/power/rx51_battery.c deleted file mode 100644 index 8208888b844..00000000000 --- a/drivers/power/rx51_battery.c +++ /dev/null | |||
@@ -1,251 +0,0 @@ | |||
1 | /* | ||
2 | * Nokia RX-51 battery driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/param.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/power_supply.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/i2c/twl4030-madc.h> | ||
27 | |||
28 | struct rx51_device_info { | ||
29 | struct device *dev; | ||
30 | struct power_supply bat; | ||
31 | }; | ||
32 | |||
33 | /* | ||
34 | * Read ADCIN channel value, code copied from maemo kernel | ||
35 | */ | ||
36 | static int rx51_battery_read_adc(int channel) | ||
37 | { | ||
38 | struct twl4030_madc_request req; | ||
39 | |||
40 | req.channels = 1 << channel; | ||
41 | req.do_avg = 1; | ||
42 | req.method = TWL4030_MADC_SW1; | ||
43 | req.func_cb = NULL; | ||
44 | req.type = TWL4030_MADC_WAIT; | ||
45 | |||
46 | if (twl4030_madc_conversion(&req) <= 0) | ||
47 | return -ENODATA; | ||
48 | |||
49 | return req.rbuf[channel]; | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Read ADCIN channel 12 (voltage) and convert RAW value to micro voltage | ||
54 | * This conversion formula was extracted from maemo program bsi-read | ||
55 | */ | ||
56 | static int rx51_battery_read_voltage(struct rx51_device_info *di) | ||
57 | { | ||
58 | int voltage = rx51_battery_read_adc(12); | ||
59 | |||
60 | if (voltage < 0) | ||
61 | return voltage; | ||
62 | |||
63 | return 1000 * (10000 * voltage / 1705); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Temperature look-up tables | ||
68 | * TEMP = (1/(t1 + 1/298) - 273.15) | ||
69 | * Where t1 = (1/B) * ln((RAW_ADC_U * 2.5)/(R * I * 255)) | ||
70 | * Formula is based on experimental data, RX-51 CAL data, maemo program bme | ||
71 | * and formula from da9052 driver with values R = 100, B = 3380, I = 0.00671 | ||
72 | */ | ||
73 | |||
74 | /* | ||
75 | * Table1 (temperature for first 25 RAW values) | ||
76 | * Usage: TEMP = rx51_temp_table1[RAW] | ||
77 | * RAW is between 1 and 24 | ||
78 | * TEMP is between 201 C and 55 C | ||
79 | */ | ||
80 | static u8 rx51_temp_table1[] = { | ||
81 | 255, 201, 159, 138, 124, 114, 106, 99, 94, 89, 85, 82, 78, 75, | ||
82 | 73, 70, 68, 66, 64, 62, 61, 59, 57, 56, 55 | ||
83 | }; | ||
84 | |||
85 | /* | ||
86 | * Table2 (lowest RAW value for temperature) | ||
87 | * Usage: RAW = rx51_temp_table2[TEMP-rx51_temp_table2_first] | ||
88 | * TEMP is between 53 C and -32 C | ||
89 | * RAW is between 25 and 993 | ||
90 | */ | ||
91 | #define rx51_temp_table2_first 53 | ||
92 | static u16 rx51_temp_table2[] = { | ||
93 | 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, | ||
94 | 40, 41, 43, 44, 46, 48, 49, 51, 53, 55, 57, 59, 61, 64, | ||
95 | 66, 69, 71, 74, 77, 80, 83, 86, 90, 94, 97, 101, 106, 110, | ||
96 | 115, 119, 125, 130, 136, 141, 148, 154, 161, 168, 176, 184, 202, 211, | ||
97 | 221, 231, 242, 254, 266, 279, 293, 308, 323, 340, 357, 375, 395, 415, | ||
98 | 437, 460, 485, 511, 539, 568, 600, 633, 669, 706, 747, 790, 836, 885, | ||
99 | 937, 993, 1024 | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * Read ADCIN channel 0 (battery temp) and convert value to tenths of Celsius | ||
104 | * Use Temperature look-up tables for conversation | ||
105 | */ | ||
106 | static int rx51_battery_read_temperature(struct rx51_device_info *di) | ||
107 | { | ||
108 | int min = 0; | ||
109 | int max = ARRAY_SIZE(rx51_temp_table2) - 1; | ||
110 | int raw = rx51_battery_read_adc(0); | ||
111 | |||
112 | /* Zero and negative values are undefined */ | ||
113 | if (raw <= 0) | ||
114 | return INT_MAX; | ||
115 | |||
116 | /* ADC channels are 10 bit, higher value are undefined */ | ||
117 | if (raw >= (1 << 10)) | ||
118 | return INT_MIN; | ||
119 | |||
120 | /* First check for temperature in first direct table */ | ||
121 | if (raw < ARRAY_SIZE(rx51_temp_table1)) | ||
122 | return rx51_temp_table1[raw] * 100; | ||
123 | |||
124 | /* Binary search RAW value in second inverse table */ | ||
125 | while (max - min > 1) { | ||
126 | int mid = (max + min) / 2; | ||
127 | if (rx51_temp_table2[mid] <= raw) | ||
128 | min = mid; | ||
129 | else if (rx51_temp_table2[mid] > raw) | ||
130 | max = mid; | ||
131 | if (rx51_temp_table2[mid] == raw) | ||
132 | break; | ||
133 | } | ||
134 | |||
135 | return (rx51_temp_table2_first - min) * 100; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Read ADCIN channel 4 (BSI) and convert RAW value to micro Ah | ||
140 | * This conversion formula was extracted from maemo program bsi-read | ||
141 | */ | ||
142 | static int rx51_battery_read_capacity(struct rx51_device_info *di) | ||
143 | { | ||
144 | int capacity = rx51_battery_read_adc(4); | ||
145 | |||
146 | if (capacity < 0) | ||
147 | return capacity; | ||
148 | |||
149 | return 1280 * (1200 * capacity)/(1024 - capacity); | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Return power_supply property | ||
154 | */ | ||
155 | static int rx51_battery_get_property(struct power_supply *psy, | ||
156 | enum power_supply_property psp, | ||
157 | union power_supply_propval *val) | ||
158 | { | ||
159 | struct rx51_device_info *di = container_of((psy), | ||
160 | struct rx51_device_info, bat); | ||
161 | |||
162 | switch (psp) { | ||
163 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
164 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | ||
165 | break; | ||
166 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
167 | val->intval = 4200000; | ||
168 | break; | ||
169 | case POWER_SUPPLY_PROP_PRESENT: | ||
170 | val->intval = rx51_battery_read_voltage(di) ? 1 : 0; | ||
171 | break; | ||
172 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
173 | val->intval = rx51_battery_read_voltage(di); | ||
174 | break; | ||
175 | case POWER_SUPPLY_PROP_TEMP: | ||
176 | val->intval = rx51_battery_read_temperature(di); | ||
177 | break; | ||
178 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
179 | val->intval = rx51_battery_read_capacity(di); | ||
180 | break; | ||
181 | default: | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | if (val->intval == INT_MAX || val->intval == INT_MIN) | ||
186 | return -EINVAL; | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static enum power_supply_property rx51_battery_props[] = { | ||
192 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
193 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
194 | POWER_SUPPLY_PROP_PRESENT, | ||
195 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
196 | POWER_SUPPLY_PROP_TEMP, | ||
197 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
198 | }; | ||
199 | |||
200 | static int rx51_battery_probe(struct platform_device *pdev) | ||
201 | { | ||
202 | struct rx51_device_info *di; | ||
203 | int ret; | ||
204 | |||
205 | di = kzalloc(sizeof(*di), GFP_KERNEL); | ||
206 | if (!di) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | platform_set_drvdata(pdev, di); | ||
210 | |||
211 | di->bat.name = dev_name(&pdev->dev); | ||
212 | di->bat.type = POWER_SUPPLY_TYPE_BATTERY; | ||
213 | di->bat.properties = rx51_battery_props; | ||
214 | di->bat.num_properties = ARRAY_SIZE(rx51_battery_props); | ||
215 | di->bat.get_property = rx51_battery_get_property; | ||
216 | |||
217 | ret = power_supply_register(di->dev, &di->bat); | ||
218 | if (ret) { | ||
219 | platform_set_drvdata(pdev, NULL); | ||
220 | kfree(di); | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int rx51_battery_remove(struct platform_device *pdev) | ||
228 | { | ||
229 | struct rx51_device_info *di = platform_get_drvdata(pdev); | ||
230 | |||
231 | power_supply_unregister(&di->bat); | ||
232 | platform_set_drvdata(pdev, NULL); | ||
233 | kfree(di); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static struct platform_driver rx51_battery_driver = { | ||
239 | .probe = rx51_battery_probe, | ||
240 | .remove = rx51_battery_remove, | ||
241 | .driver = { | ||
242 | .name = "rx51-battery", | ||
243 | .owner = THIS_MODULE, | ||
244 | }, | ||
245 | }; | ||
246 | module_platform_driver(rx51_battery_driver); | ||
247 | |||
248 | MODULE_ALIAS("platform:rx51-battery"); | ||
249 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); | ||
250 | MODULE_DESCRIPTION("Nokia RX-51 battery driver"); | ||
251 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c index d2ca989dcbd..d32d0d70f9b 100644 --- a/drivers/power/s3c_adc_battery.c +++ b/drivers/power/s3c_adc_battery.c | |||
@@ -47,22 +47,6 @@ static void s3c_adc_bat_ext_power_changed(struct power_supply *psy) | |||
47 | msecs_to_jiffies(JITTER_DELAY)); | 47 | msecs_to_jiffies(JITTER_DELAY)); |
48 | } | 48 | } |
49 | 49 | ||
50 | static int gather_samples(struct s3c_adc_client *client, int num, int channel) | ||
51 | { | ||
52 | int value, i; | ||
53 | |||
54 | /* default to 1 if nothing is set */ | ||
55 | if (num < 1) | ||
56 | num = 1; | ||
57 | |||
58 | value = 0; | ||
59 | for (i = 0; i < num; i++) | ||
60 | value += s3c_adc_read(client, channel); | ||
61 | value /= num; | ||
62 | |||
63 | return value; | ||
64 | } | ||
65 | |||
66 | static enum power_supply_property s3c_adc_backup_bat_props[] = { | 50 | static enum power_supply_property s3c_adc_backup_bat_props[] = { |
67 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 51 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
68 | POWER_SUPPLY_PROP_VOLTAGE_MIN, | 52 | POWER_SUPPLY_PROP_VOLTAGE_MIN, |
@@ -83,8 +67,7 @@ static int s3c_adc_backup_bat_get_property(struct power_supply *psy, | |||
83 | if (bat->volt_value < 0 || | 67 | if (bat->volt_value < 0 || |
84 | jiffies_to_msecs(jiffies - bat->timestamp) > | 68 | jiffies_to_msecs(jiffies - bat->timestamp) > |
85 | BAT_POLL_INTERVAL) { | 69 | BAT_POLL_INTERVAL) { |
86 | bat->volt_value = gather_samples(bat->client, | 70 | bat->volt_value = s3c_adc_read(bat->client, |
87 | bat->pdata->backup_volt_samples, | ||
88 | bat->pdata->backup_volt_channel); | 71 | bat->pdata->backup_volt_channel); |
89 | bat->volt_value *= bat->pdata->backup_volt_mult; | 72 | bat->volt_value *= bat->pdata->backup_volt_mult; |
90 | bat->timestamp = jiffies; | 73 | bat->timestamp = jiffies; |
@@ -156,11 +139,9 @@ static int s3c_adc_bat_get_property(struct power_supply *psy, | |||
156 | if (bat->volt_value < 0 || bat->cur_value < 0 || | 139 | if (bat->volt_value < 0 || bat->cur_value < 0 || |
157 | jiffies_to_msecs(jiffies - bat->timestamp) > | 140 | jiffies_to_msecs(jiffies - bat->timestamp) > |
158 | BAT_POLL_INTERVAL) { | 141 | BAT_POLL_INTERVAL) { |
159 | bat->volt_value = gather_samples(bat->client, | 142 | bat->volt_value = s3c_adc_read(bat->client, |
160 | bat->pdata->volt_samples, | ||
161 | bat->pdata->volt_channel) * bat->pdata->volt_mult; | 143 | bat->pdata->volt_channel) * bat->pdata->volt_mult; |
162 | bat->cur_value = gather_samples(bat->client, | 144 | bat->cur_value = s3c_adc_read(bat->client, |
163 | bat->pdata->current_samples, | ||
164 | bat->pdata->current_channel) * bat->pdata->current_mult; | 145 | bat->pdata->current_channel) * bat->pdata->current_mult; |
165 | bat->timestamp = jiffies; | 146 | bat->timestamp = jiffies; |
166 | } | 147 | } |
@@ -286,7 +267,7 @@ static irqreturn_t s3c_adc_bat_charged(int irq, void *dev_id) | |||
286 | return IRQ_HANDLED; | 267 | return IRQ_HANDLED; |
287 | } | 268 | } |
288 | 269 | ||
289 | static int s3c_adc_bat_probe(struct platform_device *pdev) | 270 | static int __devinit s3c_adc_bat_probe(struct platform_device *pdev) |
290 | { | 271 | { |
291 | struct s3c_adc_client *client; | 272 | struct s3c_adc_client *client; |
292 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; | 273 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; |
@@ -440,7 +421,17 @@ static struct platform_driver s3c_adc_bat_driver = { | |||
440 | .resume = s3c_adc_bat_resume, | 421 | .resume = s3c_adc_bat_resume, |
441 | }; | 422 | }; |
442 | 423 | ||
443 | module_platform_driver(s3c_adc_bat_driver); | 424 | static int __init s3c_adc_bat_init(void) |
425 | { | ||
426 | return platform_driver_register(&s3c_adc_bat_driver); | ||
427 | } | ||
428 | module_init(s3c_adc_bat_init); | ||
429 | |||
430 | static void __exit s3c_adc_bat_exit(void) | ||
431 | { | ||
432 | platform_driver_unregister(&s3c_adc_bat_driver); | ||
433 | } | ||
434 | module_exit(s3c_adc_bat_exit); | ||
444 | 435 | ||
445 | MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>"); | 436 | MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>"); |
446 | MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controller driver"); | 437 | MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controller driver"); |
diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c deleted file mode 100644 index 3960f0b2afe..00000000000 --- a/drivers/power/sbs-battery.c +++ /dev/null | |||
@@ -1,868 +0,0 @@ | |||
1 | /* | ||
2 | * Gas Gauge driver for SBS Compliant Batteries | ||
3 | * | ||
4 | * Copyright (c) 2010, NVIDIA Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/power_supply.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/gpio.h> | ||
30 | |||
31 | #include <linux/power/sbs-battery.h> | ||
32 | |||
33 | enum { | ||
34 | REG_MANUFACTURER_DATA, | ||
35 | REG_TEMPERATURE, | ||
36 | REG_VOLTAGE, | ||
37 | REG_CURRENT, | ||
38 | REG_CAPACITY, | ||
39 | REG_TIME_TO_EMPTY, | ||
40 | REG_TIME_TO_FULL, | ||
41 | REG_STATUS, | ||
42 | REG_CYCLE_COUNT, | ||
43 | REG_SERIAL_NUMBER, | ||
44 | REG_REMAINING_CAPACITY, | ||
45 | REG_REMAINING_CAPACITY_CHARGE, | ||
46 | REG_FULL_CHARGE_CAPACITY, | ||
47 | REG_FULL_CHARGE_CAPACITY_CHARGE, | ||
48 | REG_DESIGN_CAPACITY, | ||
49 | REG_DESIGN_CAPACITY_CHARGE, | ||
50 | REG_DESIGN_VOLTAGE, | ||
51 | }; | ||
52 | |||
53 | /* Battery Mode defines */ | ||
54 | #define BATTERY_MODE_OFFSET 0x03 | ||
55 | #define BATTERY_MODE_MASK 0x8000 | ||
56 | enum sbs_battery_mode { | ||
57 | BATTERY_MODE_AMPS, | ||
58 | BATTERY_MODE_WATTS | ||
59 | }; | ||
60 | |||
61 | /* manufacturer access defines */ | ||
62 | #define MANUFACTURER_ACCESS_STATUS 0x0006 | ||
63 | #define MANUFACTURER_ACCESS_SLEEP 0x0011 | ||
64 | |||
65 | /* battery status value bits */ | ||
66 | #define BATTERY_DISCHARGING 0x40 | ||
67 | #define BATTERY_FULL_CHARGED 0x20 | ||
68 | #define BATTERY_FULL_DISCHARGED 0x10 | ||
69 | |||
70 | #define SBS_DATA(_psp, _addr, _min_value, _max_value) { \ | ||
71 | .psp = _psp, \ | ||
72 | .addr = _addr, \ | ||
73 | .min_value = _min_value, \ | ||
74 | .max_value = _max_value, \ | ||
75 | } | ||
76 | |||
77 | static const struct chip_data { | ||
78 | enum power_supply_property psp; | ||
79 | u8 addr; | ||
80 | int min_value; | ||
81 | int max_value; | ||
82 | } sbs_data[] = { | ||
83 | [REG_MANUFACTURER_DATA] = | ||
84 | SBS_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535), | ||
85 | [REG_TEMPERATURE] = | ||
86 | SBS_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535), | ||
87 | [REG_VOLTAGE] = | ||
88 | SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000), | ||
89 | [REG_CURRENT] = | ||
90 | SBS_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768, 32767), | ||
91 | [REG_CAPACITY] = | ||
92 | SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0D, 0, 100), | ||
93 | [REG_REMAINING_CAPACITY] = | ||
94 | SBS_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535), | ||
95 | [REG_REMAINING_CAPACITY_CHARGE] = | ||
96 | SBS_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535), | ||
97 | [REG_FULL_CHARGE_CAPACITY] = | ||
98 | SBS_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535), | ||
99 | [REG_FULL_CHARGE_CAPACITY_CHARGE] = | ||
100 | SBS_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535), | ||
101 | [REG_TIME_TO_EMPTY] = | ||
102 | SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0, 65535), | ||
103 | [REG_TIME_TO_FULL] = | ||
104 | SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0, 65535), | ||
105 | [REG_STATUS] = | ||
106 | SBS_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535), | ||
107 | [REG_CYCLE_COUNT] = | ||
108 | SBS_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535), | ||
109 | [REG_DESIGN_CAPACITY] = | ||
110 | SBS_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0, 65535), | ||
111 | [REG_DESIGN_CAPACITY_CHARGE] = | ||
112 | SBS_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0, 65535), | ||
113 | [REG_DESIGN_VOLTAGE] = | ||
114 | SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0, 65535), | ||
115 | [REG_SERIAL_NUMBER] = | ||
116 | SBS_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535), | ||
117 | }; | ||
118 | |||
119 | static enum power_supply_property sbs_properties[] = { | ||
120 | POWER_SUPPLY_PROP_STATUS, | ||
121 | POWER_SUPPLY_PROP_HEALTH, | ||
122 | POWER_SUPPLY_PROP_PRESENT, | ||
123 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
124 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
125 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
126 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
127 | POWER_SUPPLY_PROP_CAPACITY, | ||
128 | POWER_SUPPLY_PROP_TEMP, | ||
129 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, | ||
130 | POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, | ||
131 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | ||
132 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
133 | POWER_SUPPLY_PROP_ENERGY_NOW, | ||
134 | POWER_SUPPLY_PROP_ENERGY_FULL, | ||
135 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, | ||
136 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
137 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
138 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
139 | }; | ||
140 | |||
141 | struct sbs_info { | ||
142 | struct i2c_client *client; | ||
143 | struct power_supply power_supply; | ||
144 | struct sbs_platform_data *pdata; | ||
145 | bool is_present; | ||
146 | bool gpio_detect; | ||
147 | bool enable_detection; | ||
148 | int irq; | ||
149 | int last_state; | ||
150 | int poll_time; | ||
151 | struct delayed_work work; | ||
152 | int ignore_changes; | ||
153 | }; | ||
154 | |||
155 | static int sbs_read_word_data(struct i2c_client *client, u8 address) | ||
156 | { | ||
157 | struct sbs_info *chip = i2c_get_clientdata(client); | ||
158 | s32 ret = 0; | ||
159 | int retries = 1; | ||
160 | |||
161 | if (chip->pdata) | ||
162 | retries = max(chip->pdata->i2c_retry_count + 1, 1); | ||
163 | |||
164 | while (retries > 0) { | ||
165 | ret = i2c_smbus_read_word_data(client, address); | ||
166 | if (ret >= 0) | ||
167 | break; | ||
168 | retries--; | ||
169 | } | ||
170 | |||
171 | if (ret < 0) { | ||
172 | dev_dbg(&client->dev, | ||
173 | "%s: i2c read at address 0x%x failed\n", | ||
174 | __func__, address); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | return le16_to_cpu(ret); | ||
179 | } | ||
180 | |||
181 | static int sbs_write_word_data(struct i2c_client *client, u8 address, | ||
182 | u16 value) | ||
183 | { | ||
184 | struct sbs_info *chip = i2c_get_clientdata(client); | ||
185 | s32 ret = 0; | ||
186 | int retries = 1; | ||
187 | |||
188 | if (chip->pdata) | ||
189 | retries = max(chip->pdata->i2c_retry_count + 1, 1); | ||
190 | |||
191 | while (retries > 0) { | ||
192 | ret = i2c_smbus_write_word_data(client, address, | ||
193 | le16_to_cpu(value)); | ||
194 | if (ret >= 0) | ||
195 | break; | ||
196 | retries--; | ||
197 | } | ||
198 | |||
199 | if (ret < 0) { | ||
200 | dev_dbg(&client->dev, | ||
201 | "%s: i2c write to address 0x%x failed\n", | ||
202 | __func__, address); | ||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int sbs_get_battery_presence_and_health( | ||
210 | struct i2c_client *client, enum power_supply_property psp, | ||
211 | union power_supply_propval *val) | ||
212 | { | ||
213 | s32 ret; | ||
214 | struct sbs_info *chip = i2c_get_clientdata(client); | ||
215 | |||
216 | if (psp == POWER_SUPPLY_PROP_PRESENT && | ||
217 | chip->gpio_detect) { | ||
218 | ret = gpio_get_value(chip->pdata->battery_detect); | ||
219 | if (ret == chip->pdata->battery_detect_present) | ||
220 | val->intval = 1; | ||
221 | else | ||
222 | val->intval = 0; | ||
223 | chip->is_present = val->intval; | ||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | /* Write to ManufacturerAccess with | ||
228 | * ManufacturerAccess command and then | ||
229 | * read the status */ | ||
230 | ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr, | ||
231 | MANUFACTURER_ACCESS_STATUS); | ||
232 | if (ret < 0) { | ||
233 | if (psp == POWER_SUPPLY_PROP_PRESENT) | ||
234 | val->intval = 0; /* battery removed */ | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | ret = sbs_read_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr); | ||
239 | if (ret < 0) | ||
240 | return ret; | ||
241 | |||
242 | if (ret < sbs_data[REG_MANUFACTURER_DATA].min_value || | ||
243 | ret > sbs_data[REG_MANUFACTURER_DATA].max_value) { | ||
244 | val->intval = 0; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | /* Mask the upper nibble of 2nd byte and | ||
249 | * lower byte of response then | ||
250 | * shift the result by 8 to get status*/ | ||
251 | ret &= 0x0F00; | ||
252 | ret >>= 8; | ||
253 | if (psp == POWER_SUPPLY_PROP_PRESENT) { | ||
254 | if (ret == 0x0F) | ||
255 | /* battery removed */ | ||
256 | val->intval = 0; | ||
257 | else | ||
258 | val->intval = 1; | ||
259 | } else if (psp == POWER_SUPPLY_PROP_HEALTH) { | ||
260 | if (ret == 0x09) | ||
261 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
262 | else if (ret == 0x0B) | ||
263 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
264 | else if (ret == 0x0C) | ||
265 | val->intval = POWER_SUPPLY_HEALTH_DEAD; | ||
266 | else | ||
267 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
268 | } | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int sbs_get_battery_property(struct i2c_client *client, | ||
274 | int reg_offset, enum power_supply_property psp, | ||
275 | union power_supply_propval *val) | ||
276 | { | ||
277 | struct sbs_info *chip = i2c_get_clientdata(client); | ||
278 | s32 ret; | ||
279 | |||
280 | ret = sbs_read_word_data(client, sbs_data[reg_offset].addr); | ||
281 | if (ret < 0) | ||
282 | return ret; | ||
283 | |||
284 | /* returned values are 16 bit */ | ||
285 | if (sbs_data[reg_offset].min_value < 0) | ||
286 | ret = (s16)ret; | ||
287 | |||
288 | if (ret >= sbs_data[reg_offset].min_value && | ||
289 | ret <= sbs_data[reg_offset].max_value) { | ||
290 | val->intval = ret; | ||
291 | if (psp != POWER_SUPPLY_PROP_STATUS) | ||
292 | return 0; | ||
293 | |||
294 | if (ret & BATTERY_FULL_CHARGED) | ||
295 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
296 | else if (ret & BATTERY_FULL_DISCHARGED) | ||
297 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
298 | else if (ret & BATTERY_DISCHARGING) | ||
299 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
300 | else | ||
301 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
302 | |||
303 | if (chip->poll_time == 0) | ||
304 | chip->last_state = val->intval; | ||
305 | else if (chip->last_state != val->intval) { | ||
306 | cancel_delayed_work_sync(&chip->work); | ||
307 | power_supply_changed(&chip->power_supply); | ||
308 | chip->poll_time = 0; | ||
309 | } | ||
310 | } else { | ||
311 | if (psp == POWER_SUPPLY_PROP_STATUS) | ||
312 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
313 | else | ||
314 | val->intval = 0; | ||
315 | } | ||
316 | |||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static void sbs_unit_adjustment(struct i2c_client *client, | ||
321 | enum power_supply_property psp, union power_supply_propval *val) | ||
322 | { | ||
323 | #define BASE_UNIT_CONVERSION 1000 | ||
324 | #define BATTERY_MODE_CAP_MULT_WATT (10 * BASE_UNIT_CONVERSION) | ||
325 | #define TIME_UNIT_CONVERSION 60 | ||
326 | #define TEMP_KELVIN_TO_CELSIUS 2731 | ||
327 | switch (psp) { | ||
328 | case POWER_SUPPLY_PROP_ENERGY_NOW: | ||
329 | case POWER_SUPPLY_PROP_ENERGY_FULL: | ||
330 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: | ||
331 | /* sbs provides energy in units of 10mWh. | ||
332 | * Convert to µWh | ||
333 | */ | ||
334 | val->intval *= BATTERY_MODE_CAP_MULT_WATT; | ||
335 | break; | ||
336 | |||
337 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
338 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
339 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
340 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
341 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
342 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
343 | val->intval *= BASE_UNIT_CONVERSION; | ||
344 | break; | ||
345 | |||
346 | case POWER_SUPPLY_PROP_TEMP: | ||
347 | /* sbs provides battery temperature in 0.1K | ||
348 | * so convert it to 0.1°C | ||
349 | */ | ||
350 | val->intval -= TEMP_KELVIN_TO_CELSIUS; | ||
351 | break; | ||
352 | |||
353 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: | ||
354 | case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: | ||
355 | /* sbs provides time to empty and time to full in minutes. | ||
356 | * Convert to seconds | ||
357 | */ | ||
358 | val->intval *= TIME_UNIT_CONVERSION; | ||
359 | break; | ||
360 | |||
361 | default: | ||
362 | dev_dbg(&client->dev, | ||
363 | "%s: no need for unit conversion %d\n", __func__, psp); | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static enum sbs_battery_mode sbs_set_battery_mode(struct i2c_client *client, | ||
368 | enum sbs_battery_mode mode) | ||
369 | { | ||
370 | int ret, original_val; | ||
371 | |||
372 | original_val = sbs_read_word_data(client, BATTERY_MODE_OFFSET); | ||
373 | if (original_val < 0) | ||
374 | return original_val; | ||
375 | |||
376 | if ((original_val & BATTERY_MODE_MASK) == mode) | ||
377 | return mode; | ||
378 | |||
379 | if (mode == BATTERY_MODE_AMPS) | ||
380 | ret = original_val & ~BATTERY_MODE_MASK; | ||
381 | else | ||
382 | ret = original_val | BATTERY_MODE_MASK; | ||
383 | |||
384 | ret = sbs_write_word_data(client, BATTERY_MODE_OFFSET, ret); | ||
385 | if (ret < 0) | ||
386 | return ret; | ||
387 | |||
388 | return original_val & BATTERY_MODE_MASK; | ||
389 | } | ||
390 | |||
391 | static int sbs_get_battery_capacity(struct i2c_client *client, | ||
392 | int reg_offset, enum power_supply_property psp, | ||
393 | union power_supply_propval *val) | ||
394 | { | ||
395 | s32 ret; | ||
396 | enum sbs_battery_mode mode = BATTERY_MODE_WATTS; | ||
397 | |||
398 | if (power_supply_is_amp_property(psp)) | ||
399 | mode = BATTERY_MODE_AMPS; | ||
400 | |||
401 | mode = sbs_set_battery_mode(client, mode); | ||
402 | if (mode < 0) | ||
403 | return mode; | ||
404 | |||
405 | ret = sbs_read_word_data(client, sbs_data[reg_offset].addr); | ||
406 | if (ret < 0) | ||
407 | return ret; | ||
408 | |||
409 | if (psp == POWER_SUPPLY_PROP_CAPACITY) { | ||
410 | /* sbs spec says that this can be >100 % | ||
411 | * even if max value is 100 % */ | ||
412 | val->intval = min(ret, 100); | ||
413 | } else | ||
414 | val->intval = ret; | ||
415 | |||
416 | ret = sbs_set_battery_mode(client, mode); | ||
417 | if (ret < 0) | ||
418 | return ret; | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static char sbs_serial[5]; | ||
424 | static int sbs_get_battery_serial_number(struct i2c_client *client, | ||
425 | union power_supply_propval *val) | ||
426 | { | ||
427 | int ret; | ||
428 | |||
429 | ret = sbs_read_word_data(client, sbs_data[REG_SERIAL_NUMBER].addr); | ||
430 | if (ret < 0) | ||
431 | return ret; | ||
432 | |||
433 | ret = sprintf(sbs_serial, "%04x", ret); | ||
434 | val->strval = sbs_serial; | ||
435 | |||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static int sbs_get_property_index(struct i2c_client *client, | ||
440 | enum power_supply_property psp) | ||
441 | { | ||
442 | int count; | ||
443 | for (count = 0; count < ARRAY_SIZE(sbs_data); count++) | ||
444 | if (psp == sbs_data[count].psp) | ||
445 | return count; | ||
446 | |||
447 | dev_warn(&client->dev, | ||
448 | "%s: Invalid Property - %d\n", __func__, psp); | ||
449 | |||
450 | return -EINVAL; | ||
451 | } | ||
452 | |||
453 | static int sbs_get_property(struct power_supply *psy, | ||
454 | enum power_supply_property psp, | ||
455 | union power_supply_propval *val) | ||
456 | { | ||
457 | int ret = 0; | ||
458 | struct sbs_info *chip = container_of(psy, | ||
459 | struct sbs_info, power_supply); | ||
460 | struct i2c_client *client = chip->client; | ||
461 | |||
462 | switch (psp) { | ||
463 | case POWER_SUPPLY_PROP_PRESENT: | ||
464 | case POWER_SUPPLY_PROP_HEALTH: | ||
465 | ret = sbs_get_battery_presence_and_health(client, psp, val); | ||
466 | if (psp == POWER_SUPPLY_PROP_PRESENT) | ||
467 | return 0; | ||
468 | break; | ||
469 | |||
470 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
471 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | ||
472 | goto done; /* don't trigger power_supply_changed()! */ | ||
473 | |||
474 | case POWER_SUPPLY_PROP_ENERGY_NOW: | ||
475 | case POWER_SUPPLY_PROP_ENERGY_FULL: | ||
476 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: | ||
477 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
478 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
479 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
480 | case POWER_SUPPLY_PROP_CAPACITY: | ||
481 | ret = sbs_get_property_index(client, psp); | ||
482 | if (ret < 0) | ||
483 | break; | ||
484 | |||
485 | ret = sbs_get_battery_capacity(client, ret, psp, val); | ||
486 | break; | ||
487 | |||
488 | case POWER_SUPPLY_PROP_SERIAL_NUMBER: | ||
489 | ret = sbs_get_battery_serial_number(client, val); | ||
490 | break; | ||
491 | |||
492 | case POWER_SUPPLY_PROP_STATUS: | ||
493 | case POWER_SUPPLY_PROP_CYCLE_COUNT: | ||
494 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
495 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
496 | case POWER_SUPPLY_PROP_TEMP: | ||
497 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: | ||
498 | case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: | ||
499 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
500 | ret = sbs_get_property_index(client, psp); | ||
501 | if (ret < 0) | ||
502 | break; | ||
503 | |||
504 | ret = sbs_get_battery_property(client, ret, psp, val); | ||
505 | break; | ||
506 | |||
507 | default: | ||
508 | dev_err(&client->dev, | ||
509 | "%s: INVALID property\n", __func__); | ||
510 | return -EINVAL; | ||
511 | } | ||
512 | |||
513 | if (!chip->enable_detection) | ||
514 | goto done; | ||
515 | |||
516 | if (!chip->gpio_detect && | ||
517 | chip->is_present != (ret >= 0)) { | ||
518 | chip->is_present = (ret >= 0); | ||
519 | power_supply_changed(&chip->power_supply); | ||
520 | } | ||
521 | |||
522 | done: | ||
523 | if (!ret) { | ||
524 | /* Convert units to match requirements for power supply class */ | ||
525 | sbs_unit_adjustment(client, psp, val); | ||
526 | } | ||
527 | |||
528 | dev_dbg(&client->dev, | ||
529 | "%s: property = %d, value = %x\n", __func__, psp, val->intval); | ||
530 | |||
531 | if (ret && chip->is_present) | ||
532 | return ret; | ||
533 | |||
534 | /* battery not present, so return NODATA for properties */ | ||
535 | if (ret) | ||
536 | return -ENODATA; | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | static irqreturn_t sbs_irq(int irq, void *devid) | ||
542 | { | ||
543 | struct power_supply *battery = devid; | ||
544 | |||
545 | power_supply_changed(battery); | ||
546 | |||
547 | return IRQ_HANDLED; | ||
548 | } | ||
549 | |||
550 | static void sbs_external_power_changed(struct power_supply *psy) | ||
551 | { | ||
552 | struct sbs_info *chip; | ||
553 | |||
554 | chip = container_of(psy, struct sbs_info, power_supply); | ||
555 | |||
556 | if (chip->ignore_changes > 0) { | ||
557 | chip->ignore_changes--; | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | /* cancel outstanding work */ | ||
562 | cancel_delayed_work_sync(&chip->work); | ||
563 | |||
564 | schedule_delayed_work(&chip->work, HZ); | ||
565 | chip->poll_time = chip->pdata->poll_retry_count; | ||
566 | } | ||
567 | |||
568 | static void sbs_delayed_work(struct work_struct *work) | ||
569 | { | ||
570 | struct sbs_info *chip; | ||
571 | s32 ret; | ||
572 | |||
573 | chip = container_of(work, struct sbs_info, work.work); | ||
574 | |||
575 | ret = sbs_read_word_data(chip->client, sbs_data[REG_STATUS].addr); | ||
576 | /* if the read failed, give up on this work */ | ||
577 | if (ret < 0) { | ||
578 | chip->poll_time = 0; | ||
579 | return; | ||
580 | } | ||
581 | |||
582 | if (ret & BATTERY_FULL_CHARGED) | ||
583 | ret = POWER_SUPPLY_STATUS_FULL; | ||
584 | else if (ret & BATTERY_FULL_DISCHARGED) | ||
585 | ret = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
586 | else if (ret & BATTERY_DISCHARGING) | ||
587 | ret = POWER_SUPPLY_STATUS_DISCHARGING; | ||
588 | else | ||
589 | ret = POWER_SUPPLY_STATUS_CHARGING; | ||
590 | |||
591 | if (chip->last_state != ret) { | ||
592 | chip->poll_time = 0; | ||
593 | power_supply_changed(&chip->power_supply); | ||
594 | return; | ||
595 | } | ||
596 | if (chip->poll_time > 0) { | ||
597 | schedule_delayed_work(&chip->work, HZ); | ||
598 | chip->poll_time--; | ||
599 | return; | ||
600 | } | ||
601 | } | ||
602 | |||
603 | #if defined(CONFIG_OF) | ||
604 | |||
605 | #include <linux/of_device.h> | ||
606 | #include <linux/of_gpio.h> | ||
607 | |||
608 | static const struct of_device_id sbs_dt_ids[] = { | ||
609 | { .compatible = "sbs,sbs-battery" }, | ||
610 | { .compatible = "ti,bq20z75" }, | ||
611 | { } | ||
612 | }; | ||
613 | MODULE_DEVICE_TABLE(of, sbs_dt_ids); | ||
614 | |||
615 | static struct sbs_platform_data *sbs_of_populate_pdata( | ||
616 | struct i2c_client *client) | ||
617 | { | ||
618 | struct device_node *of_node = client->dev.of_node; | ||
619 | struct sbs_platform_data *pdata = client->dev.platform_data; | ||
620 | enum of_gpio_flags gpio_flags; | ||
621 | int rc; | ||
622 | u32 prop; | ||
623 | |||
624 | /* verify this driver matches this device */ | ||
625 | if (!of_node) | ||
626 | return NULL; | ||
627 | |||
628 | /* if platform data is set, honor it */ | ||
629 | if (pdata) | ||
630 | return pdata; | ||
631 | |||
632 | /* first make sure at least one property is set, otherwise | ||
633 | * it won't change behavior from running without pdata. | ||
634 | */ | ||
635 | if (!of_get_property(of_node, "sbs,i2c-retry-count", NULL) && | ||
636 | !of_get_property(of_node, "sbs,poll-retry-count", NULL) && | ||
637 | !of_get_property(of_node, "sbs,battery-detect-gpios", NULL)) | ||
638 | goto of_out; | ||
639 | |||
640 | pdata = devm_kzalloc(&client->dev, sizeof(struct sbs_platform_data), | ||
641 | GFP_KERNEL); | ||
642 | if (!pdata) | ||
643 | goto of_out; | ||
644 | |||
645 | rc = of_property_read_u32(of_node, "sbs,i2c-retry-count", &prop); | ||
646 | if (!rc) | ||
647 | pdata->i2c_retry_count = prop; | ||
648 | |||
649 | rc = of_property_read_u32(of_node, "sbs,poll-retry-count", &prop); | ||
650 | if (!rc) | ||
651 | pdata->poll_retry_count = prop; | ||
652 | |||
653 | if (!of_get_property(of_node, "sbs,battery-detect-gpios", NULL)) { | ||
654 | pdata->battery_detect = -1; | ||
655 | goto of_out; | ||
656 | } | ||
657 | |||
658 | pdata->battery_detect = of_get_named_gpio_flags(of_node, | ||
659 | "sbs,battery-detect-gpios", 0, &gpio_flags); | ||
660 | |||
661 | if (gpio_flags & OF_GPIO_ACTIVE_LOW) | ||
662 | pdata->battery_detect_present = 0; | ||
663 | else | ||
664 | pdata->battery_detect_present = 1; | ||
665 | |||
666 | of_out: | ||
667 | return pdata; | ||
668 | } | ||
669 | #else | ||
670 | #define sbs_dt_ids NULL | ||
671 | static struct sbs_platform_data *sbs_of_populate_pdata( | ||
672 | struct i2c_client *client) | ||
673 | { | ||
674 | return client->dev.platform_data; | ||
675 | } | ||
676 | #endif | ||
677 | |||
678 | static int sbs_probe(struct i2c_client *client, | ||
679 | const struct i2c_device_id *id) | ||
680 | { | ||
681 | struct sbs_info *chip; | ||
682 | struct sbs_platform_data *pdata = client->dev.platform_data; | ||
683 | int rc; | ||
684 | int irq; | ||
685 | char *name; | ||
686 | |||
687 | name = kasprintf(GFP_KERNEL, "sbs-%s", dev_name(&client->dev)); | ||
688 | if (!name) { | ||
689 | dev_err(&client->dev, "Failed to allocate device name\n"); | ||
690 | return -ENOMEM; | ||
691 | } | ||
692 | |||
693 | chip = kzalloc(sizeof(struct sbs_info), GFP_KERNEL); | ||
694 | if (!chip) { | ||
695 | rc = -ENOMEM; | ||
696 | goto exit_free_name; | ||
697 | } | ||
698 | |||
699 | chip->client = client; | ||
700 | chip->enable_detection = false; | ||
701 | chip->gpio_detect = false; | ||
702 | chip->power_supply.name = name; | ||
703 | chip->power_supply.type = POWER_SUPPLY_TYPE_BATTERY; | ||
704 | chip->power_supply.properties = sbs_properties; | ||
705 | chip->power_supply.num_properties = ARRAY_SIZE(sbs_properties); | ||
706 | chip->power_supply.get_property = sbs_get_property; | ||
707 | /* ignore first notification of external change, it is generated | ||
708 | * from the power_supply_register call back | ||
709 | */ | ||
710 | chip->ignore_changes = 1; | ||
711 | chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN; | ||
712 | chip->power_supply.external_power_changed = sbs_external_power_changed; | ||
713 | |||
714 | pdata = sbs_of_populate_pdata(client); | ||
715 | |||
716 | if (pdata) { | ||
717 | chip->gpio_detect = gpio_is_valid(pdata->battery_detect); | ||
718 | chip->pdata = pdata; | ||
719 | } | ||
720 | |||
721 | i2c_set_clientdata(client, chip); | ||
722 | |||
723 | if (!chip->gpio_detect) | ||
724 | goto skip_gpio; | ||
725 | |||
726 | rc = gpio_request(pdata->battery_detect, dev_name(&client->dev)); | ||
727 | if (rc) { | ||
728 | dev_warn(&client->dev, "Failed to request gpio: %d\n", rc); | ||
729 | chip->gpio_detect = false; | ||
730 | goto skip_gpio; | ||
731 | } | ||
732 | |||
733 | rc = gpio_direction_input(pdata->battery_detect); | ||
734 | if (rc) { | ||
735 | dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc); | ||
736 | gpio_free(pdata->battery_detect); | ||
737 | chip->gpio_detect = false; | ||
738 | goto skip_gpio; | ||
739 | } | ||
740 | |||
741 | irq = gpio_to_irq(pdata->battery_detect); | ||
742 | if (irq <= 0) { | ||
743 | dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq); | ||
744 | gpio_free(pdata->battery_detect); | ||
745 | chip->gpio_detect = false; | ||
746 | goto skip_gpio; | ||
747 | } | ||
748 | |||
749 | rc = request_irq(irq, sbs_irq, | ||
750 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
751 | dev_name(&client->dev), &chip->power_supply); | ||
752 | if (rc) { | ||
753 | dev_warn(&client->dev, "Failed to request irq: %d\n", rc); | ||
754 | gpio_free(pdata->battery_detect); | ||
755 | chip->gpio_detect = false; | ||
756 | goto skip_gpio; | ||
757 | } | ||
758 | |||
759 | chip->irq = irq; | ||
760 | |||
761 | skip_gpio: | ||
762 | /* | ||
763 | * Before we register, we need to make sure we can actually talk | ||
764 | * to the battery. | ||
765 | */ | ||
766 | rc = sbs_read_word_data(client, sbs_data[REG_STATUS].addr); | ||
767 | if (rc < 0) { | ||
768 | dev_err(&client->dev, "%s: Failed to get device status\n", | ||
769 | __func__); | ||
770 | goto exit_psupply; | ||
771 | } | ||
772 | |||
773 | rc = power_supply_register(&client->dev, &chip->power_supply); | ||
774 | if (rc) { | ||
775 | dev_err(&client->dev, | ||
776 | "%s: Failed to register power supply\n", __func__); | ||
777 | goto exit_psupply; | ||
778 | } | ||
779 | |||
780 | dev_info(&client->dev, | ||
781 | "%s: battery gas gauge device registered\n", client->name); | ||
782 | |||
783 | INIT_DELAYED_WORK(&chip->work, sbs_delayed_work); | ||
784 | |||
785 | chip->enable_detection = true; | ||
786 | |||
787 | return 0; | ||
788 | |||
789 | exit_psupply: | ||
790 | if (chip->irq) | ||
791 | free_irq(chip->irq, &chip->power_supply); | ||
792 | if (chip->gpio_detect) | ||
793 | gpio_free(pdata->battery_detect); | ||
794 | |||
795 | kfree(chip); | ||
796 | |||
797 | exit_free_name: | ||
798 | kfree(name); | ||
799 | |||
800 | return rc; | ||
801 | } | ||
802 | |||
803 | static int sbs_remove(struct i2c_client *client) | ||
804 | { | ||
805 | struct sbs_info *chip = i2c_get_clientdata(client); | ||
806 | |||
807 | if (chip->irq) | ||
808 | free_irq(chip->irq, &chip->power_supply); | ||
809 | if (chip->gpio_detect) | ||
810 | gpio_free(chip->pdata->battery_detect); | ||
811 | |||
812 | power_supply_unregister(&chip->power_supply); | ||
813 | |||
814 | cancel_delayed_work_sync(&chip->work); | ||
815 | |||
816 | kfree(chip->power_supply.name); | ||
817 | kfree(chip); | ||
818 | chip = NULL; | ||
819 | |||
820 | return 0; | ||
821 | } | ||
822 | |||
823 | #if defined CONFIG_PM | ||
824 | static int sbs_suspend(struct i2c_client *client, | ||
825 | pm_message_t state) | ||
826 | { | ||
827 | struct sbs_info *chip = i2c_get_clientdata(client); | ||
828 | s32 ret; | ||
829 | |||
830 | if (chip->poll_time > 0) | ||
831 | cancel_delayed_work_sync(&chip->work); | ||
832 | |||
833 | /* write to manufacturer access with sleep command */ | ||
834 | ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr, | ||
835 | MANUFACTURER_ACCESS_SLEEP); | ||
836 | if (chip->is_present && ret < 0) | ||
837 | return ret; | ||
838 | |||
839 | return 0; | ||
840 | } | ||
841 | #else | ||
842 | #define sbs_suspend NULL | ||
843 | #endif | ||
844 | /* any smbus transaction will wake up sbs */ | ||
845 | #define sbs_resume NULL | ||
846 | |||
847 | static const struct i2c_device_id sbs_id[] = { | ||
848 | { "bq20z75", 0 }, | ||
849 | { "sbs-battery", 1 }, | ||
850 | {} | ||
851 | }; | ||
852 | MODULE_DEVICE_TABLE(i2c, sbs_id); | ||
853 | |||
854 | static struct i2c_driver sbs_battery_driver = { | ||
855 | .probe = sbs_probe, | ||
856 | .remove = sbs_remove, | ||
857 | .suspend = sbs_suspend, | ||
858 | .resume = sbs_resume, | ||
859 | .id_table = sbs_id, | ||
860 | .driver = { | ||
861 | .name = "sbs-battery", | ||
862 | .of_match_table = sbs_dt_ids, | ||
863 | }, | ||
864 | }; | ||
865 | module_i2c_driver(sbs_battery_driver); | ||
866 | |||
867 | MODULE_DESCRIPTION("SBS battery monitor driver"); | ||
868 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c deleted file mode 100644 index acf84e80fe9..00000000000 --- a/drivers/power/smb347-charger.c +++ /dev/null | |||
@@ -1,1326 +0,0 @@ | |||
1 | /* | ||
2 | * Summit Microelectronics SMB347 Battery Charger Driver | ||
3 | * | ||
4 | * Copyright (C) 2011, Intel Corporation | ||
5 | * | ||
6 | * Authors: Bruce E. Robertson <bruce.e.robertson@intel.com> | ||
7 | * Mika Westerberg <mika.westerberg@linux.intel.com> | ||
8 | * | ||
9 | * This program 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 | |||
14 | #include <linux/err.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/mutex.h> | ||
22 | #include <linux/power_supply.h> | ||
23 | #include <linux/power/smb347-charger.h> | ||
24 | #include <linux/regmap.h> | ||
25 | |||
26 | /* | ||
27 | * Configuration registers. These are mirrored to volatile RAM and can be | ||
28 | * written once %CMD_A_ALLOW_WRITE is set in %CMD_A register. They will be | ||
29 | * reloaded from non-volatile registers after POR. | ||
30 | */ | ||
31 | #define CFG_CHARGE_CURRENT 0x00 | ||
32 | #define CFG_CHARGE_CURRENT_FCC_MASK 0xe0 | ||
33 | #define CFG_CHARGE_CURRENT_FCC_SHIFT 5 | ||
34 | #define CFG_CHARGE_CURRENT_PCC_MASK 0x18 | ||
35 | #define CFG_CHARGE_CURRENT_PCC_SHIFT 3 | ||
36 | #define CFG_CHARGE_CURRENT_TC_MASK 0x07 | ||
37 | #define CFG_CURRENT_LIMIT 0x01 | ||
38 | #define CFG_CURRENT_LIMIT_DC_MASK 0xf0 | ||
39 | #define CFG_CURRENT_LIMIT_DC_SHIFT 4 | ||
40 | #define CFG_CURRENT_LIMIT_USB_MASK 0x0f | ||
41 | #define CFG_FLOAT_VOLTAGE 0x03 | ||
42 | #define CFG_FLOAT_VOLTAGE_FLOAT_MASK 0x3f | ||
43 | #define CFG_FLOAT_VOLTAGE_THRESHOLD_MASK 0xc0 | ||
44 | #define CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT 6 | ||
45 | #define CFG_STAT 0x05 | ||
46 | #define CFG_STAT_DISABLED BIT(5) | ||
47 | #define CFG_STAT_ACTIVE_HIGH BIT(7) | ||
48 | #define CFG_PIN 0x06 | ||
49 | #define CFG_PIN_EN_CTRL_MASK 0x60 | ||
50 | #define CFG_PIN_EN_CTRL_ACTIVE_HIGH 0x40 | ||
51 | #define CFG_PIN_EN_CTRL_ACTIVE_LOW 0x60 | ||
52 | #define CFG_PIN_EN_APSD_IRQ BIT(1) | ||
53 | #define CFG_PIN_EN_CHARGER_ERROR BIT(2) | ||
54 | #define CFG_THERM 0x07 | ||
55 | #define CFG_THERM_SOFT_HOT_COMPENSATION_MASK 0x03 | ||
56 | #define CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT 0 | ||
57 | #define CFG_THERM_SOFT_COLD_COMPENSATION_MASK 0x0c | ||
58 | #define CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT 2 | ||
59 | #define CFG_THERM_MONITOR_DISABLED BIT(4) | ||
60 | #define CFG_SYSOK 0x08 | ||
61 | #define CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED BIT(2) | ||
62 | #define CFG_OTHER 0x09 | ||
63 | #define CFG_OTHER_RID_MASK 0xc0 | ||
64 | #define CFG_OTHER_RID_ENABLED_AUTO_OTG 0xc0 | ||
65 | #define CFG_OTG 0x0a | ||
66 | #define CFG_OTG_TEMP_THRESHOLD_MASK 0x30 | ||
67 | #define CFG_OTG_TEMP_THRESHOLD_SHIFT 4 | ||
68 | #define CFG_OTG_CC_COMPENSATION_MASK 0xc0 | ||
69 | #define CFG_OTG_CC_COMPENSATION_SHIFT 6 | ||
70 | #define CFG_TEMP_LIMIT 0x0b | ||
71 | #define CFG_TEMP_LIMIT_SOFT_HOT_MASK 0x03 | ||
72 | #define CFG_TEMP_LIMIT_SOFT_HOT_SHIFT 0 | ||
73 | #define CFG_TEMP_LIMIT_SOFT_COLD_MASK 0x0c | ||
74 | #define CFG_TEMP_LIMIT_SOFT_COLD_SHIFT 2 | ||
75 | #define CFG_TEMP_LIMIT_HARD_HOT_MASK 0x30 | ||
76 | #define CFG_TEMP_LIMIT_HARD_HOT_SHIFT 4 | ||
77 | #define CFG_TEMP_LIMIT_HARD_COLD_MASK 0xc0 | ||
78 | #define CFG_TEMP_LIMIT_HARD_COLD_SHIFT 6 | ||
79 | #define CFG_FAULT_IRQ 0x0c | ||
80 | #define CFG_FAULT_IRQ_DCIN_UV BIT(2) | ||
81 | #define CFG_STATUS_IRQ 0x0d | ||
82 | #define CFG_STATUS_IRQ_TERMINATION_OR_TAPER BIT(4) | ||
83 | #define CFG_STATUS_IRQ_CHARGE_TIMEOUT BIT(7) | ||
84 | #define CFG_ADDRESS 0x0e | ||
85 | |||
86 | /* Command registers */ | ||
87 | #define CMD_A 0x30 | ||
88 | #define CMD_A_CHG_ENABLED BIT(1) | ||
89 | #define CMD_A_SUSPEND_ENABLED BIT(2) | ||
90 | #define CMD_A_ALLOW_WRITE BIT(7) | ||
91 | #define CMD_B 0x31 | ||
92 | #define CMD_C 0x33 | ||
93 | |||
94 | /* Interrupt Status registers */ | ||
95 | #define IRQSTAT_A 0x35 | ||
96 | #define IRQSTAT_C 0x37 | ||
97 | #define IRQSTAT_C_TERMINATION_STAT BIT(0) | ||
98 | #define IRQSTAT_C_TERMINATION_IRQ BIT(1) | ||
99 | #define IRQSTAT_C_TAPER_IRQ BIT(3) | ||
100 | #define IRQSTAT_D 0x38 | ||
101 | #define IRQSTAT_D_CHARGE_TIMEOUT_STAT BIT(2) | ||
102 | #define IRQSTAT_D_CHARGE_TIMEOUT_IRQ BIT(3) | ||
103 | #define IRQSTAT_E 0x39 | ||
104 | #define IRQSTAT_E_USBIN_UV_STAT BIT(0) | ||
105 | #define IRQSTAT_E_USBIN_UV_IRQ BIT(1) | ||
106 | #define IRQSTAT_E_DCIN_UV_STAT BIT(4) | ||
107 | #define IRQSTAT_E_DCIN_UV_IRQ BIT(5) | ||
108 | #define IRQSTAT_F 0x3a | ||
109 | |||
110 | /* Status registers */ | ||
111 | #define STAT_A 0x3b | ||
112 | #define STAT_A_FLOAT_VOLTAGE_MASK 0x3f | ||
113 | #define STAT_B 0x3c | ||
114 | #define STAT_C 0x3d | ||
115 | #define STAT_C_CHG_ENABLED BIT(0) | ||
116 | #define STAT_C_HOLDOFF_STAT BIT(3) | ||
117 | #define STAT_C_CHG_MASK 0x06 | ||
118 | #define STAT_C_CHG_SHIFT 1 | ||
119 | #define STAT_C_CHG_TERM BIT(5) | ||
120 | #define STAT_C_CHARGER_ERROR BIT(6) | ||
121 | #define STAT_E 0x3f | ||
122 | |||
123 | #define SMB347_MAX_REGISTER 0x3f | ||
124 | |||
125 | /** | ||
126 | * struct smb347_charger - smb347 charger instance | ||
127 | * @lock: protects concurrent access to online variables | ||
128 | * @dev: pointer to device | ||
129 | * @regmap: pointer to driver regmap | ||
130 | * @mains: power_supply instance for AC/DC power | ||
131 | * @usb: power_supply instance for USB power | ||
132 | * @battery: power_supply instance for battery | ||
133 | * @mains_online: is AC/DC input connected | ||
134 | * @usb_online: is USB input connected | ||
135 | * @charging_enabled: is charging enabled | ||
136 | * @pdata: pointer to platform data | ||
137 | */ | ||
138 | struct smb347_charger { | ||
139 | struct mutex lock; | ||
140 | struct device *dev; | ||
141 | struct regmap *regmap; | ||
142 | struct power_supply mains; | ||
143 | struct power_supply usb; | ||
144 | struct power_supply battery; | ||
145 | bool mains_online; | ||
146 | bool usb_online; | ||
147 | bool charging_enabled; | ||
148 | const struct smb347_charger_platform_data *pdata; | ||
149 | }; | ||
150 | |||
151 | /* Fast charge current in uA */ | ||
152 | static const unsigned int fcc_tbl[] = { | ||
153 | 700000, | ||
154 | 900000, | ||
155 | 1200000, | ||
156 | 1500000, | ||
157 | 1800000, | ||
158 | 2000000, | ||
159 | 2200000, | ||
160 | 2500000, | ||
161 | }; | ||
162 | |||
163 | /* Pre-charge current in uA */ | ||
164 | static const unsigned int pcc_tbl[] = { | ||
165 | 100000, | ||
166 | 150000, | ||
167 | 200000, | ||
168 | 250000, | ||
169 | }; | ||
170 | |||
171 | /* Termination current in uA */ | ||
172 | static const unsigned int tc_tbl[] = { | ||
173 | 37500, | ||
174 | 50000, | ||
175 | 100000, | ||
176 | 150000, | ||
177 | 200000, | ||
178 | 250000, | ||
179 | 500000, | ||
180 | 600000, | ||
181 | }; | ||
182 | |||
183 | /* Input current limit in uA */ | ||
184 | static const unsigned int icl_tbl[] = { | ||
185 | 300000, | ||
186 | 500000, | ||
187 | 700000, | ||
188 | 900000, | ||
189 | 1200000, | ||
190 | 1500000, | ||
191 | 1800000, | ||
192 | 2000000, | ||
193 | 2200000, | ||
194 | 2500000, | ||
195 | }; | ||
196 | |||
197 | /* Charge current compensation in uA */ | ||
198 | static const unsigned int ccc_tbl[] = { | ||
199 | 250000, | ||
200 | 700000, | ||
201 | 900000, | ||
202 | 1200000, | ||
203 | }; | ||
204 | |||
205 | /* Convert register value to current using lookup table */ | ||
206 | static int hw_to_current(const unsigned int *tbl, size_t size, unsigned int val) | ||
207 | { | ||
208 | if (val >= size) | ||
209 | return -EINVAL; | ||
210 | return tbl[val]; | ||
211 | } | ||
212 | |||
213 | /* Convert current to register value using lookup table */ | ||
214 | static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val) | ||
215 | { | ||
216 | size_t i; | ||
217 | |||
218 | for (i = 0; i < size; i++) | ||
219 | if (val < tbl[i]) | ||
220 | break; | ||
221 | return i > 0 ? i - 1 : -EINVAL; | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * smb347_update_ps_status - refreshes the power source status | ||
226 | * @smb: pointer to smb347 charger instance | ||
227 | * | ||
228 | * Function checks whether any power source is connected to the charger and | ||
229 | * updates internal state accordingly. If there is a change to previous state | ||
230 | * function returns %1, otherwise %0 and negative errno in case of errror. | ||
231 | */ | ||
232 | static int smb347_update_ps_status(struct smb347_charger *smb) | ||
233 | { | ||
234 | bool usb = false; | ||
235 | bool dc = false; | ||
236 | unsigned int val; | ||
237 | int ret; | ||
238 | |||
239 | ret = regmap_read(smb->regmap, IRQSTAT_E, &val); | ||
240 | if (ret < 0) | ||
241 | return ret; | ||
242 | |||
243 | /* | ||
244 | * Dc and usb are set depending on whether they are enabled in | ||
245 | * platform data _and_ whether corresponding undervoltage is set. | ||
246 | */ | ||
247 | if (smb->pdata->use_mains) | ||
248 | dc = !(val & IRQSTAT_E_DCIN_UV_STAT); | ||
249 | if (smb->pdata->use_usb) | ||
250 | usb = !(val & IRQSTAT_E_USBIN_UV_STAT); | ||
251 | |||
252 | mutex_lock(&smb->lock); | ||
253 | ret = smb->mains_online != dc || smb->usb_online != usb; | ||
254 | smb->mains_online = dc; | ||
255 | smb->usb_online = usb; | ||
256 | mutex_unlock(&smb->lock); | ||
257 | |||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * smb347_is_ps_online - returns whether input power source is connected | ||
263 | * @smb: pointer to smb347 charger instance | ||
264 | * | ||
265 | * Returns %true if input power source is connected. Note that this is | ||
266 | * dependent on what platform has configured for usable power sources. For | ||
267 | * example if USB is disabled, this will return %false even if the USB cable | ||
268 | * is connected. | ||
269 | */ | ||
270 | static bool smb347_is_ps_online(struct smb347_charger *smb) | ||
271 | { | ||
272 | bool ret; | ||
273 | |||
274 | mutex_lock(&smb->lock); | ||
275 | ret = smb->usb_online || smb->mains_online; | ||
276 | mutex_unlock(&smb->lock); | ||
277 | |||
278 | return ret; | ||
279 | } | ||
280 | |||
281 | /** | ||
282 | * smb347_charging_status - returns status of charging | ||
283 | * @smb: pointer to smb347 charger instance | ||
284 | * | ||
285 | * Function returns charging status. %0 means no charging is in progress, | ||
286 | * %1 means pre-charging, %2 fast-charging and %3 taper-charging. | ||
287 | */ | ||
288 | static int smb347_charging_status(struct smb347_charger *smb) | ||
289 | { | ||
290 | unsigned int val; | ||
291 | int ret; | ||
292 | |||
293 | if (!smb347_is_ps_online(smb)) | ||
294 | return 0; | ||
295 | |||
296 | ret = regmap_read(smb->regmap, STAT_C, &val); | ||
297 | if (ret < 0) | ||
298 | return 0; | ||
299 | |||
300 | return (val & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT; | ||
301 | } | ||
302 | |||
303 | static int smb347_charging_set(struct smb347_charger *smb, bool enable) | ||
304 | { | ||
305 | int ret = 0; | ||
306 | |||
307 | if (smb->pdata->enable_control != SMB347_CHG_ENABLE_SW) { | ||
308 | dev_dbg(smb->dev, "charging enable/disable in SW disabled\n"); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | mutex_lock(&smb->lock); | ||
313 | if (smb->charging_enabled != enable) { | ||
314 | ret = regmap_update_bits(smb->regmap, CMD_A, CMD_A_CHG_ENABLED, | ||
315 | enable ? CMD_A_CHG_ENABLED : 0); | ||
316 | if (!ret) | ||
317 | smb->charging_enabled = enable; | ||
318 | } | ||
319 | mutex_unlock(&smb->lock); | ||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | static inline int smb347_charging_enable(struct smb347_charger *smb) | ||
324 | { | ||
325 | return smb347_charging_set(smb, true); | ||
326 | } | ||
327 | |||
328 | static inline int smb347_charging_disable(struct smb347_charger *smb) | ||
329 | { | ||
330 | return smb347_charging_set(smb, false); | ||
331 | } | ||
332 | |||
333 | static int smb347_start_stop_charging(struct smb347_charger *smb) | ||
334 | { | ||
335 | int ret; | ||
336 | |||
337 | /* | ||
338 | * Depending on whether valid power source is connected or not, we | ||
339 | * disable or enable the charging. We do it manually because it | ||
340 | * depends on how the platform has configured the valid inputs. | ||
341 | */ | ||
342 | if (smb347_is_ps_online(smb)) { | ||
343 | ret = smb347_charging_enable(smb); | ||
344 | if (ret < 0) | ||
345 | dev_err(smb->dev, "failed to enable charging\n"); | ||
346 | } else { | ||
347 | ret = smb347_charging_disable(smb); | ||
348 | if (ret < 0) | ||
349 | dev_err(smb->dev, "failed to disable charging\n"); | ||
350 | } | ||
351 | |||
352 | return ret; | ||
353 | } | ||
354 | |||
355 | static int smb347_set_charge_current(struct smb347_charger *smb) | ||
356 | { | ||
357 | int ret; | ||
358 | |||
359 | if (smb->pdata->max_charge_current) { | ||
360 | ret = current_to_hw(fcc_tbl, ARRAY_SIZE(fcc_tbl), | ||
361 | smb->pdata->max_charge_current); | ||
362 | if (ret < 0) | ||
363 | return ret; | ||
364 | |||
365 | ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT, | ||
366 | CFG_CHARGE_CURRENT_FCC_MASK, | ||
367 | ret << CFG_CHARGE_CURRENT_FCC_SHIFT); | ||
368 | if (ret < 0) | ||
369 | return ret; | ||
370 | } | ||
371 | |||
372 | if (smb->pdata->pre_charge_current) { | ||
373 | ret = current_to_hw(pcc_tbl, ARRAY_SIZE(pcc_tbl), | ||
374 | smb->pdata->pre_charge_current); | ||
375 | if (ret < 0) | ||
376 | return ret; | ||
377 | |||
378 | ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT, | ||
379 | CFG_CHARGE_CURRENT_PCC_MASK, | ||
380 | ret << CFG_CHARGE_CURRENT_PCC_SHIFT); | ||
381 | if (ret < 0) | ||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | if (smb->pdata->termination_current) { | ||
386 | ret = current_to_hw(tc_tbl, ARRAY_SIZE(tc_tbl), | ||
387 | smb->pdata->termination_current); | ||
388 | if (ret < 0) | ||
389 | return ret; | ||
390 | |||
391 | ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT, | ||
392 | CFG_CHARGE_CURRENT_TC_MASK, ret); | ||
393 | if (ret < 0) | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static int smb347_set_current_limits(struct smb347_charger *smb) | ||
401 | { | ||
402 | int ret; | ||
403 | |||
404 | if (smb->pdata->mains_current_limit) { | ||
405 | ret = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), | ||
406 | smb->pdata->mains_current_limit); | ||
407 | if (ret < 0) | ||
408 | return ret; | ||
409 | |||
410 | ret = regmap_update_bits(smb->regmap, CFG_CURRENT_LIMIT, | ||
411 | CFG_CURRENT_LIMIT_DC_MASK, | ||
412 | ret << CFG_CURRENT_LIMIT_DC_SHIFT); | ||
413 | if (ret < 0) | ||
414 | return ret; | ||
415 | } | ||
416 | |||
417 | if (smb->pdata->usb_hc_current_limit) { | ||
418 | ret = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), | ||
419 | smb->pdata->usb_hc_current_limit); | ||
420 | if (ret < 0) | ||
421 | return ret; | ||
422 | |||
423 | ret = regmap_update_bits(smb->regmap, CFG_CURRENT_LIMIT, | ||
424 | CFG_CURRENT_LIMIT_USB_MASK, ret); | ||
425 | if (ret < 0) | ||
426 | return ret; | ||
427 | } | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static int smb347_set_voltage_limits(struct smb347_charger *smb) | ||
433 | { | ||
434 | int ret; | ||
435 | |||
436 | if (smb->pdata->pre_to_fast_voltage) { | ||
437 | ret = smb->pdata->pre_to_fast_voltage; | ||
438 | |||
439 | /* uV */ | ||
440 | ret = clamp_val(ret, 2400000, 3000000) - 2400000; | ||
441 | ret /= 200000; | ||
442 | |||
443 | ret = regmap_update_bits(smb->regmap, CFG_FLOAT_VOLTAGE, | ||
444 | CFG_FLOAT_VOLTAGE_THRESHOLD_MASK, | ||
445 | ret << CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT); | ||
446 | if (ret < 0) | ||
447 | return ret; | ||
448 | } | ||
449 | |||
450 | if (smb->pdata->max_charge_voltage) { | ||
451 | ret = smb->pdata->max_charge_voltage; | ||
452 | |||
453 | /* uV */ | ||
454 | ret = clamp_val(ret, 3500000, 4500000) - 3500000; | ||
455 | ret /= 20000; | ||
456 | |||
457 | ret = regmap_update_bits(smb->regmap, CFG_FLOAT_VOLTAGE, | ||
458 | CFG_FLOAT_VOLTAGE_FLOAT_MASK, ret); | ||
459 | if (ret < 0) | ||
460 | return ret; | ||
461 | } | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static int smb347_set_temp_limits(struct smb347_charger *smb) | ||
467 | { | ||
468 | bool enable_therm_monitor = false; | ||
469 | int ret = 0; | ||
470 | int val; | ||
471 | |||
472 | if (smb->pdata->chip_temp_threshold) { | ||
473 | val = smb->pdata->chip_temp_threshold; | ||
474 | |||
475 | /* degree C */ | ||
476 | val = clamp_val(val, 100, 130) - 100; | ||
477 | val /= 10; | ||
478 | |||
479 | ret = regmap_update_bits(smb->regmap, CFG_OTG, | ||
480 | CFG_OTG_TEMP_THRESHOLD_MASK, | ||
481 | val << CFG_OTG_TEMP_THRESHOLD_SHIFT); | ||
482 | if (ret < 0) | ||
483 | return ret; | ||
484 | } | ||
485 | |||
486 | if (smb->pdata->soft_cold_temp_limit != SMB347_TEMP_USE_DEFAULT) { | ||
487 | val = smb->pdata->soft_cold_temp_limit; | ||
488 | |||
489 | val = clamp_val(val, 0, 15); | ||
490 | val /= 5; | ||
491 | /* this goes from higher to lower so invert the value */ | ||
492 | val = ~val & 0x3; | ||
493 | |||
494 | ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, | ||
495 | CFG_TEMP_LIMIT_SOFT_COLD_MASK, | ||
496 | val << CFG_TEMP_LIMIT_SOFT_COLD_SHIFT); | ||
497 | if (ret < 0) | ||
498 | return ret; | ||
499 | |||
500 | enable_therm_monitor = true; | ||
501 | } | ||
502 | |||
503 | if (smb->pdata->soft_hot_temp_limit != SMB347_TEMP_USE_DEFAULT) { | ||
504 | val = smb->pdata->soft_hot_temp_limit; | ||
505 | |||
506 | val = clamp_val(val, 40, 55) - 40; | ||
507 | val /= 5; | ||
508 | |||
509 | ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, | ||
510 | CFG_TEMP_LIMIT_SOFT_HOT_MASK, | ||
511 | val << CFG_TEMP_LIMIT_SOFT_HOT_SHIFT); | ||
512 | if (ret < 0) | ||
513 | return ret; | ||
514 | |||
515 | enable_therm_monitor = true; | ||
516 | } | ||
517 | |||
518 | if (smb->pdata->hard_cold_temp_limit != SMB347_TEMP_USE_DEFAULT) { | ||
519 | val = smb->pdata->hard_cold_temp_limit; | ||
520 | |||
521 | val = clamp_val(val, -5, 10) + 5; | ||
522 | val /= 5; | ||
523 | /* this goes from higher to lower so invert the value */ | ||
524 | val = ~val & 0x3; | ||
525 | |||
526 | ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, | ||
527 | CFG_TEMP_LIMIT_HARD_COLD_MASK, | ||
528 | val << CFG_TEMP_LIMIT_HARD_COLD_SHIFT); | ||
529 | if (ret < 0) | ||
530 | return ret; | ||
531 | |||
532 | enable_therm_monitor = true; | ||
533 | } | ||
534 | |||
535 | if (smb->pdata->hard_hot_temp_limit != SMB347_TEMP_USE_DEFAULT) { | ||
536 | val = smb->pdata->hard_hot_temp_limit; | ||
537 | |||
538 | val = clamp_val(val, 50, 65) - 50; | ||
539 | val /= 5; | ||
540 | |||
541 | ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, | ||
542 | CFG_TEMP_LIMIT_HARD_HOT_MASK, | ||
543 | val << CFG_TEMP_LIMIT_HARD_HOT_SHIFT); | ||
544 | if (ret < 0) | ||
545 | return ret; | ||
546 | |||
547 | enable_therm_monitor = true; | ||
548 | } | ||
549 | |||
550 | /* | ||
551 | * If any of the temperature limits are set, we also enable the | ||
552 | * thermistor monitoring. | ||
553 | * | ||
554 | * When soft limits are hit, the device will start to compensate | ||
555 | * current and/or voltage depending on the configuration. | ||
556 | * | ||
557 | * When hard limit is hit, the device will suspend charging | ||
558 | * depending on the configuration. | ||
559 | */ | ||
560 | if (enable_therm_monitor) { | ||
561 | ret = regmap_update_bits(smb->regmap, CFG_THERM, | ||
562 | CFG_THERM_MONITOR_DISABLED, 0); | ||
563 | if (ret < 0) | ||
564 | return ret; | ||
565 | } | ||
566 | |||
567 | if (smb->pdata->suspend_on_hard_temp_limit) { | ||
568 | ret = regmap_update_bits(smb->regmap, CFG_SYSOK, | ||
569 | CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED, 0); | ||
570 | if (ret < 0) | ||
571 | return ret; | ||
572 | } | ||
573 | |||
574 | if (smb->pdata->soft_temp_limit_compensation != | ||
575 | SMB347_SOFT_TEMP_COMPENSATE_DEFAULT) { | ||
576 | val = smb->pdata->soft_temp_limit_compensation & 0x3; | ||
577 | |||
578 | ret = regmap_update_bits(smb->regmap, CFG_THERM, | ||
579 | CFG_THERM_SOFT_HOT_COMPENSATION_MASK, | ||
580 | val << CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT); | ||
581 | if (ret < 0) | ||
582 | return ret; | ||
583 | |||
584 | ret = regmap_update_bits(smb->regmap, CFG_THERM, | ||
585 | CFG_THERM_SOFT_COLD_COMPENSATION_MASK, | ||
586 | val << CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT); | ||
587 | if (ret < 0) | ||
588 | return ret; | ||
589 | } | ||
590 | |||
591 | if (smb->pdata->charge_current_compensation) { | ||
592 | val = current_to_hw(ccc_tbl, ARRAY_SIZE(ccc_tbl), | ||
593 | smb->pdata->charge_current_compensation); | ||
594 | if (val < 0) | ||
595 | return val; | ||
596 | |||
597 | ret = regmap_update_bits(smb->regmap, CFG_OTG, | ||
598 | CFG_OTG_CC_COMPENSATION_MASK, | ||
599 | (val & 0x3) << CFG_OTG_CC_COMPENSATION_SHIFT); | ||
600 | if (ret < 0) | ||
601 | return ret; | ||
602 | } | ||
603 | |||
604 | return ret; | ||
605 | } | ||
606 | |||
607 | /* | ||
608 | * smb347_set_writable - enables/disables writing to non-volatile registers | ||
609 | * @smb: pointer to smb347 charger instance | ||
610 | * | ||
611 | * You can enable/disable writing to the non-volatile configuration | ||
612 | * registers by calling this function. | ||
613 | * | ||
614 | * Returns %0 on success and negative errno in case of failure. | ||
615 | */ | ||
616 | static int smb347_set_writable(struct smb347_charger *smb, bool writable) | ||
617 | { | ||
618 | return regmap_update_bits(smb->regmap, CMD_A, CMD_A_ALLOW_WRITE, | ||
619 | writable ? CMD_A_ALLOW_WRITE : 0); | ||
620 | } | ||
621 | |||
622 | static int smb347_hw_init(struct smb347_charger *smb) | ||
623 | { | ||
624 | unsigned int val; | ||
625 | int ret; | ||
626 | |||
627 | ret = smb347_set_writable(smb, true); | ||
628 | if (ret < 0) | ||
629 | return ret; | ||
630 | |||
631 | /* | ||
632 | * Program the platform specific configuration values to the device | ||
633 | * first. | ||
634 | */ | ||
635 | ret = smb347_set_charge_current(smb); | ||
636 | if (ret < 0) | ||
637 | goto fail; | ||
638 | |||
639 | ret = smb347_set_current_limits(smb); | ||
640 | if (ret < 0) | ||
641 | goto fail; | ||
642 | |||
643 | ret = smb347_set_voltage_limits(smb); | ||
644 | if (ret < 0) | ||
645 | goto fail; | ||
646 | |||
647 | ret = smb347_set_temp_limits(smb); | ||
648 | if (ret < 0) | ||
649 | goto fail; | ||
650 | |||
651 | /* If USB charging is disabled we put the USB in suspend mode */ | ||
652 | if (!smb->pdata->use_usb) { | ||
653 | ret = regmap_update_bits(smb->regmap, CMD_A, | ||
654 | CMD_A_SUSPEND_ENABLED, | ||
655 | CMD_A_SUSPEND_ENABLED); | ||
656 | if (ret < 0) | ||
657 | goto fail; | ||
658 | } | ||
659 | |||
660 | /* | ||
661 | * If configured by platform data, we enable hardware Auto-OTG | ||
662 | * support for driving VBUS. Otherwise we disable it. | ||
663 | */ | ||
664 | ret = regmap_update_bits(smb->regmap, CFG_OTHER, CFG_OTHER_RID_MASK, | ||
665 | smb->pdata->use_usb_otg ? CFG_OTHER_RID_ENABLED_AUTO_OTG : 0); | ||
666 | if (ret < 0) | ||
667 | goto fail; | ||
668 | |||
669 | /* | ||
670 | * Make the charging functionality controllable by a write to the | ||
671 | * command register unless pin control is specified in the platform | ||
672 | * data. | ||
673 | */ | ||
674 | switch (smb->pdata->enable_control) { | ||
675 | case SMB347_CHG_ENABLE_PIN_ACTIVE_LOW: | ||
676 | val = CFG_PIN_EN_CTRL_ACTIVE_LOW; | ||
677 | break; | ||
678 | case SMB347_CHG_ENABLE_PIN_ACTIVE_HIGH: | ||
679 | val = CFG_PIN_EN_CTRL_ACTIVE_HIGH; | ||
680 | break; | ||
681 | default: | ||
682 | val = 0; | ||
683 | break; | ||
684 | } | ||
685 | |||
686 | ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_CTRL_MASK, | ||
687 | val); | ||
688 | if (ret < 0) | ||
689 | goto fail; | ||
690 | |||
691 | /* Disable Automatic Power Source Detection (APSD) interrupt. */ | ||
692 | ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_APSD_IRQ, 0); | ||
693 | if (ret < 0) | ||
694 | goto fail; | ||
695 | |||
696 | ret = smb347_update_ps_status(smb); | ||
697 | if (ret < 0) | ||
698 | goto fail; | ||
699 | |||
700 | ret = smb347_start_stop_charging(smb); | ||
701 | |||
702 | fail: | ||
703 | smb347_set_writable(smb, false); | ||
704 | return ret; | ||
705 | } | ||
706 | |||
707 | static irqreturn_t smb347_interrupt(int irq, void *data) | ||
708 | { | ||
709 | struct smb347_charger *smb = data; | ||
710 | unsigned int stat_c, irqstat_c, irqstat_d, irqstat_e; | ||
711 | bool handled = false; | ||
712 | int ret; | ||
713 | |||
714 | ret = regmap_read(smb->regmap, STAT_C, &stat_c); | ||
715 | if (ret < 0) { | ||
716 | dev_warn(smb->dev, "reading STAT_C failed\n"); | ||
717 | return IRQ_NONE; | ||
718 | } | ||
719 | |||
720 | ret = regmap_read(smb->regmap, IRQSTAT_C, &irqstat_c); | ||
721 | if (ret < 0) { | ||
722 | dev_warn(smb->dev, "reading IRQSTAT_C failed\n"); | ||
723 | return IRQ_NONE; | ||
724 | } | ||
725 | |||
726 | ret = regmap_read(smb->regmap, IRQSTAT_D, &irqstat_d); | ||
727 | if (ret < 0) { | ||
728 | dev_warn(smb->dev, "reading IRQSTAT_D failed\n"); | ||
729 | return IRQ_NONE; | ||
730 | } | ||
731 | |||
732 | ret = regmap_read(smb->regmap, IRQSTAT_E, &irqstat_e); | ||
733 | if (ret < 0) { | ||
734 | dev_warn(smb->dev, "reading IRQSTAT_E failed\n"); | ||
735 | return IRQ_NONE; | ||
736 | } | ||
737 | |||
738 | /* | ||
739 | * If we get charger error we report the error back to user. | ||
740 | * If the error is recovered charging will resume again. | ||
741 | */ | ||
742 | if (stat_c & STAT_C_CHARGER_ERROR) { | ||
743 | dev_err(smb->dev, "charging stopped due to charger error\n"); | ||
744 | power_supply_changed(&smb->battery); | ||
745 | handled = true; | ||
746 | } | ||
747 | |||
748 | /* | ||
749 | * If we reached the termination current the battery is charged and | ||
750 | * we can update the status now. Charging is automatically | ||
751 | * disabled by the hardware. | ||
752 | */ | ||
753 | if (irqstat_c & (IRQSTAT_C_TERMINATION_IRQ | IRQSTAT_C_TAPER_IRQ)) { | ||
754 | if (irqstat_c & IRQSTAT_C_TERMINATION_STAT) | ||
755 | power_supply_changed(&smb->battery); | ||
756 | dev_dbg(smb->dev, "going to HW maintenance mode\n"); | ||
757 | handled = true; | ||
758 | } | ||
759 | |||
760 | /* | ||
761 | * If we got a charger timeout INT that means the charge | ||
762 | * full is not detected with in charge timeout value. | ||
763 | */ | ||
764 | if (irqstat_d & IRQSTAT_D_CHARGE_TIMEOUT_IRQ) { | ||
765 | dev_dbg(smb->dev, "total Charge Timeout INT received\n"); | ||
766 | |||
767 | if (irqstat_d & IRQSTAT_D_CHARGE_TIMEOUT_STAT) | ||
768 | dev_warn(smb->dev, "charging stopped due to timeout\n"); | ||
769 | power_supply_changed(&smb->battery); | ||
770 | handled = true; | ||
771 | } | ||
772 | |||
773 | /* | ||
774 | * If we got an under voltage interrupt it means that AC/USB input | ||
775 | * was connected or disconnected. | ||
776 | */ | ||
777 | if (irqstat_e & (IRQSTAT_E_USBIN_UV_IRQ | IRQSTAT_E_DCIN_UV_IRQ)) { | ||
778 | if (smb347_update_ps_status(smb) > 0) { | ||
779 | smb347_start_stop_charging(smb); | ||
780 | if (smb->pdata->use_mains) | ||
781 | power_supply_changed(&smb->mains); | ||
782 | if (smb->pdata->use_usb) | ||
783 | power_supply_changed(&smb->usb); | ||
784 | } | ||
785 | handled = true; | ||
786 | } | ||
787 | |||
788 | return handled ? IRQ_HANDLED : IRQ_NONE; | ||
789 | } | ||
790 | |||
791 | static int smb347_irq_set(struct smb347_charger *smb, bool enable) | ||
792 | { | ||
793 | int ret; | ||
794 | |||
795 | ret = smb347_set_writable(smb, true); | ||
796 | if (ret < 0) | ||
797 | return ret; | ||
798 | |||
799 | /* | ||
800 | * Enable/disable interrupts for: | ||
801 | * - under voltage | ||
802 | * - termination current reached | ||
803 | * - charger timeout | ||
804 | * - charger error | ||
805 | */ | ||
806 | ret = regmap_update_bits(smb->regmap, CFG_FAULT_IRQ, 0xff, | ||
807 | enable ? CFG_FAULT_IRQ_DCIN_UV : 0); | ||
808 | if (ret < 0) | ||
809 | goto fail; | ||
810 | |||
811 | ret = regmap_update_bits(smb->regmap, CFG_STATUS_IRQ, 0xff, | ||
812 | enable ? (CFG_STATUS_IRQ_TERMINATION_OR_TAPER | | ||
813 | CFG_STATUS_IRQ_CHARGE_TIMEOUT) : 0); | ||
814 | if (ret < 0) | ||
815 | goto fail; | ||
816 | |||
817 | ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_CHARGER_ERROR, | ||
818 | enable ? CFG_PIN_EN_CHARGER_ERROR : 0); | ||
819 | fail: | ||
820 | smb347_set_writable(smb, false); | ||
821 | return ret; | ||
822 | } | ||
823 | |||
824 | static inline int smb347_irq_enable(struct smb347_charger *smb) | ||
825 | { | ||
826 | return smb347_irq_set(smb, true); | ||
827 | } | ||
828 | |||
829 | static inline int smb347_irq_disable(struct smb347_charger *smb) | ||
830 | { | ||
831 | return smb347_irq_set(smb, false); | ||
832 | } | ||
833 | |||
834 | static int smb347_irq_init(struct smb347_charger *smb, | ||
835 | struct i2c_client *client) | ||
836 | { | ||
837 | const struct smb347_charger_platform_data *pdata = smb->pdata; | ||
838 | int ret, irq = gpio_to_irq(pdata->irq_gpio); | ||
839 | |||
840 | ret = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); | ||
841 | if (ret < 0) | ||
842 | goto fail; | ||
843 | |||
844 | ret = request_threaded_irq(irq, NULL, smb347_interrupt, | ||
845 | IRQF_TRIGGER_FALLING, client->name, smb); | ||
846 | if (ret < 0) | ||
847 | goto fail_gpio; | ||
848 | |||
849 | ret = smb347_set_writable(smb, true); | ||
850 | if (ret < 0) | ||
851 | goto fail_irq; | ||
852 | |||
853 | /* | ||
854 | * Configure the STAT output to be suitable for interrupts: disable | ||
855 | * all other output (except interrupts) and make it active low. | ||
856 | */ | ||
857 | ret = regmap_update_bits(smb->regmap, CFG_STAT, | ||
858 | CFG_STAT_ACTIVE_HIGH | CFG_STAT_DISABLED, | ||
859 | CFG_STAT_DISABLED); | ||
860 | if (ret < 0) | ||
861 | goto fail_readonly; | ||
862 | |||
863 | smb347_set_writable(smb, false); | ||
864 | client->irq = irq; | ||
865 | return 0; | ||
866 | |||
867 | fail_readonly: | ||
868 | smb347_set_writable(smb, false); | ||
869 | fail_irq: | ||
870 | free_irq(irq, smb); | ||
871 | fail_gpio: | ||
872 | gpio_free(pdata->irq_gpio); | ||
873 | fail: | ||
874 | client->irq = 0; | ||
875 | return ret; | ||
876 | } | ||
877 | |||
878 | /* | ||
879 | * Returns the constant charge current programmed | ||
880 | * into the charger in uA. | ||
881 | */ | ||
882 | static int get_const_charge_current(struct smb347_charger *smb) | ||
883 | { | ||
884 | int ret, intval; | ||
885 | unsigned int v; | ||
886 | |||
887 | if (!smb347_is_ps_online(smb)) | ||
888 | return -ENODATA; | ||
889 | |||
890 | ret = regmap_read(smb->regmap, STAT_B, &v); | ||
891 | if (ret < 0) | ||
892 | return ret; | ||
893 | |||
894 | /* | ||
895 | * The current value is composition of FCC and PCC values | ||
896 | * and we can detect which table to use from bit 5. | ||
897 | */ | ||
898 | if (v & 0x20) { | ||
899 | intval = hw_to_current(fcc_tbl, ARRAY_SIZE(fcc_tbl), v & 7); | ||
900 | } else { | ||
901 | v >>= 3; | ||
902 | intval = hw_to_current(pcc_tbl, ARRAY_SIZE(pcc_tbl), v & 7); | ||
903 | } | ||
904 | |||
905 | return intval; | ||
906 | } | ||
907 | |||
908 | /* | ||
909 | * Returns the constant charge voltage programmed | ||
910 | * into the charger in uV. | ||
911 | */ | ||
912 | static int get_const_charge_voltage(struct smb347_charger *smb) | ||
913 | { | ||
914 | int ret, intval; | ||
915 | unsigned int v; | ||
916 | |||
917 | if (!smb347_is_ps_online(smb)) | ||
918 | return -ENODATA; | ||
919 | |||
920 | ret = regmap_read(smb->regmap, STAT_A, &v); | ||
921 | if (ret < 0) | ||
922 | return ret; | ||
923 | |||
924 | v &= STAT_A_FLOAT_VOLTAGE_MASK; | ||
925 | if (v > 0x3d) | ||
926 | v = 0x3d; | ||
927 | |||
928 | intval = 3500000 + v * 20000; | ||
929 | |||
930 | return intval; | ||
931 | } | ||
932 | |||
933 | static int smb347_mains_get_property(struct power_supply *psy, | ||
934 | enum power_supply_property prop, | ||
935 | union power_supply_propval *val) | ||
936 | { | ||
937 | struct smb347_charger *smb = | ||
938 | container_of(psy, struct smb347_charger, mains); | ||
939 | int ret; | ||
940 | |||
941 | switch (prop) { | ||
942 | case POWER_SUPPLY_PROP_ONLINE: | ||
943 | val->intval = smb->mains_online; | ||
944 | break; | ||
945 | |||
946 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | ||
947 | ret = get_const_charge_voltage(smb); | ||
948 | if (ret < 0) | ||
949 | return ret; | ||
950 | else | ||
951 | val->intval = ret; | ||
952 | break; | ||
953 | |||
954 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
955 | ret = get_const_charge_current(smb); | ||
956 | if (ret < 0) | ||
957 | return ret; | ||
958 | else | ||
959 | val->intval = ret; | ||
960 | break; | ||
961 | |||
962 | default: | ||
963 | return -EINVAL; | ||
964 | } | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static enum power_supply_property smb347_mains_properties[] = { | ||
970 | POWER_SUPPLY_PROP_ONLINE, | ||
971 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | ||
972 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | ||
973 | }; | ||
974 | |||
975 | static int smb347_usb_get_property(struct power_supply *psy, | ||
976 | enum power_supply_property prop, | ||
977 | union power_supply_propval *val) | ||
978 | { | ||
979 | struct smb347_charger *smb = | ||
980 | container_of(psy, struct smb347_charger, usb); | ||
981 | int ret; | ||
982 | |||
983 | switch (prop) { | ||
984 | case POWER_SUPPLY_PROP_ONLINE: | ||
985 | val->intval = smb->usb_online; | ||
986 | break; | ||
987 | |||
988 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | ||
989 | ret = get_const_charge_voltage(smb); | ||
990 | if (ret < 0) | ||
991 | return ret; | ||
992 | else | ||
993 | val->intval = ret; | ||
994 | break; | ||
995 | |||
996 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
997 | ret = get_const_charge_current(smb); | ||
998 | if (ret < 0) | ||
999 | return ret; | ||
1000 | else | ||
1001 | val->intval = ret; | ||
1002 | break; | ||
1003 | |||
1004 | default: | ||
1005 | return -EINVAL; | ||
1006 | } | ||
1007 | |||
1008 | return 0; | ||
1009 | } | ||
1010 | |||
1011 | static enum power_supply_property smb347_usb_properties[] = { | ||
1012 | POWER_SUPPLY_PROP_ONLINE, | ||
1013 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | ||
1014 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | ||
1015 | }; | ||
1016 | |||
1017 | static int smb347_get_charging_status(struct smb347_charger *smb) | ||
1018 | { | ||
1019 | int ret, status; | ||
1020 | unsigned int val; | ||
1021 | |||
1022 | if (!smb347_is_ps_online(smb)) | ||
1023 | return POWER_SUPPLY_STATUS_DISCHARGING; | ||
1024 | |||
1025 | ret = regmap_read(smb->regmap, STAT_C, &val); | ||
1026 | if (ret < 0) | ||
1027 | return ret; | ||
1028 | |||
1029 | if ((val & STAT_C_CHARGER_ERROR) || | ||
1030 | (val & STAT_C_HOLDOFF_STAT)) { | ||
1031 | /* | ||
1032 | * set to NOT CHARGING upon charger error | ||
1033 | * or charging has stopped. | ||
1034 | */ | ||
1035 | status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
1036 | } else { | ||
1037 | if ((val & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT) { | ||
1038 | /* | ||
1039 | * set to charging if battery is in pre-charge, | ||
1040 | * fast charge or taper charging mode. | ||
1041 | */ | ||
1042 | status = POWER_SUPPLY_STATUS_CHARGING; | ||
1043 | } else if (val & STAT_C_CHG_TERM) { | ||
1044 | /* | ||
1045 | * set the status to FULL if battery is not in pre | ||
1046 | * charge, fast charge or taper charging mode AND | ||
1047 | * charging is terminated at least once. | ||
1048 | */ | ||
1049 | status = POWER_SUPPLY_STATUS_FULL; | ||
1050 | } else { | ||
1051 | /* | ||
1052 | * in this case no charger error or termination | ||
1053 | * occured but charging is not in progress!!! | ||
1054 | */ | ||
1055 | status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | return status; | ||
1060 | } | ||
1061 | |||
1062 | static int smb347_battery_get_property(struct power_supply *psy, | ||
1063 | enum power_supply_property prop, | ||
1064 | union power_supply_propval *val) | ||
1065 | { | ||
1066 | struct smb347_charger *smb = | ||
1067 | container_of(psy, struct smb347_charger, battery); | ||
1068 | const struct smb347_charger_platform_data *pdata = smb->pdata; | ||
1069 | int ret; | ||
1070 | |||
1071 | ret = smb347_update_ps_status(smb); | ||
1072 | if (ret < 0) | ||
1073 | return ret; | ||
1074 | |||
1075 | switch (prop) { | ||
1076 | case POWER_SUPPLY_PROP_STATUS: | ||
1077 | ret = smb347_get_charging_status(smb); | ||
1078 | if (ret < 0) | ||
1079 | return ret; | ||
1080 | val->intval = ret; | ||
1081 | break; | ||
1082 | |||
1083 | case POWER_SUPPLY_PROP_CHARGE_TYPE: | ||
1084 | if (!smb347_is_ps_online(smb)) | ||
1085 | return -ENODATA; | ||
1086 | |||
1087 | /* | ||
1088 | * We handle trickle and pre-charging the same, and taper | ||
1089 | * and none the same. | ||
1090 | */ | ||
1091 | switch (smb347_charging_status(smb)) { | ||
1092 | case 1: | ||
1093 | val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; | ||
1094 | break; | ||
1095 | case 2: | ||
1096 | val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; | ||
1097 | break; | ||
1098 | default: | ||
1099 | val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; | ||
1100 | break; | ||
1101 | } | ||
1102 | break; | ||
1103 | |||
1104 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
1105 | val->intval = pdata->battery_info.technology; | ||
1106 | break; | ||
1107 | |||
1108 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | ||
1109 | val->intval = pdata->battery_info.voltage_min_design; | ||
1110 | break; | ||
1111 | |||
1112 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
1113 | val->intval = pdata->battery_info.voltage_max_design; | ||
1114 | break; | ||
1115 | |||
1116 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
1117 | val->intval = pdata->battery_info.charge_full_design; | ||
1118 | break; | ||
1119 | |||
1120 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
1121 | val->strval = pdata->battery_info.name; | ||
1122 | break; | ||
1123 | |||
1124 | default: | ||
1125 | return -EINVAL; | ||
1126 | } | ||
1127 | |||
1128 | return 0; | ||
1129 | } | ||
1130 | |||
1131 | static enum power_supply_property smb347_battery_properties[] = { | ||
1132 | POWER_SUPPLY_PROP_STATUS, | ||
1133 | POWER_SUPPLY_PROP_CHARGE_TYPE, | ||
1134 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
1135 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | ||
1136 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
1137 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
1138 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
1139 | }; | ||
1140 | |||
1141 | static bool smb347_volatile_reg(struct device *dev, unsigned int reg) | ||
1142 | { | ||
1143 | switch (reg) { | ||
1144 | case IRQSTAT_A: | ||
1145 | case IRQSTAT_C: | ||
1146 | case IRQSTAT_E: | ||
1147 | case IRQSTAT_F: | ||
1148 | case STAT_A: | ||
1149 | case STAT_B: | ||
1150 | case STAT_C: | ||
1151 | case STAT_E: | ||
1152 | return true; | ||
1153 | } | ||
1154 | |||
1155 | return false; | ||
1156 | } | ||
1157 | |||
1158 | static bool smb347_readable_reg(struct device *dev, unsigned int reg) | ||
1159 | { | ||
1160 | switch (reg) { | ||
1161 | case CFG_CHARGE_CURRENT: | ||
1162 | case CFG_CURRENT_LIMIT: | ||
1163 | case CFG_FLOAT_VOLTAGE: | ||
1164 | case CFG_STAT: | ||
1165 | case CFG_PIN: | ||
1166 | case CFG_THERM: | ||
1167 | case CFG_SYSOK: | ||
1168 | case CFG_OTHER: | ||
1169 | case CFG_OTG: | ||
1170 | case CFG_TEMP_LIMIT: | ||
1171 | case CFG_FAULT_IRQ: | ||
1172 | case CFG_STATUS_IRQ: | ||
1173 | case CFG_ADDRESS: | ||
1174 | case CMD_A: | ||
1175 | case CMD_B: | ||
1176 | case CMD_C: | ||
1177 | return true; | ||
1178 | } | ||
1179 | |||
1180 | return smb347_volatile_reg(dev, reg); | ||
1181 | } | ||
1182 | |||
1183 | static const struct regmap_config smb347_regmap = { | ||
1184 | .reg_bits = 8, | ||
1185 | .val_bits = 8, | ||
1186 | .max_register = SMB347_MAX_REGISTER, | ||
1187 | .volatile_reg = smb347_volatile_reg, | ||
1188 | .readable_reg = smb347_readable_reg, | ||
1189 | }; | ||
1190 | |||
1191 | static int smb347_probe(struct i2c_client *client, | ||
1192 | const struct i2c_device_id *id) | ||
1193 | { | ||
1194 | static char *battery[] = { "smb347-battery" }; | ||
1195 | const struct smb347_charger_platform_data *pdata; | ||
1196 | struct device *dev = &client->dev; | ||
1197 | struct smb347_charger *smb; | ||
1198 | int ret; | ||
1199 | |||
1200 | pdata = dev->platform_data; | ||
1201 | if (!pdata) | ||
1202 | return -EINVAL; | ||
1203 | |||
1204 | if (!pdata->use_mains && !pdata->use_usb) | ||
1205 | return -EINVAL; | ||
1206 | |||
1207 | smb = devm_kzalloc(dev, sizeof(*smb), GFP_KERNEL); | ||
1208 | if (!smb) | ||
1209 | return -ENOMEM; | ||
1210 | |||
1211 | i2c_set_clientdata(client, smb); | ||
1212 | |||
1213 | mutex_init(&smb->lock); | ||
1214 | smb->dev = &client->dev; | ||
1215 | smb->pdata = pdata; | ||
1216 | |||
1217 | smb->regmap = devm_regmap_init_i2c(client, &smb347_regmap); | ||
1218 | if (IS_ERR(smb->regmap)) | ||
1219 | return PTR_ERR(smb->regmap); | ||
1220 | |||
1221 | ret = smb347_hw_init(smb); | ||
1222 | if (ret < 0) | ||
1223 | return ret; | ||
1224 | |||
1225 | if (smb->pdata->use_mains) { | ||
1226 | smb->mains.name = "smb347-mains"; | ||
1227 | smb->mains.type = POWER_SUPPLY_TYPE_MAINS; | ||
1228 | smb->mains.get_property = smb347_mains_get_property; | ||
1229 | smb->mains.properties = smb347_mains_properties; | ||
1230 | smb->mains.num_properties = ARRAY_SIZE(smb347_mains_properties); | ||
1231 | smb->mains.supplied_to = battery; | ||
1232 | smb->mains.num_supplicants = ARRAY_SIZE(battery); | ||
1233 | ret = power_supply_register(dev, &smb->mains); | ||
1234 | if (ret < 0) | ||
1235 | return ret; | ||
1236 | } | ||
1237 | |||
1238 | if (smb->pdata->use_usb) { | ||
1239 | smb->usb.name = "smb347-usb"; | ||
1240 | smb->usb.type = POWER_SUPPLY_TYPE_USB; | ||
1241 | smb->usb.get_property = smb347_usb_get_property; | ||
1242 | smb->usb.properties = smb347_usb_properties; | ||
1243 | smb->usb.num_properties = ARRAY_SIZE(smb347_usb_properties); | ||
1244 | smb->usb.supplied_to = battery; | ||
1245 | smb->usb.num_supplicants = ARRAY_SIZE(battery); | ||
1246 | ret = power_supply_register(dev, &smb->usb); | ||
1247 | if (ret < 0) { | ||
1248 | if (smb->pdata->use_mains) | ||
1249 | power_supply_unregister(&smb->mains); | ||
1250 | return ret; | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1254 | smb->battery.name = "smb347-battery"; | ||
1255 | smb->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
1256 | smb->battery.get_property = smb347_battery_get_property; | ||
1257 | smb->battery.properties = smb347_battery_properties; | ||
1258 | smb->battery.num_properties = ARRAY_SIZE(smb347_battery_properties); | ||
1259 | |||
1260 | |||
1261 | ret = power_supply_register(dev, &smb->battery); | ||
1262 | if (ret < 0) { | ||
1263 | if (smb->pdata->use_usb) | ||
1264 | power_supply_unregister(&smb->usb); | ||
1265 | if (smb->pdata->use_mains) | ||
1266 | power_supply_unregister(&smb->mains); | ||
1267 | return ret; | ||
1268 | } | ||
1269 | |||
1270 | /* | ||
1271 | * Interrupt pin is optional. If it is connected, we setup the | ||
1272 | * interrupt support here. | ||
1273 | */ | ||
1274 | if (pdata->irq_gpio >= 0) { | ||
1275 | ret = smb347_irq_init(smb, client); | ||
1276 | if (ret < 0) { | ||
1277 | dev_warn(dev, "failed to initialize IRQ: %d\n", ret); | ||
1278 | dev_warn(dev, "disabling IRQ support\n"); | ||
1279 | } else { | ||
1280 | smb347_irq_enable(smb); | ||
1281 | } | ||
1282 | } | ||
1283 | |||
1284 | return 0; | ||
1285 | } | ||
1286 | |||
1287 | static int smb347_remove(struct i2c_client *client) | ||
1288 | { | ||
1289 | struct smb347_charger *smb = i2c_get_clientdata(client); | ||
1290 | |||
1291 | if (client->irq) { | ||
1292 | smb347_irq_disable(smb); | ||
1293 | free_irq(client->irq, smb); | ||
1294 | gpio_free(smb->pdata->irq_gpio); | ||
1295 | } | ||
1296 | |||
1297 | power_supply_unregister(&smb->battery); | ||
1298 | if (smb->pdata->use_usb) | ||
1299 | power_supply_unregister(&smb->usb); | ||
1300 | if (smb->pdata->use_mains) | ||
1301 | power_supply_unregister(&smb->mains); | ||
1302 | return 0; | ||
1303 | } | ||
1304 | |||
1305 | static const struct i2c_device_id smb347_id[] = { | ||
1306 | { "smb347", 0 }, | ||
1307 | { } | ||
1308 | }; | ||
1309 | MODULE_DEVICE_TABLE(i2c, smb347_id); | ||
1310 | |||
1311 | static struct i2c_driver smb347_driver = { | ||
1312 | .driver = { | ||
1313 | .name = "smb347", | ||
1314 | }, | ||
1315 | .probe = smb347_probe, | ||
1316 | .remove = smb347_remove, | ||
1317 | .id_table = smb347_id, | ||
1318 | }; | ||
1319 | |||
1320 | module_i2c_driver(smb347_driver); | ||
1321 | |||
1322 | MODULE_AUTHOR("Bruce E. Robertson <bruce.e.robertson@intel.com>"); | ||
1323 | MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); | ||
1324 | MODULE_DESCRIPTION("SMB347 battery charger driver"); | ||
1325 | MODULE_LICENSE("GPL"); | ||
1326 | MODULE_ALIAS("i2c:smb347"); | ||
diff --git a/drivers/power/test_power.c b/drivers/power/test_power.c index b99a452a4fd..b527c93bf2f 100644 --- a/drivers/power/test_power.c +++ b/drivers/power/test_power.c | |||
@@ -22,13 +22,11 @@ | |||
22 | #include <linux/vermagic.h> | 22 | #include <linux/vermagic.h> |
23 | 23 | ||
24 | static int ac_online = 1; | 24 | static int ac_online = 1; |
25 | static int usb_online = 1; | ||
26 | static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING; | 25 | static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING; |
27 | static int battery_health = POWER_SUPPLY_HEALTH_GOOD; | 26 | static int battery_health = POWER_SUPPLY_HEALTH_GOOD; |
28 | static int battery_present = 1; /* true */ | 27 | static int battery_present = 1; /* true */ |
29 | static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION; | 28 | static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION; |
30 | static int battery_capacity = 50; | 29 | static int battery_capacity = 50; |
31 | static int battery_voltage = 3300; | ||
32 | 30 | ||
33 | static int test_power_get_ac_property(struct power_supply *psy, | 31 | static int test_power_get_ac_property(struct power_supply *psy, |
34 | enum power_supply_property psp, | 32 | enum power_supply_property psp, |
@@ -44,20 +42,6 @@ static int test_power_get_ac_property(struct power_supply *psy, | |||
44 | return 0; | 42 | return 0; |
45 | } | 43 | } |
46 | 44 | ||
47 | static int test_power_get_usb_property(struct power_supply *psy, | ||
48 | enum power_supply_property psp, | ||
49 | union power_supply_propval *val) | ||
50 | { | ||
51 | switch (psp) { | ||
52 | case POWER_SUPPLY_PROP_ONLINE: | ||
53 | val->intval = usb_online; | ||
54 | break; | ||
55 | default: | ||
56 | return -EINVAL; | ||
57 | } | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int test_power_get_battery_property(struct power_supply *psy, | 45 | static int test_power_get_battery_property(struct power_supply *psy, |
62 | enum power_supply_property psp, | 46 | enum power_supply_property psp, |
63 | union power_supply_propval *val) | 47 | union power_supply_propval *val) |
@@ -102,12 +86,6 @@ static int test_power_get_battery_property(struct power_supply *psy, | |||
102 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: | 86 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: |
103 | val->intval = 3600; | 87 | val->intval = 3600; |
104 | break; | 88 | break; |
105 | case POWER_SUPPLY_PROP_TEMP: | ||
106 | val->intval = 26; | ||
107 | break; | ||
108 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
109 | val->intval = battery_voltage; | ||
110 | break; | ||
111 | default: | 89 | default: |
112 | pr_info("%s: some properties deliberately report errors.\n", | 90 | pr_info("%s: some properties deliberately report errors.\n", |
113 | __func__); | 91 | __func__); |
@@ -136,8 +114,6 @@ static enum power_supply_property test_power_battery_props[] = { | |||
136 | POWER_SUPPLY_PROP_MODEL_NAME, | 114 | POWER_SUPPLY_PROP_MODEL_NAME, |
137 | POWER_SUPPLY_PROP_MANUFACTURER, | 115 | POWER_SUPPLY_PROP_MANUFACTURER, |
138 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 116 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
139 | POWER_SUPPLY_PROP_TEMP, | ||
140 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
141 | }; | 117 | }; |
142 | 118 | ||
143 | static char *test_power_ac_supplied_to[] = { | 119 | static char *test_power_ac_supplied_to[] = { |
@@ -159,14 +135,6 @@ static struct power_supply test_power_supplies[] = { | |||
159 | .properties = test_power_battery_props, | 135 | .properties = test_power_battery_props, |
160 | .num_properties = ARRAY_SIZE(test_power_battery_props), | 136 | .num_properties = ARRAY_SIZE(test_power_battery_props), |
161 | .get_property = test_power_get_battery_property, | 137 | .get_property = test_power_get_battery_property, |
162 | }, { | ||
163 | .name = "test_usb", | ||
164 | .type = POWER_SUPPLY_TYPE_USB, | ||
165 | .supplied_to = test_power_ac_supplied_to, | ||
166 | .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to), | ||
167 | .properties = test_power_ac_props, | ||
168 | .num_properties = ARRAY_SIZE(test_power_ac_props), | ||
169 | .get_property = test_power_get_usb_property, | ||
170 | }, | 138 | }, |
171 | }; | 139 | }; |
172 | 140 | ||
@@ -199,7 +167,6 @@ static void __exit test_power_exit(void) | |||
199 | 167 | ||
200 | /* Let's see how we handle changes... */ | 168 | /* Let's see how we handle changes... */ |
201 | ac_online = 0; | 169 | ac_online = 0; |
202 | usb_online = 0; | ||
203 | battery_status = POWER_SUPPLY_STATUS_DISCHARGING; | 170 | battery_status = POWER_SUPPLY_STATUS_DISCHARGING; |
204 | for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) | 171 | for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) |
205 | power_supply_changed(&test_power_supplies[i]); | 172 | power_supply_changed(&test_power_supplies[i]); |
@@ -308,19 +275,6 @@ static int param_get_ac_online(char *buffer, const struct kernel_param *kp) | |||
308 | return strlen(buffer); | 275 | return strlen(buffer); |
309 | } | 276 | } |
310 | 277 | ||
311 | static int param_set_usb_online(const char *key, const struct kernel_param *kp) | ||
312 | { | ||
313 | usb_online = map_get_value(map_ac_online, key, usb_online); | ||
314 | power_supply_changed(&test_power_supplies[2]); | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int param_get_usb_online(char *buffer, const struct kernel_param *kp) | ||
319 | { | ||
320 | strcpy(buffer, map_get_key(map_ac_online, usb_online, "unknown")); | ||
321 | return strlen(buffer); | ||
322 | } | ||
323 | |||
324 | static int param_set_battery_status(const char *key, | 278 | static int param_set_battery_status(const char *key, |
325 | const struct kernel_param *kp) | 279 | const struct kernel_param *kp) |
326 | { | 280 | { |
@@ -396,31 +350,13 @@ static int param_set_battery_capacity(const char *key, | |||
396 | 350 | ||
397 | #define param_get_battery_capacity param_get_int | 351 | #define param_get_battery_capacity param_get_int |
398 | 352 | ||
399 | static int param_set_battery_voltage(const char *key, | ||
400 | const struct kernel_param *kp) | ||
401 | { | ||
402 | int tmp; | ||
403 | |||
404 | if (1 != sscanf(key, "%d", &tmp)) | ||
405 | return -EINVAL; | ||
406 | |||
407 | battery_voltage = tmp; | ||
408 | power_supply_changed(&test_power_supplies[1]); | ||
409 | return 0; | ||
410 | } | ||
411 | 353 | ||
412 | #define param_get_battery_voltage param_get_int | ||
413 | 354 | ||
414 | static struct kernel_param_ops param_ops_ac_online = { | 355 | static struct kernel_param_ops param_ops_ac_online = { |
415 | .set = param_set_ac_online, | 356 | .set = param_set_ac_online, |
416 | .get = param_get_ac_online, | 357 | .get = param_get_ac_online, |
417 | }; | 358 | }; |
418 | 359 | ||
419 | static struct kernel_param_ops param_ops_usb_online = { | ||
420 | .set = param_set_usb_online, | ||
421 | .get = param_get_usb_online, | ||
422 | }; | ||
423 | |||
424 | static struct kernel_param_ops param_ops_battery_status = { | 360 | static struct kernel_param_ops param_ops_battery_status = { |
425 | .set = param_set_battery_status, | 361 | .set = param_set_battery_status, |
426 | .get = param_get_battery_status, | 362 | .get = param_get_battery_status, |
@@ -446,27 +382,18 @@ static struct kernel_param_ops param_ops_battery_capacity = { | |||
446 | .get = param_get_battery_capacity, | 382 | .get = param_get_battery_capacity, |
447 | }; | 383 | }; |
448 | 384 | ||
449 | static struct kernel_param_ops param_ops_battery_voltage = { | ||
450 | .set = param_set_battery_voltage, | ||
451 | .get = param_get_battery_voltage, | ||
452 | }; | ||
453 | 385 | ||
454 | #define param_check_ac_online(name, p) __param_check(name, p, void); | 386 | #define param_check_ac_online(name, p) __param_check(name, p, void); |
455 | #define param_check_usb_online(name, p) __param_check(name, p, void); | ||
456 | #define param_check_battery_status(name, p) __param_check(name, p, void); | 387 | #define param_check_battery_status(name, p) __param_check(name, p, void); |
457 | #define param_check_battery_present(name, p) __param_check(name, p, void); | 388 | #define param_check_battery_present(name, p) __param_check(name, p, void); |
458 | #define param_check_battery_technology(name, p) __param_check(name, p, void); | 389 | #define param_check_battery_technology(name, p) __param_check(name, p, void); |
459 | #define param_check_battery_health(name, p) __param_check(name, p, void); | 390 | #define param_check_battery_health(name, p) __param_check(name, p, void); |
460 | #define param_check_battery_capacity(name, p) __param_check(name, p, void); | 391 | #define param_check_battery_capacity(name, p) __param_check(name, p, void); |
461 | #define param_check_battery_voltage(name, p) __param_check(name, p, void); | ||
462 | 392 | ||
463 | 393 | ||
464 | module_param(ac_online, ac_online, 0644); | 394 | module_param(ac_online, ac_online, 0644); |
465 | MODULE_PARM_DESC(ac_online, "AC charging state <on|off>"); | 395 | MODULE_PARM_DESC(ac_online, "AC charging state <on|off>"); |
466 | 396 | ||
467 | module_param(usb_online, usb_online, 0644); | ||
468 | MODULE_PARM_DESC(usb_online, "USB charging state <on|off>"); | ||
469 | |||
470 | module_param(battery_status, battery_status, 0644); | 397 | module_param(battery_status, battery_status, 0644); |
471 | MODULE_PARM_DESC(battery_status, | 398 | MODULE_PARM_DESC(battery_status, |
472 | "battery status <charging|discharging|not-charging|full>"); | 399 | "battery status <charging|discharging|not-charging|full>"); |
@@ -486,8 +413,6 @@ MODULE_PARM_DESC(battery_health, | |||
486 | module_param(battery_capacity, battery_capacity, 0644); | 413 | module_param(battery_capacity, battery_capacity, 0644); |
487 | MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)"); | 414 | MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)"); |
488 | 415 | ||
489 | module_param(battery_voltage, battery_voltage, 0644); | ||
490 | MODULE_PARM_DESC(battery_voltage, "battery voltage (millivolts)"); | ||
491 | 416 | ||
492 | MODULE_DESCRIPTION("Power supply driver for testing"); | 417 | MODULE_DESCRIPTION("Power supply driver for testing"); |
493 | MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); | 418 | MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); |
diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c index 0224de50c54..53f0d3524fc 100644 --- a/drivers/power/tosa_battery.c +++ b/drivers/power/tosa_battery.c | |||
@@ -307,27 +307,32 @@ static struct tosa_bat tosa_bat_bu = { | |||
307 | .adc_temp_divider = -1, | 307 | .adc_temp_divider = -1, |
308 | }; | 308 | }; |
309 | 309 | ||
310 | static struct gpio tosa_bat_gpios[] = { | 310 | static struct { |
311 | { TOSA_GPIO_CHARGE_OFF, GPIOF_OUT_INIT_HIGH, "main charge off" }, | 311 | int gpio; |
312 | { TOSA_GPIO_CHARGE_OFF_JC, GPIOF_OUT_INIT_HIGH, "jacket charge off" }, | 312 | char *name; |
313 | { TOSA_GPIO_BAT_SW_ON, GPIOF_OUT_INIT_LOW, "battery switch" }, | 313 | bool output; |
314 | { TOSA_GPIO_BAT0_V_ON, GPIOF_OUT_INIT_LOW, "main battery" }, | 314 | int value; |
315 | { TOSA_GPIO_BAT1_V_ON, GPIOF_OUT_INIT_LOW, "jacket battery" }, | 315 | } gpios[] = { |
316 | { TOSA_GPIO_BAT1_TH_ON, GPIOF_OUT_INIT_LOW, "main battery temp" }, | 316 | { TOSA_GPIO_CHARGE_OFF, "main charge off", 1, 1 }, |
317 | { TOSA_GPIO_BAT0_TH_ON, GPIOF_OUT_INIT_LOW, "jacket battery temp" }, | 317 | { TOSA_GPIO_CHARGE_OFF_JC, "jacket charge off", 1, 1 }, |
318 | { TOSA_GPIO_BU_CHRG_ON, GPIOF_OUT_INIT_LOW, "backup battery" }, | 318 | { TOSA_GPIO_BAT_SW_ON, "battery switch", 1, 0 }, |
319 | { TOSA_GPIO_BAT0_CRG, GPIOF_IN, "main battery full" }, | 319 | { TOSA_GPIO_BAT0_V_ON, "main battery", 1, 0 }, |
320 | { TOSA_GPIO_BAT1_CRG, GPIOF_IN, "jacket battery full" }, | 320 | { TOSA_GPIO_BAT1_V_ON, "jacket battery", 1, 0 }, |
321 | { TOSA_GPIO_BAT0_LOW, GPIOF_IN, "main battery low" }, | 321 | { TOSA_GPIO_BAT1_TH_ON, "main battery temp", 1, 0 }, |
322 | { TOSA_GPIO_BAT1_LOW, GPIOF_IN, "jacket battery low" }, | 322 | { TOSA_GPIO_BAT0_TH_ON, "jacket battery temp", 1, 0 }, |
323 | { TOSA_GPIO_JACKET_DETECT, GPIOF_IN, "jacket detect" }, | 323 | { TOSA_GPIO_BU_CHRG_ON, "backup battery", 1, 0 }, |
324 | { TOSA_GPIO_BAT0_CRG, "main battery full", 0, 0 }, | ||
325 | { TOSA_GPIO_BAT1_CRG, "jacket battery full", 0, 0 }, | ||
326 | { TOSA_GPIO_BAT0_LOW, "main battery low", 0, 0 }, | ||
327 | { TOSA_GPIO_BAT1_LOW, "jacket battery low", 0, 0 }, | ||
328 | { TOSA_GPIO_JACKET_DETECT, "jacket detect", 0, 0 }, | ||
324 | }; | 329 | }; |
325 | 330 | ||
326 | #ifdef CONFIG_PM | 331 | #ifdef CONFIG_PM |
327 | static int tosa_bat_suspend(struct platform_device *dev, pm_message_t state) | 332 | static int tosa_bat_suspend(struct platform_device *dev, pm_message_t state) |
328 | { | 333 | { |
329 | /* flush all pending status updates */ | 334 | /* flush all pending status updates */ |
330 | flush_work(&bat_work); | 335 | flush_work_sync(&bat_work); |
331 | return 0; | 336 | return 0; |
332 | } | 337 | } |
333 | 338 | ||
@@ -342,16 +347,30 @@ static int tosa_bat_resume(struct platform_device *dev) | |||
342 | #define tosa_bat_resume NULL | 347 | #define tosa_bat_resume NULL |
343 | #endif | 348 | #endif |
344 | 349 | ||
345 | static int tosa_bat_probe(struct platform_device *dev) | 350 | static int __devinit tosa_bat_probe(struct platform_device *dev) |
346 | { | 351 | { |
347 | int ret; | 352 | int ret; |
353 | int i; | ||
348 | 354 | ||
349 | if (!machine_is_tosa()) | 355 | if (!machine_is_tosa()) |
350 | return -ENODEV; | 356 | return -ENODEV; |
351 | 357 | ||
352 | ret = gpio_request_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios)); | 358 | for (i = 0; i < ARRAY_SIZE(gpios); i++) { |
353 | if (ret) | 359 | ret = gpio_request(gpios[i].gpio, gpios[i].name); |
354 | return ret; | 360 | if (ret) { |
361 | i--; | ||
362 | goto err_gpio; | ||
363 | } | ||
364 | |||
365 | if (gpios[i].output) | ||
366 | ret = gpio_direction_output(gpios[i].gpio, | ||
367 | gpios[i].value); | ||
368 | else | ||
369 | ret = gpio_direction_input(gpios[i].gpio); | ||
370 | |||
371 | if (ret) | ||
372 | goto err_gpio; | ||
373 | } | ||
355 | 374 | ||
356 | mutex_init(&tosa_bat_main.work_lock); | 375 | mutex_init(&tosa_bat_main.work_lock); |
357 | mutex_init(&tosa_bat_jacket.work_lock); | 376 | mutex_init(&tosa_bat_jacket.work_lock); |
@@ -405,12 +424,18 @@ err_psy_reg_main: | |||
405 | /* see comment in tosa_bat_remove */ | 424 | /* see comment in tosa_bat_remove */ |
406 | cancel_work_sync(&bat_work); | 425 | cancel_work_sync(&bat_work); |
407 | 426 | ||
408 | gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios)); | 427 | i--; |
428 | err_gpio: | ||
429 | for (; i >= 0; i--) | ||
430 | gpio_free(gpios[i].gpio); | ||
431 | |||
409 | return ret; | 432 | return ret; |
410 | } | 433 | } |
411 | 434 | ||
412 | static int tosa_bat_remove(struct platform_device *dev) | 435 | static int __devexit tosa_bat_remove(struct platform_device *dev) |
413 | { | 436 | { |
437 | int i; | ||
438 | |||
414 | free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket); | 439 | free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket); |
415 | free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket); | 440 | free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket); |
416 | free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main); | 441 | free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main); |
@@ -425,7 +450,10 @@ static int tosa_bat_remove(struct platform_device *dev) | |||
425 | * unregistered now. | 450 | * unregistered now. |
426 | */ | 451 | */ |
427 | cancel_work_sync(&bat_work); | 452 | cancel_work_sync(&bat_work); |
428 | gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios)); | 453 | |
454 | for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--) | ||
455 | gpio_free(gpios[i].gpio); | ||
456 | |||
429 | return 0; | 457 | return 0; |
430 | } | 458 | } |
431 | 459 | ||
@@ -433,12 +461,23 @@ static struct platform_driver tosa_bat_driver = { | |||
433 | .driver.name = "wm97xx-battery", | 461 | .driver.name = "wm97xx-battery", |
434 | .driver.owner = THIS_MODULE, | 462 | .driver.owner = THIS_MODULE, |
435 | .probe = tosa_bat_probe, | 463 | .probe = tosa_bat_probe, |
436 | .remove = tosa_bat_remove, | 464 | .remove = __devexit_p(tosa_bat_remove), |
437 | .suspend = tosa_bat_suspend, | 465 | .suspend = tosa_bat_suspend, |
438 | .resume = tosa_bat_resume, | 466 | .resume = tosa_bat_resume, |
439 | }; | 467 | }; |
440 | 468 | ||
441 | module_platform_driver(tosa_bat_driver); | 469 | static int __init tosa_bat_init(void) |
470 | { | ||
471 | return platform_driver_register(&tosa_bat_driver); | ||
472 | } | ||
473 | |||
474 | static void __exit tosa_bat_exit(void) | ||
475 | { | ||
476 | platform_driver_unregister(&tosa_bat_driver); | ||
477 | } | ||
478 | |||
479 | module_init(tosa_bat_init); | ||
480 | module_exit(tosa_bat_exit); | ||
442 | 481 | ||
443 | MODULE_LICENSE("GPL"); | 482 | MODULE_LICENSE("GPL"); |
444 | MODULE_AUTHOR("Dmitry Baryshkov"); | 483 | MODULE_AUTHOR("Dmitry Baryshkov"); |
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index a69d0d11b54..54b9198fa57 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c | |||
@@ -15,14 +15,12 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/err.h> | ||
19 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
20 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
21 | #include <linux/i2c/twl.h> | 20 | #include <linux/i2c/twl.h> |
22 | #include <linux/power_supply.h> | 21 | #include <linux/power_supply.h> |
23 | #include <linux/notifier.h> | 22 | #include <linux/notifier.h> |
24 | #include <linux/usb/otg.h> | 23 | #include <linux/usb/otg.h> |
25 | #include <linux/regulator/machine.h> | ||
26 | 24 | ||
27 | #define TWL4030_BCIMSTATEC 0x02 | 25 | #define TWL4030_BCIMSTATEC 0x02 |
28 | #define TWL4030_BCIICHG 0x08 | 26 | #define TWL4030_BCIICHG 0x08 |
@@ -30,7 +28,6 @@ | |||
30 | #define TWL4030_BCIVBUS 0x0c | 28 | #define TWL4030_BCIVBUS 0x0c |
31 | #define TWL4030_BCIMFSTS4 0x10 | 29 | #define TWL4030_BCIMFSTS4 0x10 |
32 | #define TWL4030_BCICTL1 0x23 | 30 | #define TWL4030_BCICTL1 0x23 |
33 | #define TWL4030_BB_CFG 0x12 | ||
34 | 31 | ||
35 | #define TWL4030_BCIAUTOWEN BIT(5) | 32 | #define TWL4030_BCIAUTOWEN BIT(5) |
36 | #define TWL4030_CONFIG_DONE BIT(4) | 33 | #define TWL4030_CONFIG_DONE BIT(4) |
@@ -40,17 +37,6 @@ | |||
40 | #define TWL4030_USBFASTMCHG BIT(2) | 37 | #define TWL4030_USBFASTMCHG BIT(2) |
41 | #define TWL4030_STS_VBUS BIT(7) | 38 | #define TWL4030_STS_VBUS BIT(7) |
42 | #define TWL4030_STS_USB_ID BIT(2) | 39 | #define TWL4030_STS_USB_ID BIT(2) |
43 | #define TWL4030_BBCHEN BIT(4) | ||
44 | #define TWL4030_BBSEL_MASK 0x0c | ||
45 | #define TWL4030_BBSEL_2V5 0x00 | ||
46 | #define TWL4030_BBSEL_3V0 0x04 | ||
47 | #define TWL4030_BBSEL_3V1 0x08 | ||
48 | #define TWL4030_BBSEL_3V2 0x0c | ||
49 | #define TWL4030_BBISEL_MASK 0x03 | ||
50 | #define TWL4030_BBISEL_25uA 0x00 | ||
51 | #define TWL4030_BBISEL_150uA 0x01 | ||
52 | #define TWL4030_BBISEL_500uA 0x02 | ||
53 | #define TWL4030_BBISEL_1000uA 0x03 | ||
54 | 40 | ||
55 | /* BCI interrupts */ | 41 | /* BCI interrupts */ |
56 | #define TWL4030_WOVF BIT(0) /* Watchdog overflow */ | 42 | #define TWL4030_WOVF BIT(0) /* Watchdog overflow */ |
@@ -83,13 +69,11 @@ struct twl4030_bci { | |||
83 | struct device *dev; | 69 | struct device *dev; |
84 | struct power_supply ac; | 70 | struct power_supply ac; |
85 | struct power_supply usb; | 71 | struct power_supply usb; |
86 | struct usb_phy *transceiver; | 72 | struct otg_transceiver *transceiver; |
87 | struct notifier_block usb_nb; | 73 | struct notifier_block otg_nb; |
88 | struct work_struct work; | 74 | struct work_struct work; |
89 | int irq_chg; | 75 | int irq_chg; |
90 | int irq_bci; | 76 | int irq_bci; |
91 | struct regulator *usb_reg; | ||
92 | int usb_enabled; | ||
93 | 77 | ||
94 | unsigned long event; | 78 | unsigned long event; |
95 | }; | 79 | }; |
@@ -114,12 +98,12 @@ static int twl4030_clear_set(u8 mod_no, u8 clear, u8 set, u8 reg) | |||
114 | 98 | ||
115 | static int twl4030_bci_read(u8 reg, u8 *val) | 99 | static int twl4030_bci_read(u8 reg, u8 *val) |
116 | { | 100 | { |
117 | return twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, val, reg); | 101 | return twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, val, reg); |
118 | } | 102 | } |
119 | 103 | ||
120 | static int twl4030_clear_set_boot_bci(u8 clear, u8 set) | 104 | static int twl4030_clear_set_boot_bci(u8 clear, u8 set) |
121 | { | 105 | { |
122 | return twl4030_clear_set(TWL_MODULE_PM_MASTER, clear, | 106 | return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, 0, |
123 | TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set, | 107 | TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set, |
124 | TWL4030_PM_MASTER_BOOT_BCI); | 108 | TWL4030_PM_MASTER_BOOT_BCI); |
125 | } | 109 | } |
@@ -152,7 +136,7 @@ static int twl4030_bci_have_vbus(struct twl4030_bci *bci) | |||
152 | int ret; | 136 | int ret; |
153 | u8 hwsts; | 137 | u8 hwsts; |
154 | 138 | ||
155 | ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &hwsts, | 139 | ret = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts, |
156 | TWL4030_PM_MASTER_STS_HW_CONDITIONS); | 140 | TWL4030_PM_MASTER_STS_HW_CONDITIONS); |
157 | if (ret < 0) | 141 | if (ret < 0) |
158 | return 0; | 142 | return 0; |
@@ -167,14 +151,14 @@ static int twl4030_bci_have_vbus(struct twl4030_bci *bci) | |||
167 | } | 151 | } |
168 | 152 | ||
169 | /* | 153 | /* |
170 | * Enable/Disable USB Charge functionality. | 154 | * Enable/Disable USB Charge funtionality. |
171 | */ | 155 | */ |
172 | static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) | 156 | static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) |
173 | { | 157 | { |
174 | int ret; | 158 | int ret; |
175 | 159 | ||
176 | if (enable) { | 160 | if (enable) { |
177 | /* Check for USB charger connected */ | 161 | /* Check for USB charger conneted */ |
178 | if (!twl4030_bci_have_vbus(bci)) | 162 | if (!twl4030_bci_have_vbus(bci)) |
179 | return -ENODEV; | 163 | return -ENODEV; |
180 | 164 | ||
@@ -187,26 +171,16 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) | |||
187 | return -EACCES; | 171 | return -EACCES; |
188 | } | 172 | } |
189 | 173 | ||
190 | /* Need to keep regulator on */ | ||
191 | if (!bci->usb_enabled) { | ||
192 | regulator_enable(bci->usb_reg); | ||
193 | bci->usb_enabled = 1; | ||
194 | } | ||
195 | |||
196 | /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */ | 174 | /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */ |
197 | ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB); | 175 | ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB); |
198 | if (ret < 0) | 176 | if (ret < 0) |
199 | return ret; | 177 | return ret; |
200 | 178 | ||
201 | /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */ | 179 | /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */ |
202 | ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0, | 180 | ret = twl4030_clear_set(TWL4030_MODULE_MAIN_CHARGE, 0, |
203 | TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4); | 181 | TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4); |
204 | } else { | 182 | } else { |
205 | ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0); | 183 | ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0); |
206 | if (bci->usb_enabled) { | ||
207 | regulator_disable(bci->usb_reg); | ||
208 | bci->usb_enabled = 0; | ||
209 | } | ||
210 | } | 184 | } |
211 | 185 | ||
212 | return ret; | 186 | return ret; |
@@ -228,49 +202,6 @@ static int twl4030_charger_enable_ac(bool enable) | |||
228 | } | 202 | } |
229 | 203 | ||
230 | /* | 204 | /* |
231 | * Enable/Disable charging of Backup Battery. | ||
232 | */ | ||
233 | static int twl4030_charger_enable_backup(int uvolt, int uamp) | ||
234 | { | ||
235 | int ret; | ||
236 | u8 flags; | ||
237 | |||
238 | if (uvolt < 2500000 || | ||
239 | uamp < 25) { | ||
240 | /* disable charging of backup battery */ | ||
241 | ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER, | ||
242 | TWL4030_BBCHEN, 0, TWL4030_BB_CFG); | ||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | flags = TWL4030_BBCHEN; | ||
247 | if (uvolt >= 3200000) | ||
248 | flags |= TWL4030_BBSEL_3V2; | ||
249 | else if (uvolt >= 3100000) | ||
250 | flags |= TWL4030_BBSEL_3V1; | ||
251 | else if (uvolt >= 3000000) | ||
252 | flags |= TWL4030_BBSEL_3V0; | ||
253 | else | ||
254 | flags |= TWL4030_BBSEL_2V5; | ||
255 | |||
256 | if (uamp >= 1000) | ||
257 | flags |= TWL4030_BBISEL_1000uA; | ||
258 | else if (uamp >= 500) | ||
259 | flags |= TWL4030_BBISEL_500uA; | ||
260 | else if (uamp >= 150) | ||
261 | flags |= TWL4030_BBISEL_150uA; | ||
262 | else | ||
263 | flags |= TWL4030_BBISEL_25uA; | ||
264 | |||
265 | ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER, | ||
266 | TWL4030_BBSEL_MASK | TWL4030_BBISEL_MASK, | ||
267 | flags, | ||
268 | TWL4030_BB_CFG); | ||
269 | |||
270 | return ret; | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * TWL4030 CHG_PRES (AC charger presence) events | 205 | * TWL4030 CHG_PRES (AC charger presence) events |
275 | */ | 206 | */ |
276 | static irqreturn_t twl4030_charger_interrupt(int irq, void *arg) | 207 | static irqreturn_t twl4030_charger_interrupt(int irq, void *arg) |
@@ -348,7 +279,7 @@ static void twl4030_bci_usb_work(struct work_struct *data) | |||
348 | static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, | 279 | static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, |
349 | void *priv) | 280 | void *priv) |
350 | { | 281 | { |
351 | struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, usb_nb); | 282 | struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb); |
352 | 283 | ||
353 | dev_dbg(bci->dev, "OTG notify %lu\n", val); | 284 | dev_dbg(bci->dev, "OTG notify %lu\n", val); |
354 | 285 | ||
@@ -493,7 +424,6 @@ static enum power_supply_property twl4030_charger_props[] = { | |||
493 | static int __init twl4030_bci_probe(struct platform_device *pdev) | 424 | static int __init twl4030_bci_probe(struct platform_device *pdev) |
494 | { | 425 | { |
495 | struct twl4030_bci *bci; | 426 | struct twl4030_bci *bci; |
496 | struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data; | ||
497 | int ret; | 427 | int ret; |
498 | u32 reg; | 428 | u32 reg; |
499 | 429 | ||
@@ -525,8 +455,6 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) | |||
525 | bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props); | 455 | bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props); |
526 | bci->usb.get_property = twl4030_bci_get_property; | 456 | bci->usb.get_property = twl4030_bci_get_property; |
527 | 457 | ||
528 | bci->usb_reg = regulator_get(bci->dev, "bci3v1"); | ||
529 | |||
530 | ret = power_supply_register(&pdev->dev, &bci->usb); | 458 | ret = power_supply_register(&pdev->dev, &bci->usb); |
531 | if (ret) { | 459 | if (ret) { |
532 | dev_err(&pdev->dev, "failed to register usb: %d\n", ret); | 460 | dev_err(&pdev->dev, "failed to register usb: %d\n", ret); |
@@ -534,8 +462,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) | |||
534 | } | 462 | } |
535 | 463 | ||
536 | ret = request_threaded_irq(bci->irq_chg, NULL, | 464 | ret = request_threaded_irq(bci->irq_chg, NULL, |
537 | twl4030_charger_interrupt, IRQF_ONESHOT, pdev->name, | 465 | twl4030_charger_interrupt, 0, pdev->name, bci); |
538 | bci); | ||
539 | if (ret < 0) { | 466 | if (ret < 0) { |
540 | dev_err(&pdev->dev, "could not request irq %d, status %d\n", | 467 | dev_err(&pdev->dev, "could not request irq %d, status %d\n", |
541 | bci->irq_chg, ret); | 468 | bci->irq_chg, ret); |
@@ -543,7 +470,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) | |||
543 | } | 470 | } |
544 | 471 | ||
545 | ret = request_threaded_irq(bci->irq_bci, NULL, | 472 | ret = request_threaded_irq(bci->irq_bci, NULL, |
546 | twl4030_bci_interrupt, IRQF_ONESHOT, pdev->name, bci); | 473 | twl4030_bci_interrupt, 0, pdev->name, bci); |
547 | if (ret < 0) { | 474 | if (ret < 0) { |
548 | dev_err(&pdev->dev, "could not request irq %d, status %d\n", | 475 | dev_err(&pdev->dev, "could not request irq %d, status %d\n", |
549 | bci->irq_bci, ret); | 476 | bci->irq_bci, ret); |
@@ -552,10 +479,10 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) | |||
552 | 479 | ||
553 | INIT_WORK(&bci->work, twl4030_bci_usb_work); | 480 | INIT_WORK(&bci->work, twl4030_bci_usb_work); |
554 | 481 | ||
555 | bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | 482 | bci->transceiver = otg_get_transceiver(); |
556 | if (!IS_ERR_OR_NULL(bci->transceiver)) { | 483 | if (bci->transceiver != NULL) { |
557 | bci->usb_nb.notifier_call = twl4030_bci_usb_ncb; | 484 | bci->otg_nb.notifier_call = twl4030_bci_usb_ncb; |
558 | usb_register_notifier(bci->transceiver, &bci->usb_nb); | 485 | otg_register_notifier(bci->transceiver, &bci->otg_nb); |
559 | } | 486 | } |
560 | 487 | ||
561 | /* Enable interrupts now. */ | 488 | /* Enable interrupts now. */ |
@@ -576,15 +503,13 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) | |||
576 | 503 | ||
577 | twl4030_charger_enable_ac(true); | 504 | twl4030_charger_enable_ac(true); |
578 | twl4030_charger_enable_usb(bci, true); | 505 | twl4030_charger_enable_usb(bci, true); |
579 | twl4030_charger_enable_backup(pdata->bb_uvolt, | ||
580 | pdata->bb_uamp); | ||
581 | 506 | ||
582 | return 0; | 507 | return 0; |
583 | 508 | ||
584 | fail_unmask_interrupts: | 509 | fail_unmask_interrupts: |
585 | if (!IS_ERR_OR_NULL(bci->transceiver)) { | 510 | if (bci->transceiver != NULL) { |
586 | usb_unregister_notifier(bci->transceiver, &bci->usb_nb); | 511 | otg_unregister_notifier(bci->transceiver, &bci->otg_nb); |
587 | usb_put_phy(bci->transceiver); | 512 | otg_put_transceiver(bci->transceiver); |
588 | } | 513 | } |
589 | free_irq(bci->irq_bci, bci); | 514 | free_irq(bci->irq_bci, bci); |
590 | fail_bci_irq: | 515 | fail_bci_irq: |
@@ -606,7 +531,6 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) | |||
606 | 531 | ||
607 | twl4030_charger_enable_ac(false); | 532 | twl4030_charger_enable_ac(false); |
608 | twl4030_charger_enable_usb(bci, false); | 533 | twl4030_charger_enable_usb(bci, false); |
609 | twl4030_charger_enable_backup(0, 0); | ||
610 | 534 | ||
611 | /* mask interrupts */ | 535 | /* mask interrupts */ |
612 | twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, | 536 | twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, |
@@ -614,9 +538,9 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) | |||
614 | twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, | 538 | twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, |
615 | TWL4030_INTERRUPTS_BCIIMR2A); | 539 | TWL4030_INTERRUPTS_BCIIMR2A); |
616 | 540 | ||
617 | if (!IS_ERR_OR_NULL(bci->transceiver)) { | 541 | if (bci->transceiver != NULL) { |
618 | usb_unregister_notifier(bci->transceiver, &bci->usb_nb); | 542 | otg_unregister_notifier(bci->transceiver, &bci->otg_nb); |
619 | usb_put_phy(bci->transceiver); | 543 | otg_put_transceiver(bci->transceiver); |
620 | } | 544 | } |
621 | free_irq(bci->irq_bci, bci); | 545 | free_irq(bci->irq_bci, bci); |
622 | free_irq(bci->irq_chg, bci); | 546 | free_irq(bci->irq_chg, bci); |
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c index d9cc169f142..e648cbea1e6 100644 --- a/drivers/power/wm831x_backup.c +++ b/drivers/power/wm831x_backup.c | |||
@@ -161,7 +161,7 @@ static enum power_supply_property wm831x_backup_props[] = { | |||
161 | * Initialisation | 161 | * Initialisation |
162 | *********************************************************************/ | 162 | *********************************************************************/ |
163 | 163 | ||
164 | static int wm831x_backup_probe(struct platform_device *pdev) | 164 | static __devinit int wm831x_backup_probe(struct platform_device *pdev) |
165 | { | 165 | { |
166 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | 166 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); |
167 | struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data; | 167 | struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data; |
@@ -207,7 +207,7 @@ err_kmalloc: | |||
207 | return ret; | 207 | return ret; |
208 | } | 208 | } |
209 | 209 | ||
210 | static int wm831x_backup_remove(struct platform_device *pdev) | 210 | static __devexit int wm831x_backup_remove(struct platform_device *pdev) |
211 | { | 211 | { |
212 | struct wm831x_backup *devdata = platform_get_drvdata(pdev); | 212 | struct wm831x_backup *devdata = platform_get_drvdata(pdev); |
213 | 213 | ||
@@ -220,13 +220,23 @@ static int wm831x_backup_remove(struct platform_device *pdev) | |||
220 | 220 | ||
221 | static struct platform_driver wm831x_backup_driver = { | 221 | static struct platform_driver wm831x_backup_driver = { |
222 | .probe = wm831x_backup_probe, | 222 | .probe = wm831x_backup_probe, |
223 | .remove = wm831x_backup_remove, | 223 | .remove = __devexit_p(wm831x_backup_remove), |
224 | .driver = { | 224 | .driver = { |
225 | .name = "wm831x-backup", | 225 | .name = "wm831x-backup", |
226 | }, | 226 | }, |
227 | }; | 227 | }; |
228 | 228 | ||
229 | module_platform_driver(wm831x_backup_driver); | 229 | static int __init wm831x_backup_init(void) |
230 | { | ||
231 | return platform_driver_register(&wm831x_backup_driver); | ||
232 | } | ||
233 | module_init(wm831x_backup_init); | ||
234 | |||
235 | static void __exit wm831x_backup_exit(void) | ||
236 | { | ||
237 | platform_driver_unregister(&wm831x_backup_driver); | ||
238 | } | ||
239 | module_exit(wm831x_backup_exit); | ||
230 | 240 | ||
231 | MODULE_DESCRIPTION("Backup battery charger driver for WM831x PMICs"); | 241 | MODULE_DESCRIPTION("Backup battery charger driver for WM831x PMICs"); |
232 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 242 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index 3bed2f55cf7..6cc2ca6427f 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c | |||
@@ -27,7 +27,6 @@ struct wm831x_power { | |||
27 | char wall_name[20]; | 27 | char wall_name[20]; |
28 | char usb_name[20]; | 28 | char usb_name[20]; |
29 | char battery_name[20]; | 29 | char battery_name[20]; |
30 | bool have_battery; | ||
31 | }; | 30 | }; |
32 | 31 | ||
33 | static int wm831x_power_check_online(struct wm831x *wm831x, int supply, | 32 | static int wm831x_power_check_online(struct wm831x *wm831x, int supply, |
@@ -450,8 +449,7 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data) | |||
450 | 449 | ||
451 | /* The battery charger is autonomous so we don't need to do | 450 | /* The battery charger is autonomous so we don't need to do |
452 | * anything except kick user space */ | 451 | * anything except kick user space */ |
453 | if (wm831x_power->have_battery) | 452 | power_supply_changed(&wm831x_power->battery); |
454 | power_supply_changed(&wm831x_power->battery); | ||
455 | 453 | ||
456 | return IRQ_HANDLED; | 454 | return IRQ_HANDLED; |
457 | } | 455 | } |
@@ -481,15 +479,14 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data) | |||
481 | dev_dbg(wm831x->dev, "Power source changed\n"); | 479 | dev_dbg(wm831x->dev, "Power source changed\n"); |
482 | 480 | ||
483 | /* Just notify for everything - little harm in overnotifying. */ | 481 | /* Just notify for everything - little harm in overnotifying. */ |
484 | if (wm831x_power->have_battery) | 482 | power_supply_changed(&wm831x_power->battery); |
485 | power_supply_changed(&wm831x_power->battery); | ||
486 | power_supply_changed(&wm831x_power->usb); | 483 | power_supply_changed(&wm831x_power->usb); |
487 | power_supply_changed(&wm831x_power->wall); | 484 | power_supply_changed(&wm831x_power->wall); |
488 | 485 | ||
489 | return IRQ_HANDLED; | 486 | return IRQ_HANDLED; |
490 | } | 487 | } |
491 | 488 | ||
492 | static int wm831x_power_probe(struct platform_device *pdev) | 489 | static __devinit int wm831x_power_probe(struct platform_device *pdev) |
493 | { | 490 | { |
494 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | 491 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); |
495 | struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data; | 492 | struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data; |
@@ -540,6 +537,15 @@ static int wm831x_power_probe(struct platform_device *pdev) | |||
540 | if (ret) | 537 | if (ret) |
541 | goto err_kmalloc; | 538 | goto err_kmalloc; |
542 | 539 | ||
540 | battery->name = power->battery_name; | ||
541 | battery->properties = wm831x_bat_props; | ||
542 | battery->num_properties = ARRAY_SIZE(wm831x_bat_props); | ||
543 | battery->get_property = wm831x_bat_get_prop; | ||
544 | battery->use_for_apm = 1; | ||
545 | ret = power_supply_register(&pdev->dev, battery); | ||
546 | if (ret) | ||
547 | goto err_wall; | ||
548 | |||
543 | usb->name = power->usb_name, | 549 | usb->name = power->usb_name, |
544 | usb->type = POWER_SUPPLY_TYPE_USB; | 550 | usb->type = POWER_SUPPLY_TYPE_USB; |
545 | usb->properties = wm831x_usb_props; | 551 | usb->properties = wm831x_usb_props; |
@@ -547,35 +553,19 @@ static int wm831x_power_probe(struct platform_device *pdev) | |||
547 | usb->get_property = wm831x_usb_get_prop; | 553 | usb->get_property = wm831x_usb_get_prop; |
548 | ret = power_supply_register(&pdev->dev, usb); | 554 | ret = power_supply_register(&pdev->dev, usb); |
549 | if (ret) | 555 | if (ret) |
550 | goto err_wall; | 556 | goto err_battery; |
551 | |||
552 | ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_1); | ||
553 | if (ret < 0) | ||
554 | goto err_wall; | ||
555 | power->have_battery = ret & WM831X_CHG_ENA; | ||
556 | |||
557 | if (power->have_battery) { | ||
558 | battery->name = power->battery_name; | ||
559 | battery->properties = wm831x_bat_props; | ||
560 | battery->num_properties = ARRAY_SIZE(wm831x_bat_props); | ||
561 | battery->get_property = wm831x_bat_get_prop; | ||
562 | battery->use_for_apm = 1; | ||
563 | ret = power_supply_register(&pdev->dev, battery); | ||
564 | if (ret) | ||
565 | goto err_usb; | ||
566 | } | ||
567 | 557 | ||
568 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); | 558 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
569 | ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, | 559 | ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, |
570 | IRQF_TRIGGER_RISING, "System power low", | 560 | IRQF_TRIGGER_RISING, "System power low", |
571 | power); | 561 | power); |
572 | if (ret != 0) { | 562 | if (ret != 0) { |
573 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", | 563 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", |
574 | irq, ret); | 564 | irq, ret); |
575 | goto err_battery; | 565 | goto err_usb; |
576 | } | 566 | } |
577 | 567 | ||
578 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); | 568 | irq = platform_get_irq_byname(pdev, "PWR SRC"); |
579 | ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, | 569 | ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, |
580 | IRQF_TRIGGER_RISING, "Power source", | 570 | IRQF_TRIGGER_RISING, "Power source", |
581 | power); | 571 | power); |
@@ -586,9 +576,7 @@ static int wm831x_power_probe(struct platform_device *pdev) | |||
586 | } | 576 | } |
587 | 577 | ||
588 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { | 578 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { |
589 | irq = wm831x_irq(wm831x, | 579 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); |
590 | platform_get_irq_byname(pdev, | ||
591 | wm831x_bat_irqs[i])); | ||
592 | ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, | 580 | ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, |
593 | IRQF_TRIGGER_RISING, | 581 | IRQF_TRIGGER_RISING, |
594 | wm831x_bat_irqs[i], | 582 | wm831x_bat_irqs[i], |
@@ -608,16 +596,15 @@ err_bat_irq: | |||
608 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); | 596 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); |
609 | free_irq(irq, power); | 597 | free_irq(irq, power); |
610 | } | 598 | } |
611 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); | 599 | irq = platform_get_irq_byname(pdev, "PWR SRC"); |
612 | free_irq(irq, power); | 600 | free_irq(irq, power); |
613 | err_syslo: | 601 | err_syslo: |
614 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); | 602 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
615 | free_irq(irq, power); | 603 | free_irq(irq, power); |
616 | err_battery: | ||
617 | if (power->have_battery) | ||
618 | power_supply_unregister(battery); | ||
619 | err_usb: | 604 | err_usb: |
620 | power_supply_unregister(usb); | 605 | power_supply_unregister(usb); |
606 | err_battery: | ||
607 | power_supply_unregister(battery); | ||
621 | err_wall: | 608 | err_wall: |
622 | power_supply_unregister(wall); | 609 | power_supply_unregister(wall); |
623 | err_kmalloc: | 610 | err_kmalloc: |
@@ -625,27 +612,23 @@ err_kmalloc: | |||
625 | return ret; | 612 | return ret; |
626 | } | 613 | } |
627 | 614 | ||
628 | static int wm831x_power_remove(struct platform_device *pdev) | 615 | static __devexit int wm831x_power_remove(struct platform_device *pdev) |
629 | { | 616 | { |
630 | struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); | 617 | struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); |
631 | struct wm831x *wm831x = wm831x_power->wm831x; | ||
632 | int irq, i; | 618 | int irq, i; |
633 | 619 | ||
634 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { | 620 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { |
635 | irq = wm831x_irq(wm831x, | 621 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); |
636 | platform_get_irq_byname(pdev, | ||
637 | wm831x_bat_irqs[i])); | ||
638 | free_irq(irq, wm831x_power); | 622 | free_irq(irq, wm831x_power); |
639 | } | 623 | } |
640 | 624 | ||
641 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); | 625 | irq = platform_get_irq_byname(pdev, "PWR SRC"); |
642 | free_irq(irq, wm831x_power); | 626 | free_irq(irq, wm831x_power); |
643 | 627 | ||
644 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); | 628 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
645 | free_irq(irq, wm831x_power); | 629 | free_irq(irq, wm831x_power); |
646 | 630 | ||
647 | if (wm831x_power->have_battery) | 631 | power_supply_unregister(&wm831x_power->battery); |
648 | power_supply_unregister(&wm831x_power->battery); | ||
649 | power_supply_unregister(&wm831x_power->wall); | 632 | power_supply_unregister(&wm831x_power->wall); |
650 | power_supply_unregister(&wm831x_power->usb); | 633 | power_supply_unregister(&wm831x_power->usb); |
651 | kfree(wm831x_power); | 634 | kfree(wm831x_power); |
@@ -654,13 +637,23 @@ static int wm831x_power_remove(struct platform_device *pdev) | |||
654 | 637 | ||
655 | static struct platform_driver wm831x_power_driver = { | 638 | static struct platform_driver wm831x_power_driver = { |
656 | .probe = wm831x_power_probe, | 639 | .probe = wm831x_power_probe, |
657 | .remove = wm831x_power_remove, | 640 | .remove = __devexit_p(wm831x_power_remove), |
658 | .driver = { | 641 | .driver = { |
659 | .name = "wm831x-power", | 642 | .name = "wm831x-power", |
660 | }, | 643 | }, |
661 | }; | 644 | }; |
662 | 645 | ||
663 | module_platform_driver(wm831x_power_driver); | 646 | static int __init wm831x_power_init(void) |
647 | { | ||
648 | return platform_driver_register(&wm831x_power_driver); | ||
649 | } | ||
650 | module_init(wm831x_power_init); | ||
651 | |||
652 | static void __exit wm831x_power_exit(void) | ||
653 | { | ||
654 | platform_driver_unregister(&wm831x_power_driver); | ||
655 | } | ||
656 | module_exit(wm831x_power_exit); | ||
664 | 657 | ||
665 | MODULE_DESCRIPTION("Power supply driver for WM831x PMICs"); | 658 | MODULE_DESCRIPTION("Power supply driver for WM831x PMICs"); |
666 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 659 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c index b3607e2906d..0693902d615 100644 --- a/drivers/power/wm8350_power.c +++ b/drivers/power/wm8350_power.c | |||
@@ -442,7 +442,7 @@ static void free_charger_irq(struct wm8350 *wm8350) | |||
442 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350); | 442 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350); |
443 | } | 443 | } |
444 | 444 | ||
445 | static int wm8350_power_probe(struct platform_device *pdev) | 445 | static __devinit int wm8350_power_probe(struct platform_device *pdev) |
446 | { | 446 | { |
447 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 447 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); |
448 | struct wm8350_power *power = &wm8350->power; | 448 | struct wm8350_power *power = &wm8350->power; |
@@ -501,7 +501,7 @@ battery_failed: | |||
501 | return ret; | 501 | return ret; |
502 | } | 502 | } |
503 | 503 | ||
504 | static int wm8350_power_remove(struct platform_device *pdev) | 504 | static __devexit int wm8350_power_remove(struct platform_device *pdev) |
505 | { | 505 | { |
506 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 506 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); |
507 | struct wm8350_power *power = &wm8350->power; | 507 | struct wm8350_power *power = &wm8350->power; |
@@ -516,13 +516,23 @@ static int wm8350_power_remove(struct platform_device *pdev) | |||
516 | 516 | ||
517 | static struct platform_driver wm8350_power_driver = { | 517 | static struct platform_driver wm8350_power_driver = { |
518 | .probe = wm8350_power_probe, | 518 | .probe = wm8350_power_probe, |
519 | .remove = wm8350_power_remove, | 519 | .remove = __devexit_p(wm8350_power_remove), |
520 | .driver = { | 520 | .driver = { |
521 | .name = "wm8350-power", | 521 | .name = "wm8350-power", |
522 | }, | 522 | }, |
523 | }; | 523 | }; |
524 | 524 | ||
525 | module_platform_driver(wm8350_power_driver); | 525 | static int __init wm8350_power_init(void) |
526 | { | ||
527 | return platform_driver_register(&wm8350_power_driver); | ||
528 | } | ||
529 | module_init(wm8350_power_init); | ||
530 | |||
531 | static void __exit wm8350_power_exit(void) | ||
532 | { | ||
533 | platform_driver_unregister(&wm8350_power_driver); | ||
534 | } | ||
535 | module_exit(wm8350_power_exit); | ||
526 | 536 | ||
527 | MODULE_LICENSE("GPL"); | 537 | MODULE_LICENSE("GPL"); |
528 | MODULE_DESCRIPTION("Power supply driver for WM8350"); | 538 | MODULE_DESCRIPTION("Power supply driver for WM8350"); |
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c index 58f7348e6c2..156559e56fa 100644 --- a/drivers/power/wm97xx_battery.c +++ b/drivers/power/wm97xx_battery.c | |||
@@ -25,8 +25,9 @@ | |||
25 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | 27 | ||
28 | static DEFINE_MUTEX(bat_lock); | ||
28 | static struct work_struct bat_work; | 29 | static struct work_struct bat_work; |
29 | static DEFINE_MUTEX(work_lock); | 30 | static struct mutex work_lock; |
30 | static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; | 31 | static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; |
31 | static enum power_supply_property *prop; | 32 | static enum power_supply_property *prop; |
32 | 33 | ||
@@ -146,7 +147,7 @@ static irqreturn_t wm97xx_chrg_irq(int irq, void *data) | |||
146 | #ifdef CONFIG_PM | 147 | #ifdef CONFIG_PM |
147 | static int wm97xx_bat_suspend(struct device *dev) | 148 | static int wm97xx_bat_suspend(struct device *dev) |
148 | { | 149 | { |
149 | flush_work(&bat_work); | 150 | flush_work_sync(&bat_work); |
150 | return 0; | 151 | return 0; |
151 | } | 152 | } |
152 | 153 | ||
@@ -162,7 +163,7 @@ static const struct dev_pm_ops wm97xx_bat_pm_ops = { | |||
162 | }; | 163 | }; |
163 | #endif | 164 | #endif |
164 | 165 | ||
165 | static int wm97xx_bat_probe(struct platform_device *dev) | 166 | static int __devinit wm97xx_bat_probe(struct platform_device *dev) |
166 | { | 167 | { |
167 | int ret = 0; | 168 | int ret = 0; |
168 | int props = 1; /* POWER_SUPPLY_PROP_PRESENT */ | 169 | int props = 1; /* POWER_SUPPLY_PROP_PRESENT */ |
@@ -180,6 +181,8 @@ static int wm97xx_bat_probe(struct platform_device *dev) | |||
180 | if (dev->id != -1) | 181 | if (dev->id != -1) |
181 | return -EINVAL; | 182 | return -EINVAL; |
182 | 183 | ||
184 | mutex_init(&work_lock); | ||
185 | |||
183 | if (!pdata) { | 186 | if (!pdata) { |
184 | dev_err(&dev->dev, "No platform_data supplied\n"); | 187 | dev_err(&dev->dev, "No platform_data supplied\n"); |
185 | return -EINVAL; | 188 | return -EINVAL; |
@@ -193,7 +196,7 @@ static int wm97xx_bat_probe(struct platform_device *dev) | |||
193 | if (ret) | 196 | if (ret) |
194 | goto err2; | 197 | goto err2; |
195 | ret = request_irq(gpio_to_irq(pdata->charge_gpio), | 198 | ret = request_irq(gpio_to_irq(pdata->charge_gpio), |
196 | wm97xx_chrg_irq, 0, | 199 | wm97xx_chrg_irq, IRQF_DISABLED, |
197 | "AC Detect", dev); | 200 | "AC Detect", dev); |
198 | if (ret) | 201 | if (ret) |
199 | goto err2; | 202 | goto err2; |
@@ -212,10 +215,8 @@ static int wm97xx_bat_probe(struct platform_device *dev) | |||
212 | props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ | 215 | props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ |
213 | 216 | ||
214 | prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); | 217 | prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); |
215 | if (!prop) { | 218 | if (!prop) |
216 | ret = -ENOMEM; | ||
217 | goto err3; | 219 | goto err3; |
218 | } | ||
219 | 220 | ||
220 | prop[i++] = POWER_SUPPLY_PROP_PRESENT; | 221 | prop[i++] = POWER_SUPPLY_PROP_PRESENT; |
221 | if (pdata->charge_gpio >= 0) | 222 | if (pdata->charge_gpio >= 0) |
@@ -263,7 +264,7 @@ err: | |||
263 | return ret; | 264 | return ret; |
264 | } | 265 | } |
265 | 266 | ||
266 | static int wm97xx_bat_remove(struct platform_device *dev) | 267 | static int __devexit wm97xx_bat_remove(struct platform_device *dev) |
267 | { | 268 | { |
268 | struct wm97xx_pdata *wmdata = dev->dev.platform_data; | 269 | struct wm97xx_pdata *wmdata = dev->dev.platform_data; |
269 | struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; | 270 | struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; |
@@ -287,10 +288,21 @@ static struct platform_driver wm97xx_bat_driver = { | |||
287 | #endif | 288 | #endif |
288 | }, | 289 | }, |
289 | .probe = wm97xx_bat_probe, | 290 | .probe = wm97xx_bat_probe, |
290 | .remove = wm97xx_bat_remove, | 291 | .remove = __devexit_p(wm97xx_bat_remove), |
291 | }; | 292 | }; |
292 | 293 | ||
293 | module_platform_driver(wm97xx_bat_driver); | 294 | static int __init wm97xx_bat_init(void) |
295 | { | ||
296 | return platform_driver_register(&wm97xx_bat_driver); | ||
297 | } | ||
298 | |||
299 | static void __exit wm97xx_bat_exit(void) | ||
300 | { | ||
301 | platform_driver_unregister(&wm97xx_bat_driver); | ||
302 | } | ||
303 | |||
304 | module_init(wm97xx_bat_init); | ||
305 | module_exit(wm97xx_bat_exit); | ||
294 | 306 | ||
295 | MODULE_LICENSE("GPL"); | 307 | MODULE_LICENSE("GPL"); |
296 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | 308 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); |
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c index 814d2e31f0c..d119c38b3ff 100644 --- a/drivers/power/z2_battery.c +++ b/drivers/power/z2_battery.c | |||
@@ -180,7 +180,7 @@ static int z2_batt_ps_init(struct z2_charger *charger, int props) | |||
180 | return 0; | 180 | return 0; |
181 | } | 181 | } |
182 | 182 | ||
183 | static int z2_batt_probe(struct i2c_client *client, | 183 | static int __devinit z2_batt_probe(struct i2c_client *client, |
184 | const struct i2c_device_id *id) | 184 | const struct i2c_device_id *id) |
185 | { | 185 | { |
186 | int ret = 0; | 186 | int ret = 0; |
@@ -218,7 +218,7 @@ static int z2_batt_probe(struct i2c_client *client, | |||
218 | irq_set_irq_type(gpio_to_irq(info->charge_gpio), | 218 | irq_set_irq_type(gpio_to_irq(info->charge_gpio), |
219 | IRQ_TYPE_EDGE_BOTH); | 219 | IRQ_TYPE_EDGE_BOTH); |
220 | ret = request_irq(gpio_to_irq(info->charge_gpio), | 220 | ret = request_irq(gpio_to_irq(info->charge_gpio), |
221 | z2_charge_switch_irq, 0, | 221 | z2_charge_switch_irq, IRQF_DISABLED, |
222 | "AC Detect", charger); | 222 | "AC Detect", charger); |
223 | if (ret) | 223 | if (ret) |
224 | goto err3; | 224 | goto err3; |
@@ -251,7 +251,7 @@ err: | |||
251 | return ret; | 251 | return ret; |
252 | } | 252 | } |
253 | 253 | ||
254 | static int z2_batt_remove(struct i2c_client *client) | 254 | static int __devexit z2_batt_remove(struct i2c_client *client) |
255 | { | 255 | { |
256 | struct z2_charger *charger = i2c_get_clientdata(client); | 256 | struct z2_charger *charger = i2c_get_clientdata(client); |
257 | struct z2_battery_info *info = charger->info; | 257 | struct z2_battery_info *info = charger->info; |
@@ -276,7 +276,7 @@ static int z2_batt_suspend(struct device *dev) | |||
276 | struct i2c_client *client = to_i2c_client(dev); | 276 | struct i2c_client *client = to_i2c_client(dev); |
277 | struct z2_charger *charger = i2c_get_clientdata(client); | 277 | struct z2_charger *charger = i2c_get_clientdata(client); |
278 | 278 | ||
279 | flush_work(&charger->bat_work); | 279 | flush_work_sync(&charger->bat_work); |
280 | return 0; | 280 | return 0; |
281 | } | 281 | } |
282 | 282 | ||
@@ -316,7 +316,19 @@ static struct i2c_driver z2_batt_driver = { | |||
316 | .remove = z2_batt_remove, | 316 | .remove = z2_batt_remove, |
317 | .id_table = z2_batt_id, | 317 | .id_table = z2_batt_id, |
318 | }; | 318 | }; |
319 | module_i2c_driver(z2_batt_driver); | 319 | |
320 | static int __init z2_batt_init(void) | ||
321 | { | ||
322 | return i2c_add_driver(&z2_batt_driver); | ||
323 | } | ||
324 | |||
325 | static void __exit z2_batt_exit(void) | ||
326 | { | ||
327 | i2c_del_driver(&z2_batt_driver); | ||
328 | } | ||
329 | |||
330 | module_init(z2_batt_init); | ||
331 | module_exit(z2_batt_exit); | ||
320 | 332 | ||
321 | MODULE_LICENSE("GPL"); | 333 | MODULE_LICENSE("GPL"); |
322 | MODULE_AUTHOR("Peter Edwards <sweetlilmre@gmail.com>"); | 334 | MODULE_AUTHOR("Peter Edwards <sweetlilmre@gmail.com>"); |