blob: a9486f1a1b5b394ad6e704db06679e2d87b28bc4 [file] [log] [blame]
Arun Murthy1f855822012-02-29 21:54:28 +05301/*
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>
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -080023#include <linux/jiffies.h>
24#include <linux/of.h>
25#include <linux/mfd/core.h>
Arun Murthy1f855822012-02-29 21:54:28 +053026#include <linux/mfd/abx500.h>
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -080027#include <linux/mfd/abx500/ab8500.h>
Arun Murthy1f855822012-02-29 21:54:28 +053028#include <linux/mfd/abx500/ab8500-bm.h>
29#include <linux/mfd/abx500/ab8500-gpadc.h>
Arun Murthy1f855822012-02-29 21:54:28 +053030
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
Michel JAOUENe6aac612012-05-22 15:46:46 +020042#define BTEMP_BATCTRL_CURR_SRC_16UA 16
43#define BTEMP_BATCTRL_CURR_SRC_18UA 18
44
Lee Jones861a30d2012-08-29 20:36:51 +080045#define BTEMP_BATCTRL_CURR_SRC_60UA 60
46#define BTEMP_BATCTRL_CURR_SRC_120UA 120
47
Arun Murthy1f855822012-02-29 21:54:28 +053048#define to_ab8500_btemp_device_info(x) container_of((x), \
49 struct ab8500_btemp, btemp_psy);
50
51/**
52 * struct ab8500_btemp_interrupts - ab8500 interrupts
53 * @name: name of the interrupt
54 * @isr function pointer to the isr
55 */
56struct ab8500_btemp_interrupts {
57 char *name;
58 irqreturn_t (*isr)(int irq, void *data);
59};
60
61struct ab8500_btemp_events {
62 bool batt_rem;
63 bool btemp_high;
64 bool btemp_medhigh;
65 bool btemp_lowmed;
66 bool btemp_low;
67 bool ac_conn;
68 bool usb_conn;
69};
70
71struct ab8500_btemp_ranges {
72 int btemp_high_limit;
73 int btemp_med_limit;
74 int btemp_low_limit;
75};
76
77/**
78 * struct ab8500_btemp - ab8500 BTEMP device information
79 * @dev: Pointer to the structure device
80 * @node: List of AB8500 BTEMPs, hence prepared for reentrance
81 * @curr_source: What current source we use, in uA
Hakan Berg908fe8d2012-07-17 14:17:16 +020082 * @bat_temp: Dispatched battery temperature in degree Celcius
83 * @prev_bat_temp Last measured battery temperature in degree Celcius
Arun Murthy1f855822012-02-29 21:54:28 +053084 * @parent: Pointer to the struct ab8500
85 * @gpadc: Pointer to the struct gpadc
86 * @fg: Pointer to the struct fg
Lee Jonesb0284de2012-11-30 10:09:42 +000087 * @bm: Platform specific battery management information
Arun Murthy1f855822012-02-29 21:54:28 +053088 * @btemp_psy: Structure for BTEMP specific battery properties
89 * @events: Structure for information about events triggered
90 * @btemp_ranges: Battery temperature range structure
91 * @btemp_wq: Work queue for measuring the temperature periodically
92 * @btemp_periodic_work: Work for measuring the temperature periodically
Jonas Aabergf6271b42012-02-27 11:02:44 +010093 * @initialized: True if battery id read.
Arun Murthy1f855822012-02-29 21:54:28 +053094 */
95struct ab8500_btemp {
96 struct device *dev;
97 struct list_head node;
98 int curr_source;
99 int bat_temp;
100 int prev_bat_temp;
101 struct ab8500 *parent;
102 struct ab8500_gpadc *gpadc;
103 struct ab8500_fg *fg;
Lee Jonesb0284de2012-11-30 10:09:42 +0000104 struct abx500_bm_data *bm;
Arun Murthy1f855822012-02-29 21:54:28 +0530105 struct power_supply btemp_psy;
106 struct ab8500_btemp_events events;
107 struct ab8500_btemp_ranges btemp_ranges;
108 struct workqueue_struct *btemp_wq;
109 struct delayed_work btemp_periodic_work;
Jonas Aabergf6271b42012-02-27 11:02:44 +0100110 bool initialized;
Arun Murthy1f855822012-02-29 21:54:28 +0530111};
112
113/* BTEMP power supply properties */
114static enum power_supply_property ab8500_btemp_props[] = {
115 POWER_SUPPLY_PROP_PRESENT,
116 POWER_SUPPLY_PROP_ONLINE,
117 POWER_SUPPLY_PROP_TECHNOLOGY,
118 POWER_SUPPLY_PROP_TEMP,
119};
120
121static LIST_HEAD(ab8500_btemp_list);
122
123/**
124 * ab8500_btemp_get() - returns a reference to the primary AB8500 BTEMP
125 * (i.e. the first BTEMP in the instance list)
126 */
127struct ab8500_btemp *ab8500_btemp_get(void)
128{
129 struct ab8500_btemp *btemp;
130 btemp = list_first_entry(&ab8500_btemp_list, struct ab8500_btemp, node);
131
132 return btemp;
133}
134
135/**
136 * ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance
137 * @di: pointer to the ab8500_btemp structure
138 * @v_batctrl: measured batctrl voltage
139 * @inst_curr: measured instant current
140 *
141 * This function returns the battery resistance that is
142 * derived from the BATCTRL voltage.
143 * Returns value in Ohms.
144 */
145static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
146 int v_batctrl, int inst_curr)
147{
148 int rbs;
149
150 if (is_ab8500_1p1_or_earlier(di->parent)) {
151 /*
152 * For ABB cut1.0 and 1.1 BAT_CTRL is internally
153 * connected to 1.8V through a 450k resistor
154 */
155 return (450000 * (v_batctrl)) / (1800 - v_batctrl);
156 }
157
Lee Jonesb0284de2012-11-30 10:09:42 +0000158 if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
Arun Murthy1f855822012-02-29 21:54:28 +0530159 /*
160 * If the battery has internal NTC, we use the current
Marcus Cooper7a2cf9b2012-11-28 14:42:59 +0100161 * source to calculate the resistance.
Arun Murthy1f855822012-02-29 21:54:28 +0530162 */
163 rbs = (v_batctrl * 1000
Lee Jonesb0284de2012-11-30 10:09:42 +0000164 - di->bm->gnd_lift_resistance * inst_curr)
Arun Murthy1f855822012-02-29 21:54:28 +0530165 / di->curr_source;
166 } else {
167 /*
168 * BAT_CTRL is internally
169 * connected to 1.8V through a 80k resistor
170 */
171 rbs = (80000 * (v_batctrl)) / (1800 - v_batctrl);
172 }
173
174 return rbs;
175}
176
177/**
178 * ab8500_btemp_read_batctrl_voltage() - measure batctrl voltage
179 * @di: pointer to the ab8500_btemp structure
180 *
181 * This function returns the voltage on BATCTRL. Returns value in mV.
182 */
183static int ab8500_btemp_read_batctrl_voltage(struct ab8500_btemp *di)
184{
185 int vbtemp;
186 static int prev;
187
188 vbtemp = ab8500_gpadc_convert(di->gpadc, BAT_CTRL);
189 if (vbtemp < 0) {
190 dev_err(di->dev,
191 "%s gpadc conversion failed, using previous value",
192 __func__);
193 return prev;
194 }
195 prev = vbtemp;
196 return vbtemp;
197}
198
199/**
200 * ab8500_btemp_curr_source_enable() - enable/disable batctrl current source
201 * @di: pointer to the ab8500_btemp structure
202 * @enable: enable or disable the current source
203 *
204 * Enable or disable the current sources for the BatCtrl AD channel
205 */
206static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
207 bool enable)
208{
209 int curr;
210 int ret = 0;
211
212 /*
213 * BATCTRL current sources are included on AB8500 cut2.0
214 * and future versions
215 */
216 if (is_ab8500_1p1_or_earlier(di->parent))
217 return 0;
218
219 /* Only do this for batteries with internal NTC */
Lee Jonesb0284de2012-11-30 10:09:42 +0000220 if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
Michel JAOUENe6aac612012-05-22 15:46:46 +0200221
Lee Jones861a30d2012-08-29 20:36:51 +0800222 if (is_ab8540(di->parent)) {
223 if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_60UA)
224 curr = BAT_CTRL_60U_ENA;
225 else
226 curr = BAT_CTRL_120U_ENA;
227 } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
Michel JAOUENe6aac612012-05-22 15:46:46 +0200228 if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA)
229 curr = BAT_CTRL_16U_ENA;
230 else
231 curr = BAT_CTRL_18U_ENA;
232 } else {
233 if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
234 curr = BAT_CTRL_7U_ENA;
235 else
236 curr = BAT_CTRL_20U_ENA;
237 }
Arun Murthy1f855822012-02-29 21:54:28 +0530238
239 dev_dbg(di->dev, "Set BATCTRL %duA\n", di->curr_source);
240
241 ret = abx500_mask_and_set_register_interruptible(di->dev,
242 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
243 FORCE_BAT_CTRL_CMP_HIGH, FORCE_BAT_CTRL_CMP_HIGH);
244 if (ret) {
245 dev_err(di->dev, "%s failed setting cmp_force\n",
246 __func__);
247 return ret;
248 }
249
250 /*
251 * We have to wait one 32kHz cycle before enabling
252 * the current source, since ForceBatCtrlCmpHigh needs
253 * to be written in a separate cycle
254 */
255 udelay(32);
256
257 ret = abx500_set_register_interruptible(di->dev,
258 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
259 FORCE_BAT_CTRL_CMP_HIGH | curr);
260 if (ret) {
261 dev_err(di->dev, "%s failed enabling current source\n",
262 __func__);
263 goto disable_curr_source;
264 }
Lee Jonesb0284de2012-11-30 10:09:42 +0000265 } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
Arun Murthy1f855822012-02-29 21:54:28 +0530266 dev_dbg(di->dev, "Disable BATCTRL curr source\n");
267
Lee Jones861a30d2012-08-29 20:36:51 +0800268 if (is_ab8540(di->parent)) {
269 /* Write 0 to the curr bits */
270 ret = abx500_mask_and_set_register_interruptible(
271 di->dev,
272 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
273 BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
274 ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
275 } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
Michel JAOUENe6aac612012-05-22 15:46:46 +0200276 /* Write 0 to the curr bits */
277 ret = abx500_mask_and_set_register_interruptible(
278 di->dev,
279 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
280 BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA,
281 ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA));
282 } else {
283 /* Write 0 to the curr bits */
284 ret = abx500_mask_and_set_register_interruptible(
285 di->dev,
286 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
287 BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
288 ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
289 }
290
Arun Murthy1f855822012-02-29 21:54:28 +0530291 if (ret) {
292 dev_err(di->dev, "%s failed disabling current source\n",
293 __func__);
294 goto disable_curr_source;
295 }
296
297 /* Enable Pull-Up and comparator */
298 ret = abx500_mask_and_set_register_interruptible(di->dev,
299 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
300 BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA,
301 BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA);
302 if (ret) {
303 dev_err(di->dev, "%s failed enabling PU and comp\n",
304 __func__);
305 goto enable_pu_comp;
306 }
307
308 /*
309 * We have to wait one 32kHz cycle before disabling
310 * ForceBatCtrlCmpHigh since this needs to be written
311 * in a separate cycle
312 */
313 udelay(32);
314
315 /* Disable 'force comparator' */
316 ret = abx500_mask_and_set_register_interruptible(di->dev,
317 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
318 FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH);
319 if (ret) {
320 dev_err(di->dev, "%s failed disabling force comp\n",
321 __func__);
322 goto disable_force_comp;
323 }
324 }
325 return ret;
326
327 /*
328 * We have to try unsetting FORCE_BAT_CTRL_CMP_HIGH one more time
329 * if we got an error above
330 */
331disable_curr_source:
Lee Jones861a30d2012-08-29 20:36:51 +0800332 if (is_ab8540(di->parent)) {
333 /* Write 0 to the curr bits */
334 ret = abx500_mask_and_set_register_interruptible(di->dev,
335 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
336 BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
337 ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
338 } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
Michel JAOUENe6aac612012-05-22 15:46:46 +0200339 /* Write 0 to the curr bits */
340 ret = abx500_mask_and_set_register_interruptible(di->dev,
341 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
342 BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA,
343 ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA));
344 } else {
345 /* Write 0 to the curr bits */
346 ret = abx500_mask_and_set_register_interruptible(di->dev,
Arun Murthy1f855822012-02-29 21:54:28 +0530347 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
348 BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
349 ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
Michel JAOUENe6aac612012-05-22 15:46:46 +0200350 }
351
Arun Murthy1f855822012-02-29 21:54:28 +0530352 if (ret) {
353 dev_err(di->dev, "%s failed disabling current source\n",
354 __func__);
355 return ret;
356 }
357enable_pu_comp:
358 /* Enable Pull-Up and comparator */
359 ret = abx500_mask_and_set_register_interruptible(di->dev,
360 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
361 BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA,
362 BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA);
363 if (ret) {
364 dev_err(di->dev, "%s failed enabling PU and comp\n",
365 __func__);
366 return ret;
367 }
368
369disable_force_comp:
370 /*
371 * We have to wait one 32kHz cycle before disabling
372 * ForceBatCtrlCmpHigh since this needs to be written
373 * in a separate cycle
374 */
375 udelay(32);
376
377 /* Disable 'force comparator' */
378 ret = abx500_mask_and_set_register_interruptible(di->dev,
379 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
380 FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH);
381 if (ret) {
382 dev_err(di->dev, "%s failed disabling force comp\n",
383 __func__);
384 return ret;
385 }
386
387 return ret;
388}
389
390/**
391 * ab8500_btemp_get_batctrl_res() - get battery resistance
392 * @di: pointer to the ab8500_btemp structure
393 *
394 * This function returns the battery pack identification resistance.
395 * Returns value in Ohms.
396 */
397static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di)
398{
399 int ret;
400 int batctrl = 0;
401 int res;
402 int inst_curr;
403 int i;
404
405 /*
406 * BATCTRL current sources are included on AB8500 cut2.0
407 * and future versions
408 */
409 ret = ab8500_btemp_curr_source_enable(di, true);
410 if (ret) {
411 dev_err(di->dev, "%s curr source enabled failed\n", __func__);
412 return ret;
413 }
414
415 if (!di->fg)
416 di->fg = ab8500_fg_get();
417 if (!di->fg) {
418 dev_err(di->dev, "No fg found\n");
419 return -EINVAL;
420 }
421
422 ret = ab8500_fg_inst_curr_start(di->fg);
423
424 if (ret) {
425 dev_err(di->dev, "Failed to start current measurement\n");
426 return ret;
427 }
428
Johan Bjornstedt3988a4d2013-01-11 13:12:50 +0000429 do {
430 msleep(20);
431 } while (!ab8500_fg_inst_curr_started(di->fg));
432
Arun Murthy1f855822012-02-29 21:54:28 +0530433 i = 0;
434
435 do {
436 batctrl += ab8500_btemp_read_batctrl_voltage(di);
437 i++;
438 msleep(20);
439 } while (!ab8500_fg_inst_curr_done(di->fg));
440 batctrl /= i;
441
442 ret = ab8500_fg_inst_curr_finalize(di->fg, &inst_curr);
443 if (ret) {
444 dev_err(di->dev, "Failed to finalize current measurement\n");
445 return ret;
446 }
447
448 res = ab8500_btemp_batctrl_volt_to_res(di, batctrl, inst_curr);
449
450 ret = ab8500_btemp_curr_source_enable(di, false);
451 if (ret) {
452 dev_err(di->dev, "%s curr source disable failed\n", __func__);
453 return ret;
454 }
455
456 dev_dbg(di->dev, "%s batctrl: %d res: %d inst_curr: %d samples: %d\n",
457 __func__, batctrl, res, inst_curr, i);
458
459 return res;
460}
461
462/**
463 * ab8500_btemp_res_to_temp() - resistance to temperature
464 * @di: pointer to the ab8500_btemp structure
465 * @tbl: pointer to the resiatance to temperature table
466 * @tbl_size: size of the resistance to temperature table
467 * @res: resistance to calculate the temperature from
468 *
469 * This function returns the battery temperature in degrees Celcius
470 * based on the NTC resistance.
471 */
472static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di,
473 const struct abx500_res_to_temp *tbl, int tbl_size, int res)
474{
475 int i, temp;
476 /*
477 * Calculate the formula for the straight line
478 * Simple interpolation if we are within
479 * the resistance table limits, extrapolate
480 * if resistance is outside the limits.
481 */
482 if (res > tbl[0].resist)
483 i = 0;
484 else if (res <= tbl[tbl_size - 1].resist)
485 i = tbl_size - 2;
486 else {
487 i = 0;
488 while (!(res <= tbl[i].resist &&
489 res > tbl[i + 1].resist))
490 i++;
491 }
492
493 temp = tbl[i].temp + ((tbl[i + 1].temp - tbl[i].temp) *
494 (res - tbl[i].resist)) / (tbl[i + 1].resist - tbl[i].resist);
495 return temp;
496}
497
498/**
499 * ab8500_btemp_measure_temp() - measure battery temperature
500 * @di: pointer to the ab8500_btemp structure
501 *
502 * Returns battery temperature (on success) else the previous temperature
503 */
504static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
505{
506 int temp;
507 static int prev;
508 int rbat, rntc, vntc;
509 u8 id;
510
Lee Jonesb0284de2012-11-30 10:09:42 +0000511 id = di->bm->batt_id;
Arun Murthy1f855822012-02-29 21:54:28 +0530512
Lee Jonesb0284de2012-11-30 10:09:42 +0000513 if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
Arun Murthy1f855822012-02-29 21:54:28 +0530514 id != BATTERY_UNKNOWN) {
515
516 rbat = ab8500_btemp_get_batctrl_res(di);
517 if (rbat < 0) {
518 dev_err(di->dev, "%s get batctrl res failed\n",
519 __func__);
520 /*
521 * Return out-of-range temperature so that
522 * charging is stopped
523 */
524 return BTEMP_THERMAL_LOW_LIMIT;
525 }
526
527 temp = ab8500_btemp_res_to_temp(di,
Lee Jonesb0284de2012-11-30 10:09:42 +0000528 di->bm->bat_type[id].r_to_t_tbl,
529 di->bm->bat_type[id].n_temp_tbl_elements, rbat);
Arun Murthy1f855822012-02-29 21:54:28 +0530530 } else {
531 vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
532 if (vntc < 0) {
533 dev_err(di->dev,
534 "%s gpadc conversion failed,"
535 " using previous value\n", __func__);
536 return prev;
537 }
538 /*
539 * The PCB NTC is sourced from VTVOUT via a 230kOhm
540 * resistor.
541 */
542 rntc = 230000 * vntc / (VTVOUT_V - vntc);
543
544 temp = ab8500_btemp_res_to_temp(di,
Lee Jonesb0284de2012-11-30 10:09:42 +0000545 di->bm->bat_type[id].r_to_t_tbl,
546 di->bm->bat_type[id].n_temp_tbl_elements, rntc);
Arun Murthy1f855822012-02-29 21:54:28 +0530547 prev = temp;
548 }
549 dev_dbg(di->dev, "Battery temperature is %d\n", temp);
550 return temp;
551}
552
553/**
554 * ab8500_btemp_id() - Identify the connected battery
555 * @di: pointer to the ab8500_btemp structure
556 *
557 * This function will try to identify the battery by reading the ID
558 * resistor. Some brands use a combined ID resistor with a NTC resistor to
559 * both be able to identify and to read the temperature of it.
560 */
561static int ab8500_btemp_id(struct ab8500_btemp *di)
562{
563 int res;
564 u8 i;
Lee Jones861a30d2012-08-29 20:36:51 +0800565 if (is_ab8540(di->parent))
566 di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
567 else if (is_ab9540(di->parent) || is_ab8505(di->parent))
Michel JAOUENe6aac612012-05-22 15:46:46 +0200568 di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
569 else
570 di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
Arun Murthy1f855822012-02-29 21:54:28 +0530571
Lee Jonesb0284de2012-11-30 10:09:42 +0000572 di->bm->batt_id = BATTERY_UNKNOWN;
Arun Murthy1f855822012-02-29 21:54:28 +0530573
574 res = ab8500_btemp_get_batctrl_res(di);
575 if (res < 0) {
576 dev_err(di->dev, "%s get batctrl res failed\n", __func__);
577 return -ENXIO;
578 }
579
580 /* BATTERY_UNKNOWN is defined on position 0, skip it! */
Lee Jonesb0284de2012-11-30 10:09:42 +0000581 for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) {
582 if ((res <= di->bm->bat_type[i].resis_high) &&
583 (res >= di->bm->bat_type[i].resis_low)) {
Arun Murthy1f855822012-02-29 21:54:28 +0530584 dev_dbg(di->dev, "Battery detected on %s"
585 " low %d < res %d < high: %d"
586 " index: %d\n",
Lee Jonesb0284de2012-11-30 10:09:42 +0000587 di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL ?
Arun Murthy1f855822012-02-29 21:54:28 +0530588 "BATCTRL" : "BATTEMP",
Lee Jonesb0284de2012-11-30 10:09:42 +0000589 di->bm->bat_type[i].resis_low, res,
590 di->bm->bat_type[i].resis_high, i);
Arun Murthy1f855822012-02-29 21:54:28 +0530591
Lee Jonesb0284de2012-11-30 10:09:42 +0000592 di->bm->batt_id = i;
Arun Murthy1f855822012-02-29 21:54:28 +0530593 break;
594 }
595 }
596
Lee Jonesb0284de2012-11-30 10:09:42 +0000597 if (di->bm->batt_id == BATTERY_UNKNOWN) {
Arun Murthy1f855822012-02-29 21:54:28 +0530598 dev_warn(di->dev, "Battery identified as unknown"
599 ", resistance %d Ohm\n", res);
600 return -ENXIO;
601 }
602
603 /*
604 * We only have to change current source if the
Marcus Cooper7a2cf9b2012-11-28 14:42:59 +0100605 * detected type is Type 1.
Arun Murthy1f855822012-02-29 21:54:28 +0530606 */
Lee Jonesb0284de2012-11-30 10:09:42 +0000607 if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
Lee Jones861a30d2012-08-29 20:36:51 +0800608 di->bm->batt_id == 1) {
609 if (is_ab8540(di->parent)) {
610 dev_dbg(di->dev,
611 "Set BATCTRL current source to 60uA\n");
612 di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
613 } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
614 dev_dbg(di->dev,
615 "Set BATCTRL current source to 16uA\n");
Michel JAOUENe6aac612012-05-22 15:46:46 +0200616 di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
617 } else {
618 dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
619 di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
620 }
Arun Murthy1f855822012-02-29 21:54:28 +0530621 }
622
Lee Jonesb0284de2012-11-30 10:09:42 +0000623 return di->bm->batt_id;
Arun Murthy1f855822012-02-29 21:54:28 +0530624}
625
626/**
627 * ab8500_btemp_periodic_work() - Measuring the temperature periodically
628 * @work: pointer to the work_struct structure
629 *
630 * Work function for measuring the temperature periodically
631 */
632static void ab8500_btemp_periodic_work(struct work_struct *work)
633{
634 int interval;
Hakan Berg908fe8d2012-07-17 14:17:16 +0200635 int bat_temp;
Arun Murthy1f855822012-02-29 21:54:28 +0530636 struct ab8500_btemp *di = container_of(work,
637 struct ab8500_btemp, btemp_periodic_work.work);
638
Jonas Aabergf6271b42012-02-27 11:02:44 +0100639 if (!di->initialized) {
Jonas Aabergf6271b42012-02-27 11:02:44 +0100640 /* Identify the battery */
641 if (ab8500_btemp_id(di) < 0)
642 dev_warn(di->dev, "failed to identify the battery\n");
643 }
644
Hakan Berg908fe8d2012-07-17 14:17:16 +0200645 bat_temp = ab8500_btemp_measure_temp(di);
646 /*
647 * Filter battery temperature.
648 * Allow direct updates on temperature only if two samples result in
649 * same temperature. Else only allow 1 degree change from previous
650 * reported value in the direction of the new measurement.
651 */
Rupesh Kumar2c4c40a2012-08-22 15:14:22 +0530652 if ((bat_temp == di->prev_bat_temp) || !di->initialized) {
653 if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) {
654 di->initialized = true;
Hakan Berg908fe8d2012-07-17 14:17:16 +0200655 di->bat_temp = bat_temp;
656 power_supply_changed(&di->btemp_psy);
657 }
658 } else if (bat_temp < di->prev_bat_temp) {
659 di->bat_temp--;
660 power_supply_changed(&di->btemp_psy);
661 } else if (bat_temp > di->prev_bat_temp) {
662 di->bat_temp++;
Arun Murthy1f855822012-02-29 21:54:28 +0530663 power_supply_changed(&di->btemp_psy);
664 }
Hakan Berg908fe8d2012-07-17 14:17:16 +0200665 di->prev_bat_temp = bat_temp;
Arun Murthy1f855822012-02-29 21:54:28 +0530666
667 if (di->events.ac_conn || di->events.usb_conn)
Lee Jonesb0284de2012-11-30 10:09:42 +0000668 interval = di->bm->temp_interval_chg;
Arun Murthy1f855822012-02-29 21:54:28 +0530669 else
Lee Jonesb0284de2012-11-30 10:09:42 +0000670 interval = di->bm->temp_interval_nochg;
Arun Murthy1f855822012-02-29 21:54:28 +0530671
672 /* Schedule a new measurement */
673 queue_delayed_work(di->btemp_wq,
674 &di->btemp_periodic_work,
675 round_jiffies(interval * HZ));
676}
677
678/**
679 * ab8500_btemp_batctrlindb_handler() - battery removal detected
680 * @irq: interrupt number
681 * @_di: void pointer that has to address of ab8500_btemp
682 *
683 * Returns IRQ status(IRQ_HANDLED)
684 */
685static irqreturn_t ab8500_btemp_batctrlindb_handler(int irq, void *_di)
686{
687 struct ab8500_btemp *di = _di;
688 dev_err(di->dev, "Battery removal detected!\n");
689
690 di->events.batt_rem = true;
691 power_supply_changed(&di->btemp_psy);
692
693 return IRQ_HANDLED;
694}
695
696/**
697 * ab8500_btemp_templow_handler() - battery temp lower than 10 degrees
698 * @irq: interrupt number
699 * @_di: void pointer that has to address of ab8500_btemp
700 *
701 * Returns IRQ status(IRQ_HANDLED)
702 */
703static irqreturn_t ab8500_btemp_templow_handler(int irq, void *_di)
704{
705 struct ab8500_btemp *di = _di;
706
Hakan Bergd36e3e62013-01-11 13:12:57 +0000707 if (is_ab8500_3p3_or_earlier(di->parent)) {
Arun Murthy1f855822012-02-29 21:54:28 +0530708 dev_dbg(di->dev, "Ignore false btemp low irq"
Hakan Bergd36e3e62013-01-11 13:12:57 +0000709 " for ABB cut 1.0, 1.1, 2.0 and 3.3\n");
Arun Murthy1f855822012-02-29 21:54:28 +0530710 } else {
711 dev_crit(di->dev, "Battery temperature lower than -10deg c\n");
712
713 di->events.btemp_low = true;
714 di->events.btemp_high = false;
715 di->events.btemp_medhigh = false;
716 di->events.btemp_lowmed = false;
717 power_supply_changed(&di->btemp_psy);
718 }
719
720 return IRQ_HANDLED;
721}
722
723/**
724 * ab8500_btemp_temphigh_handler() - battery temp higher than max temp
725 * @irq: interrupt number
726 * @_di: void pointer that has to address of ab8500_btemp
727 *
728 * Returns IRQ status(IRQ_HANDLED)
729 */
730static irqreturn_t ab8500_btemp_temphigh_handler(int irq, void *_di)
731{
732 struct ab8500_btemp *di = _di;
733
734 dev_crit(di->dev, "Battery temperature is higher than MAX temp\n");
735
736 di->events.btemp_high = true;
737 di->events.btemp_medhigh = false;
738 di->events.btemp_lowmed = false;
739 di->events.btemp_low = false;
740 power_supply_changed(&di->btemp_psy);
741
742 return IRQ_HANDLED;
743}
744
745/**
746 * ab8500_btemp_lowmed_handler() - battery temp between low and medium
747 * @irq: interrupt number
748 * @_di: void pointer that has to address of ab8500_btemp
749 *
750 * Returns IRQ status(IRQ_HANDLED)
751 */
752static irqreturn_t ab8500_btemp_lowmed_handler(int irq, void *_di)
753{
754 struct ab8500_btemp *di = _di;
755
756 dev_dbg(di->dev, "Battery temperature is between low and medium\n");
757
758 di->events.btemp_lowmed = true;
759 di->events.btemp_medhigh = false;
760 di->events.btemp_high = false;
761 di->events.btemp_low = false;
762 power_supply_changed(&di->btemp_psy);
763
764 return IRQ_HANDLED;
765}
766
767/**
768 * ab8500_btemp_medhigh_handler() - battery temp between medium and high
769 * @irq: interrupt number
770 * @_di: void pointer that has to address of ab8500_btemp
771 *
772 * Returns IRQ status(IRQ_HANDLED)
773 */
774static irqreturn_t ab8500_btemp_medhigh_handler(int irq, void *_di)
775{
776 struct ab8500_btemp *di = _di;
777
778 dev_dbg(di->dev, "Battery temperature is between medium and high\n");
779
780 di->events.btemp_medhigh = true;
781 di->events.btemp_lowmed = false;
782 di->events.btemp_high = false;
783 di->events.btemp_low = false;
784 power_supply_changed(&di->btemp_psy);
785
786 return IRQ_HANDLED;
787}
788
789/**
790 * ab8500_btemp_periodic() - Periodic temperature measurements
791 * @di: pointer to the ab8500_btemp structure
792 * @enable: enable or disable periodic temperature measurements
793 *
794 * Starts of stops periodic temperature measurements. Periodic measurements
795 * should only be done when a charger is connected.
796 */
797static void ab8500_btemp_periodic(struct ab8500_btemp *di,
798 bool enable)
799{
800 dev_dbg(di->dev, "Enable periodic temperature measurements: %d\n",
801 enable);
802 /*
803 * Make sure a new measurement is done directly by cancelling
804 * any pending work
805 */
806 cancel_delayed_work_sync(&di->btemp_periodic_work);
807
808 if (enable)
809 queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0);
810}
811
812/**
813 * ab8500_btemp_get_temp() - get battery temperature
814 * @di: pointer to the ab8500_btemp structure
815 *
816 * Returns battery temperature
817 */
818static int ab8500_btemp_get_temp(struct ab8500_btemp *di)
819{
820 int temp = 0;
821
822 /*
Hakan Bergd36e3e62013-01-11 13:12:57 +0000823 * The BTEMP events are not reliabe on AB8500 cut3.3
Arun Murthy1f855822012-02-29 21:54:28 +0530824 * and prior versions
825 */
Hakan Bergd36e3e62013-01-11 13:12:57 +0000826 if (is_ab8500_3p3_or_earlier(di->parent)) {
Arun Murthy1f855822012-02-29 21:54:28 +0530827 temp = di->bat_temp * 10;
828 } else {
829 if (di->events.btemp_low) {
830 if (temp > di->btemp_ranges.btemp_low_limit)
Lee Jones5b41aa92013-01-11 13:12:56 +0000831 temp = di->btemp_ranges.btemp_low_limit * 10;
Arun Murthy1f855822012-02-29 21:54:28 +0530832 else
833 temp = di->bat_temp * 10;
834 } else if (di->events.btemp_high) {
835 if (temp < di->btemp_ranges.btemp_high_limit)
Lee Jones5b41aa92013-01-11 13:12:56 +0000836 temp = di->btemp_ranges.btemp_high_limit * 10;
Arun Murthy1f855822012-02-29 21:54:28 +0530837 else
838 temp = di->bat_temp * 10;
839 } else if (di->events.btemp_lowmed) {
840 if (temp > di->btemp_ranges.btemp_med_limit)
Lee Jones5b41aa92013-01-11 13:12:56 +0000841 temp = di->btemp_ranges.btemp_med_limit * 10;
Arun Murthy1f855822012-02-29 21:54:28 +0530842 else
843 temp = di->bat_temp * 10;
844 } else if (di->events.btemp_medhigh) {
845 if (temp < di->btemp_ranges.btemp_med_limit)
Lee Jones5b41aa92013-01-11 13:12:56 +0000846 temp = di->btemp_ranges.btemp_med_limit * 10;
Arun Murthy1f855822012-02-29 21:54:28 +0530847 else
848 temp = di->bat_temp * 10;
849 } else
850 temp = di->bat_temp * 10;
851 }
852 return temp;
853}
854
855/**
856 * ab8500_btemp_get_batctrl_temp() - get the temperature
857 * @btemp: pointer to the btemp structure
858 *
859 * Returns the batctrl temperature in millidegrees
860 */
861int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
862{
863 return btemp->bat_temp * 1000;
864}
865
866/**
867 * ab8500_btemp_get_property() - get the btemp properties
868 * @psy: pointer to the power_supply structure
869 * @psp: pointer to the power_supply_property structure
870 * @val: pointer to the power_supply_propval union
871 *
872 * This function gets called when an application tries to get the btemp
873 * properties by reading the sysfs files.
874 * online: presence of the battery
875 * present: presence of the battery
876 * technology: battery technology
877 * temp: battery temperature
878 * Returns error code in case of failure else 0(on success)
879 */
880static int ab8500_btemp_get_property(struct power_supply *psy,
881 enum power_supply_property psp,
882 union power_supply_propval *val)
883{
884 struct ab8500_btemp *di;
885
886 di = to_ab8500_btemp_device_info(psy);
887
888 switch (psp) {
889 case POWER_SUPPLY_PROP_PRESENT:
890 case POWER_SUPPLY_PROP_ONLINE:
891 if (di->events.batt_rem)
892 val->intval = 0;
893 else
894 val->intval = 1;
895 break;
896 case POWER_SUPPLY_PROP_TECHNOLOGY:
Lee Jonesb0284de2012-11-30 10:09:42 +0000897 val->intval = di->bm->bat_type[di->bm->batt_id].name;
Arun Murthy1f855822012-02-29 21:54:28 +0530898 break;
899 case POWER_SUPPLY_PROP_TEMP:
900 val->intval = ab8500_btemp_get_temp(di);
901 break;
902 default:
903 return -EINVAL;
904 }
905 return 0;
906}
907
908static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
909{
910 struct power_supply *psy;
911 struct power_supply *ext;
912 struct ab8500_btemp *di;
913 union power_supply_propval ret;
914 int i, j;
915 bool psy_found = false;
916
917 psy = (struct power_supply *)data;
918 ext = dev_get_drvdata(dev);
919 di = to_ab8500_btemp_device_info(psy);
920
921 /*
922 * For all psy where the name of your driver
923 * appears in any supplied_to
924 */
925 for (i = 0; i < ext->num_supplicants; i++) {
926 if (!strcmp(ext->supplied_to[i], psy->name))
927 psy_found = true;
928 }
929
930 if (!psy_found)
931 return 0;
932
933 /* Go through all properties for the psy */
934 for (j = 0; j < ext->num_properties; j++) {
935 enum power_supply_property prop;
936 prop = ext->properties[j];
937
938 if (ext->get_property(ext, prop, &ret))
939 continue;
940
941 switch (prop) {
942 case POWER_SUPPLY_PROP_PRESENT:
943 switch (ext->type) {
944 case POWER_SUPPLY_TYPE_MAINS:
945 /* AC disconnected */
946 if (!ret.intval && di->events.ac_conn) {
947 di->events.ac_conn = false;
948 }
949 /* AC connected */
950 else if (ret.intval && !di->events.ac_conn) {
951 di->events.ac_conn = true;
952 if (!di->events.usb_conn)
953 ab8500_btemp_periodic(di, true);
954 }
955 break;
956 case POWER_SUPPLY_TYPE_USB:
957 /* USB disconnected */
958 if (!ret.intval && di->events.usb_conn) {
959 di->events.usb_conn = false;
960 }
961 /* USB connected */
962 else if (ret.intval && !di->events.usb_conn) {
963 di->events.usb_conn = true;
964 if (!di->events.ac_conn)
965 ab8500_btemp_periodic(di, true);
966 }
967 break;
968 default:
969 break;
970 }
971 break;
972 default:
973 break;
974 }
975 }
976 return 0;
977}
978
979/**
980 * ab8500_btemp_external_power_changed() - callback for power supply changes
981 * @psy: pointer to the structure power_supply
982 *
983 * This function is pointing to the function pointer external_power_changed
984 * of the structure power_supply.
985 * This function gets executed when there is a change in the external power
986 * supply to the btemp.
987 */
988static void ab8500_btemp_external_power_changed(struct power_supply *psy)
989{
990 struct ab8500_btemp *di = to_ab8500_btemp_device_info(psy);
991
992 class_for_each_device(power_supply_class, NULL,
993 &di->btemp_psy, ab8500_btemp_get_ext_psy_data);
994}
995
996/* ab8500 btemp driver interrupts and their respective isr */
997static struct ab8500_btemp_interrupts ab8500_btemp_irq[] = {
998 {"BAT_CTRL_INDB", ab8500_btemp_batctrlindb_handler},
999 {"BTEMP_LOW", ab8500_btemp_templow_handler},
1000 {"BTEMP_HIGH", ab8500_btemp_temphigh_handler},
1001 {"BTEMP_LOW_MEDIUM", ab8500_btemp_lowmed_handler},
1002 {"BTEMP_MEDIUM_HIGH", ab8500_btemp_medhigh_handler},
1003};
1004
1005#if defined(CONFIG_PM)
1006static int ab8500_btemp_resume(struct platform_device *pdev)
1007{
1008 struct ab8500_btemp *di = platform_get_drvdata(pdev);
1009
1010 ab8500_btemp_periodic(di, true);
1011
1012 return 0;
1013}
1014
1015static int ab8500_btemp_suspend(struct platform_device *pdev,
1016 pm_message_t state)
1017{
1018 struct ab8500_btemp *di = platform_get_drvdata(pdev);
1019
1020 ab8500_btemp_periodic(di, false);
1021
1022 return 0;
1023}
1024#else
1025#define ab8500_btemp_suspend NULL
1026#define ab8500_btemp_resume NULL
1027#endif
1028
Bill Pemberton415ec692012-11-19 13:26:07 -05001029static int ab8500_btemp_remove(struct platform_device *pdev)
Arun Murthy1f855822012-02-29 21:54:28 +05301030{
1031 struct ab8500_btemp *di = platform_get_drvdata(pdev);
1032 int i, irq;
1033
1034 /* Disable interrupts */
1035 for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
1036 irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1037 free_irq(irq, di);
1038 }
1039
1040 /* Delete the work queue */
1041 destroy_workqueue(di->btemp_wq);
1042
1043 flush_scheduled_work();
1044 power_supply_unregister(&di->btemp_psy);
1045 platform_set_drvdata(pdev, NULL);
Arun Murthy1f855822012-02-29 21:54:28 +05301046
1047 return 0;
1048}
1049
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001050static char *supply_interface[] = {
1051 "ab8500_chargalg",
1052 "ab8500_fg",
1053};
1054
Bill Pembertonc8afa642012-11-19 13:22:23 -05001055static int ab8500_btemp_probe(struct platform_device *pdev)
Arun Murthy1f855822012-02-29 21:54:28 +05301056{
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001057 struct device_node *np = pdev->dev.of_node;
Lee Jones95820242012-11-30 10:48:30 +00001058 struct abx500_bm_data *plat = pdev->dev.platform_data;
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -08001059 struct ab8500_btemp *di;
Arun Murthy1f855822012-02-29 21:54:28 +05301060 int irq, i, ret = 0;
1061 u8 val;
Arun Murthy1f855822012-02-29 21:54:28 +05301062
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001063 di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
1064 if (!di) {
1065 dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
Arun Murthy1f855822012-02-29 21:54:28 +05301066 return -ENOMEM;
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001067 }
Lee Jones95820242012-11-30 10:48:30 +00001068
1069 if (!plat) {
1070 dev_err(&pdev->dev, "no battery management data supplied\n");
1071 return -EINVAL;
1072 }
1073 di->bm = plat;
1074
1075 if (np) {
1076 ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
1077 if (ret) {
1078 dev_err(&pdev->dev, "failed to get battery information\n");
1079 return ret;
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001080 }
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001081 }
Arun Murthy1f855822012-02-29 21:54:28 +05301082
1083 /* get parent data */
1084 di->dev = &pdev->dev;
1085 di->parent = dev_get_drvdata(pdev->dev.parent);
1086 di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1087
Jonas Aabergf6271b42012-02-27 11:02:44 +01001088 di->initialized = false;
1089
Arun Murthy1f855822012-02-29 21:54:28 +05301090 /* BTEMP supply */
1091 di->btemp_psy.name = "ab8500_btemp";
1092 di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
1093 di->btemp_psy.properties = ab8500_btemp_props;
1094 di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props);
1095 di->btemp_psy.get_property = ab8500_btemp_get_property;
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001096 di->btemp_psy.supplied_to = supply_interface;
1097 di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface);
Arun Murthy1f855822012-02-29 21:54:28 +05301098 di->btemp_psy.external_power_changed =
1099 ab8500_btemp_external_power_changed;
1100
1101
1102 /* Create a work queue for the btemp */
1103 di->btemp_wq =
1104 create_singlethread_workqueue("ab8500_btemp_wq");
1105 if (di->btemp_wq == NULL) {
1106 dev_err(di->dev, "failed to create work queue\n");
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001107 return -ENOMEM;
Arun Murthy1f855822012-02-29 21:54:28 +05301108 }
1109
1110 /* Init work for measuring temperature periodically */
Tejun Heo203b42f2012-08-21 13:18:23 -07001111 INIT_DEFERRABLE_WORK(&di->btemp_periodic_work,
Arun Murthy1f855822012-02-29 21:54:28 +05301112 ab8500_btemp_periodic_work);
1113
Arun Murthy1f855822012-02-29 21:54:28 +05301114 /* Set BTEMP thermal limits. Low and Med are fixed */
Hakan Berg0cdaf9a2013-01-11 13:13:00 +00001115 di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
1116 di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
Arun Murthy1f855822012-02-29 21:54:28 +05301117
1118 ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
1119 AB8500_BTEMP_HIGH_TH, &val);
1120 if (ret < 0) {
1121 dev_err(di->dev, "%s ab8500 read failed\n", __func__);
1122 goto free_btemp_wq;
1123 }
1124 switch (val) {
1125 case BTEMP_HIGH_TH_57_0:
1126 case BTEMP_HIGH_TH_57_1:
1127 di->btemp_ranges.btemp_high_limit =
1128 BTEMP_THERMAL_HIGH_LIMIT_57;
1129 break;
1130 case BTEMP_HIGH_TH_52:
1131 di->btemp_ranges.btemp_high_limit =
1132 BTEMP_THERMAL_HIGH_LIMIT_52;
1133 break;
1134 case BTEMP_HIGH_TH_62:
1135 di->btemp_ranges.btemp_high_limit =
1136 BTEMP_THERMAL_HIGH_LIMIT_62;
1137 break;
1138 }
1139
1140 /* Register BTEMP power supply class */
1141 ret = power_supply_register(di->dev, &di->btemp_psy);
1142 if (ret) {
1143 dev_err(di->dev, "failed to register BTEMP psy\n");
1144 goto free_btemp_wq;
1145 }
1146
1147 /* Register interrupts */
1148 for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
1149 irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1150 ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr,
1151 IRQF_SHARED | IRQF_NO_SUSPEND,
1152 ab8500_btemp_irq[i].name, di);
1153
1154 if (ret) {
1155 dev_err(di->dev, "failed to request %s IRQ %d: %d\n"
1156 , ab8500_btemp_irq[i].name, irq, ret);
1157 goto free_irq;
1158 }
1159 dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
1160 ab8500_btemp_irq[i].name, irq, ret);
1161 }
1162
1163 platform_set_drvdata(pdev, di);
1164
1165 /* Kick off periodic temperature measurements */
1166 ab8500_btemp_periodic(di, true);
1167 list_add_tail(&di->node, &ab8500_btemp_list);
1168
1169 return ret;
1170
1171free_irq:
1172 power_supply_unregister(&di->btemp_psy);
1173
1174 /* We also have to free all successfully registered irqs */
1175 for (i = i - 1; i >= 0; i--) {
1176 irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1177 free_irq(irq, di);
1178 }
1179free_btemp_wq:
1180 destroy_workqueue(di->btemp_wq);
Arun Murthy1f855822012-02-29 21:54:28 +05301181 return ret;
1182}
1183
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001184static const struct of_device_id ab8500_btemp_match[] = {
1185 { .compatible = "stericsson,ab8500-btemp", },
1186 { },
1187};
1188
Arun Murthy1f855822012-02-29 21:54:28 +05301189static struct platform_driver ab8500_btemp_driver = {
1190 .probe = ab8500_btemp_probe,
Bill Pemberton28ea73f2012-11-19 13:20:40 -05001191 .remove = ab8500_btemp_remove,
Arun Murthy1f855822012-02-29 21:54:28 +05301192 .suspend = ab8500_btemp_suspend,
1193 .resume = ab8500_btemp_resume,
1194 .driver = {
1195 .name = "ab8500-btemp",
1196 .owner = THIS_MODULE,
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001197 .of_match_table = ab8500_btemp_match,
Arun Murthy1f855822012-02-29 21:54:28 +05301198 },
1199};
1200
1201static int __init ab8500_btemp_init(void)
1202{
1203 return platform_driver_register(&ab8500_btemp_driver);
1204}
1205
1206static void __exit ab8500_btemp_exit(void)
1207{
1208 platform_driver_unregister(&ab8500_btemp_driver);
1209}
1210
Rajanikanth H.Veeb07512013-01-23 09:56:45 +05301211device_initcall(ab8500_btemp_init);
Arun Murthy1f855822012-02-29 21:54:28 +05301212module_exit(ab8500_btemp_exit);
1213
1214MODULE_LICENSE("GPL v2");
1215MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
1216MODULE_ALIAS("platform:ab8500-btemp");
1217MODULE_DESCRIPTION("AB8500 battery temperature driver");