• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/mfd/abx500/ab8500.h>
24 #include <linux/mfd/abx500.h>
25 #include <linux/mfd/abx500/ab8500-bm.h>
26 #include <linux/mfd/abx500/ab8500-gpadc.h>
27 #include <linux/jiffies.h>
28 
29 #define VTVOUT_V			1800
30 
31 #define BTEMP_THERMAL_LOW_LIMIT		-10
32 #define BTEMP_THERMAL_MED_LIMIT		0
33 #define BTEMP_THERMAL_HIGH_LIMIT_52	52
34 #define BTEMP_THERMAL_HIGH_LIMIT_57	57
35 #define BTEMP_THERMAL_HIGH_LIMIT_62	62
36 
37 #define BTEMP_BATCTRL_CURR_SRC_7UA	7
38 #define BTEMP_BATCTRL_CURR_SRC_20UA	20
39 
40 #define to_ab8500_btemp_device_info(x) container_of((x), \
41 	struct ab8500_btemp, btemp_psy);
42 
43 /**
44  * struct ab8500_btemp_interrupts - ab8500 interrupts
45  * @name:	name of the interrupt
46  * @isr		function pointer to the isr
47  */
48 struct ab8500_btemp_interrupts {
49 	char *name;
50 	irqreturn_t (*isr)(int irq, void *data);
51 };
52 
53 struct ab8500_btemp_events {
54 	bool batt_rem;
55 	bool btemp_high;
56 	bool btemp_medhigh;
57 	bool btemp_lowmed;
58 	bool btemp_low;
59 	bool ac_conn;
60 	bool usb_conn;
61 };
62 
63 struct ab8500_btemp_ranges {
64 	int btemp_high_limit;
65 	int btemp_med_limit;
66 	int btemp_low_limit;
67 };
68 
69 /**
70  * struct ab8500_btemp - ab8500 BTEMP device information
71  * @dev:		Pointer to the structure device
72  * @node:		List of AB8500 BTEMPs, hence prepared for reentrance
73  * @curr_source:	What current source we use, in uA
74  * @bat_temp:		Battery temperature in degree Celcius
75  * @prev_bat_temp	Last dispatched battery temperature
76  * @parent:		Pointer to the struct ab8500
77  * @gpadc:		Pointer to the struct gpadc
78  * @fg:			Pointer to the struct fg
79  * @pdata:		Pointer to the abx500_btemp platform data
80  * @bat:		Pointer to the abx500_bm platform data
81  * @btemp_psy:		Structure for BTEMP specific battery properties
82  * @events:		Structure for information about events triggered
83  * @btemp_ranges:	Battery temperature range structure
84  * @btemp_wq:		Work queue for measuring the temperature periodically
85  * @btemp_periodic_work:	Work for measuring the temperature periodically
86  */
87 struct ab8500_btemp {
88 	struct device *dev;
89 	struct list_head node;
90 	int curr_source;
91 	int bat_temp;
92 	int prev_bat_temp;
93 	struct ab8500 *parent;
94 	struct ab8500_gpadc *gpadc;
95 	struct ab8500_fg *fg;
96 	struct abx500_btemp_platform_data *pdata;
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  */
ab8500_btemp_get(void)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  */
ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp * di,int v_batctrl,int inst_curr)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  */
ab8500_btemp_read_batctrl_voltage(struct ab8500_btemp * di)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  */
ab8500_btemp_curr_source_enable(struct ab8500_btemp * di,bool enable)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  */
ab8500_btemp_get_batctrl_res(struct ab8500_btemp * di)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  */
ab8500_btemp_res_to_temp(struct ab8500_btemp * di,const struct abx500_res_to_temp * tbl,int tbl_size,int res)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  */
ab8500_btemp_measure_temp(struct ab8500_btemp * di)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  */
ab8500_btemp_id(struct ab8500_btemp * di)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  */
ab8500_btemp_periodic_work(struct work_struct * work)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  */
ab8500_btemp_batctrlindb_handler(int irq,void * _di)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  */
ab8500_btemp_templow_handler(int irq,void * _di)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  */
ab8500_btemp_temphigh_handler(int irq,void * _di)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  */
ab8500_btemp_lowmed_handler(int irq,void * _di)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  */
ab8500_btemp_medhigh_handler(int irq,void * _di)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  */
ab8500_btemp_periodic(struct ab8500_btemp * di,bool enable)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  */
ab8500_btemp_get_temp(struct ab8500_btemp * di)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  */
ab8500_btemp_get_batctrl_temp(struct ab8500_btemp * btemp)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  */
ab8500_btemp_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)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 
ab8500_btemp_get_ext_psy_data(struct device * dev,void * data)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  */
ab8500_btemp_external_power_changed(struct power_supply * psy)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)
ab8500_btemp_resume(struct platform_device * pdev)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 
ab8500_btemp_suspend(struct platform_device * pdev,pm_message_t state)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 
ab8500_btemp_remove(struct platform_device * pdev)941 static int __devexit 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 	kfree(di);
959 
960 	return 0;
961 }
962 
ab8500_btemp_probe(struct platform_device * pdev)963 static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
964 {
965 	int irq, i, ret = 0;
966 	u8 val;
967 	struct abx500_bm_plat_data *plat_data;
968 
969 	struct ab8500_btemp *di =
970 		kzalloc(sizeof(struct ab8500_btemp), GFP_KERNEL);
971 	if (!di)
972 		return -ENOMEM;
973 
974 	/* get parent data */
975 	di->dev = &pdev->dev;
976 	di->parent = dev_get_drvdata(pdev->dev.parent);
977 	di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
978 
979 	/* get btemp specific platform data */
980 	plat_data = pdev->dev.platform_data;
981 	di->pdata = plat_data->btemp;
982 	if (!di->pdata) {
983 		dev_err(di->dev, "no btemp platform data supplied\n");
984 		ret = -EINVAL;
985 		goto free_device_info;
986 	}
987 
988 	/* get battery specific platform data */
989 	di->bat = plat_data->battery;
990 	if (!di->bat) {
991 		dev_err(di->dev, "no battery platform data supplied\n");
992 		ret = -EINVAL;
993 		goto free_device_info;
994 	}
995 
996 	/* BTEMP supply */
997 	di->btemp_psy.name = "ab8500_btemp";
998 	di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
999 	di->btemp_psy.properties = ab8500_btemp_props;
1000 	di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props);
1001 	di->btemp_psy.get_property = ab8500_btemp_get_property;
1002 	di->btemp_psy.supplied_to = di->pdata->supplied_to;
1003 	di->btemp_psy.num_supplicants = di->pdata->num_supplicants;
1004 	di->btemp_psy.external_power_changed =
1005 		ab8500_btemp_external_power_changed;
1006 
1007 
1008 	/* Create a work queue for the btemp */
1009 	di->btemp_wq =
1010 		create_singlethread_workqueue("ab8500_btemp_wq");
1011 	if (di->btemp_wq == NULL) {
1012 		dev_err(di->dev, "failed to create work queue\n");
1013 		goto free_device_info;
1014 	}
1015 
1016 	/* Init work for measuring temperature periodically */
1017 	INIT_DELAYED_WORK_DEFERRABLE(&di->btemp_periodic_work,
1018 		ab8500_btemp_periodic_work);
1019 
1020 	/* Identify the battery */
1021 	if (ab8500_btemp_id(di) < 0)
1022 		dev_warn(di->dev, "failed to identify the battery\n");
1023 
1024 	/* Set BTEMP thermal limits. Low and Med are fixed */
1025 	di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
1026 	di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
1027 
1028 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
1029 		AB8500_BTEMP_HIGH_TH, &val);
1030 	if (ret < 0) {
1031 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
1032 		goto free_btemp_wq;
1033 	}
1034 	switch (val) {
1035 	case BTEMP_HIGH_TH_57_0:
1036 	case BTEMP_HIGH_TH_57_1:
1037 		di->btemp_ranges.btemp_high_limit =
1038 			BTEMP_THERMAL_HIGH_LIMIT_57;
1039 		break;
1040 	case BTEMP_HIGH_TH_52:
1041 		di->btemp_ranges.btemp_high_limit =
1042 			BTEMP_THERMAL_HIGH_LIMIT_52;
1043 		break;
1044 	case BTEMP_HIGH_TH_62:
1045 		di->btemp_ranges.btemp_high_limit =
1046 			BTEMP_THERMAL_HIGH_LIMIT_62;
1047 		break;
1048 	}
1049 
1050 	/* Register BTEMP power supply class */
1051 	ret = power_supply_register(di->dev, &di->btemp_psy);
1052 	if (ret) {
1053 		dev_err(di->dev, "failed to register BTEMP psy\n");
1054 		goto free_btemp_wq;
1055 	}
1056 
1057 	/* Register interrupts */
1058 	for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
1059 		irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1060 		ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr,
1061 			IRQF_SHARED | IRQF_NO_SUSPEND,
1062 			ab8500_btemp_irq[i].name, di);
1063 
1064 		if (ret) {
1065 			dev_err(di->dev, "failed to request %s IRQ %d: %d\n"
1066 				, ab8500_btemp_irq[i].name, irq, ret);
1067 			goto free_irq;
1068 		}
1069 		dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
1070 			ab8500_btemp_irq[i].name, irq, ret);
1071 	}
1072 
1073 	platform_set_drvdata(pdev, di);
1074 
1075 	/* Kick off periodic temperature measurements */
1076 	ab8500_btemp_periodic(di, true);
1077 	list_add_tail(&di->node, &ab8500_btemp_list);
1078 
1079 	return ret;
1080 
1081 free_irq:
1082 	power_supply_unregister(&di->btemp_psy);
1083 
1084 	/* We also have to free all successfully registered irqs */
1085 	for (i = i - 1; i >= 0; i--) {
1086 		irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1087 		free_irq(irq, di);
1088 	}
1089 free_btemp_wq:
1090 	destroy_workqueue(di->btemp_wq);
1091 free_device_info:
1092 	kfree(di);
1093 
1094 	return ret;
1095 }
1096 
1097 static struct platform_driver ab8500_btemp_driver = {
1098 	.probe = ab8500_btemp_probe,
1099 	.remove = __devexit_p(ab8500_btemp_remove),
1100 	.suspend = ab8500_btemp_suspend,
1101 	.resume = ab8500_btemp_resume,
1102 	.driver = {
1103 		.name = "ab8500-btemp",
1104 		.owner = THIS_MODULE,
1105 	},
1106 };
1107 
ab8500_btemp_init(void)1108 static int __init ab8500_btemp_init(void)
1109 {
1110 	return platform_driver_register(&ab8500_btemp_driver);
1111 }
1112 
ab8500_btemp_exit(void)1113 static void __exit ab8500_btemp_exit(void)
1114 {
1115 	platform_driver_unregister(&ab8500_btemp_driver);
1116 }
1117 
1118 device_initcall(ab8500_btemp_init);
1119 module_exit(ab8500_btemp_exit);
1120 
1121 MODULE_LICENSE("GPL v2");
1122 MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
1123 MODULE_ALIAS("platform:ab8500-btemp");
1124 MODULE_DESCRIPTION("AB8500 battery temperature driver");
1125