ded2c8c8b2cc0ffc6444ed1b52af01e0d25fd19a
[deliverable/linux.git] / drivers / staging / omap-thermal / omap-bandgap.c
1 /*
2 * OMAP4 Bandgap temperature sensor driver
3 *
4 * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
5 * Author: J Keerthy <j-keerthy@ti.com>
6 * Author: Moiz Sonasath <m-sonasath@ti.com>
7 * Couple of fixes, DT and MFD adaptation:
8 * Eduardo Valentin <eduardo.valentin@ti.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * version 2 as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 *
24 */
25
26 #include <linux/module.h>
27 #include <linux/export.h>
28 #include <linux/init.h>
29 #include <linux/kernel.h>
30 #include <linux/interrupt.h>
31 #include <linux/clk.h>
32 #include <linux/gpio.h>
33 #include <linux/platform_device.h>
34 #include <linux/err.h>
35 #include <linux/types.h>
36 #include <linux/mutex.h>
37 #include <linux/reboot.h>
38 #include <linux/of_device.h>
39 #include <linux/of_platform.h>
40 #include <linux/of_irq.h>
41 #include <linux/io.h>
42
43 #include "omap-bandgap.h"
44
45 /*** Helper functions to access registers and their bitfields ***/
46
47 /**
48 * omap_bandgap_readl() - simple read helper function
49 * @bg_ptr: pointer to omap_bandgap structure
50 * @reg: desired register (offset) to be read
51 *
52 * Helper function to read bandgap registers. It uses the io remapped area.
53 * Returns the register value.
54 */
55 static u32 omap_bandgap_readl(struct omap_bandgap *bg_ptr, u32 reg)
56 {
57 return readl(bg_ptr->base + reg);
58 }
59
60 /**
61 * omap_bandgap_writel() - simple write helper function
62 * @bg_ptr: pointer to omap_bandgap structure
63 * @val: desired register value to be written
64 * @reg: desired register (offset) to be written
65 *
66 * Helper function to write bandgap registers. It uses the io remapped area.
67 */
68 static void omap_bandgap_writel(struct omap_bandgap *bg_ptr, u32 val, u32 reg)
69 {
70 writel(val, bg_ptr->base + reg);
71 }
72
73 /**
74 * DOC: macro to update bits.
75 *
76 * RMW_BITS() - used to read, modify and update bandgap bitfields.
77 * The value passed will be shifted.
78 */
79 #define RMW_BITS(bg_ptr, id, reg, mask, val) \
80 do { \
81 struct temp_sensor_registers *t; \
82 u32 r; \
83 \
84 t = bg_ptr->conf->sensors[(id)].registers; \
85 r = omap_bandgap_readl(bg_ptr, t->reg); \
86 r &= ~t->mask; \
87 r |= (val) << __ffs(t->mask); \
88 omap_bandgap_writel(bg_ptr, r, t->reg); \
89 } while (0)
90
91 /*** Basic helper functions ***/
92
93 /**
94 * omap_bandgap_power() - controls the power state of a bandgap device
95 * @bg_ptr: pointer to omap_bandgap structure
96 * @on: desired power state (1 - on, 0 - off)
97 *
98 * Used to power on/off a bandgap device instance. Only used on those
99 * that features tempsoff bit.
100 */
101 static int omap_bandgap_power(struct omap_bandgap *bg_ptr, bool on)
102 {
103 int i;
104
105 if (!OMAP_BANDGAP_HAS(bg_ptr, POWER_SWITCH))
106 goto exit;
107
108 for (i = 0; i < bg_ptr->conf->sensor_count; i++)
109 /* active on 0 */
110 RMW_BITS(bg_ptr, i, temp_sensor_ctrl, bgap_tempsoff_mask, !on);
111
112 exit:
113 return 0;
114 }
115
116 /**
117 * omap_bandgap_read_temp() - helper function to read sensor temperature
118 * @bg_ptr: pointer to omap_bandgap structure
119 * @id: bandgap sensor id
120 *
121 * Function to concentrate the steps to read sensor temperature register.
122 * This function is desired because, depending on bandgap device version,
123 * it might be needed to freeze the bandgap state machine, before fetching
124 * the register value.
125 */
126 static u32 omap_bandgap_read_temp(struct omap_bandgap *bg_ptr, int id)
127 {
128 struct temp_sensor_registers *tsr;
129 u32 temp, reg;
130
131 tsr = bg_ptr->conf->sensors[id].registers;
132 reg = tsr->temp_sensor_ctrl;
133
134 if (OMAP_BANDGAP_HAS(bg_ptr, FREEZE_BIT)) {
135 RMW_BITS(bg_ptr, id, bgap_mask_ctrl, mask_freeze_mask, 1);
136 /*
137 * In case we cannot read from cur_dtemp / dtemp_0,
138 * then we read from the last valid temp read
139 */
140 reg = tsr->ctrl_dtemp_1;
141 }
142
143 /* read temperature */
144 temp = omap_bandgap_readl(bg_ptr, reg);
145 temp &= tsr->bgap_dtemp_mask;
146
147 if (OMAP_BANDGAP_HAS(bg_ptr, FREEZE_BIT))
148 RMW_BITS(bg_ptr, id, bgap_mask_ctrl, mask_freeze_mask, 0);
149
150 return temp;
151 }
152
153 /*** IRQ handlers ***/
154
155 /**
156 * omap_bandgap_talert_irq_handler() - handles Temperature alert IRQs
157 * @irq: IRQ number
158 * @data: private data (struct omap_bandgap *)
159 *
160 * This is the Talert handler. Use it only if bandgap device features
161 * HAS(TALERT). This handler goes over all sensors and checks their
162 * conditions and acts accordingly. In case there are events pending,
163 * it will reset the event mask to wait for the opposite event (next event).
164 * Every time there is a new event, it will be reported to thermal layer.
165 */
166 static irqreturn_t omap_bandgap_talert_irq_handler(int irq, void *data)
167 {
168 struct omap_bandgap *bg_ptr = data;
169 struct temp_sensor_registers *tsr;
170 u32 t_hot = 0, t_cold = 0, ctrl;
171 int i;
172
173 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
174 tsr = bg_ptr->conf->sensors[i].registers;
175 ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_status);
176
177 /* Read the status of t_hot */
178 t_hot = ctrl & tsr->status_hot_mask;
179
180 /* Read the status of t_cold */
181 t_cold = ctrl & tsr->status_cold_mask;
182
183 if (!t_cold && !t_hot)
184 continue;
185
186 ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
187 /*
188 * One TALERT interrupt: Two sources
189 * If the interrupt is due to t_hot then mask t_hot and
190 * and unmask t_cold else mask t_cold and unmask t_hot
191 */
192 if (t_hot) {
193 ctrl &= ~tsr->mask_hot_mask;
194 ctrl |= tsr->mask_cold_mask;
195 } else if (t_cold) {
196 ctrl &= ~tsr->mask_cold_mask;
197 ctrl |= tsr->mask_hot_mask;
198 }
199
200 omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
201
202 dev_dbg(bg_ptr->dev,
203 "%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
204 __func__, bg_ptr->conf->sensors[i].domain,
205 t_hot, t_cold);
206
207 /* report temperature to whom may concern */
208 if (bg_ptr->conf->report_temperature)
209 bg_ptr->conf->report_temperature(bg_ptr, i);
210 }
211
212 return IRQ_HANDLED;
213 }
214
215 /**
216 * omap_bandgap_tshut_irq_handler() - handles Temperature shutdown signal
217 * @irq: IRQ number
218 * @data: private data (unused)
219 *
220 * This is the Tshut handler. Use it only if bandgap device features
221 * HAS(TSHUT). If any sensor fires the Tshut signal, we simply shutdown
222 * the system.
223 */
224 static irqreturn_t omap_bandgap_tshut_irq_handler(int irq, void *data)
225 {
226 pr_emerg("%s: TSHUT temperature reached. Needs shut down...\n",
227 __func__);
228
229 orderly_poweroff(true);
230
231 return IRQ_HANDLED;
232 }
233
234 static
235 int adc_to_temp_conversion(struct omap_bandgap *bg_ptr, int id, int adc_val,
236 int *t)
237 {
238 struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
239
240 /* look up for temperature in the table and return the temperature */
241 if (adc_val < ts_data->adc_start_val || adc_val > ts_data->adc_end_val)
242 return -ERANGE;
243
244 *t = bg_ptr->conf->conv_table[adc_val - ts_data->adc_start_val];
245
246 return 0;
247 }
248
249 static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i,
250 int *adc)
251 {
252 struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[i].ts_data;
253 const int *conv_table = bg_ptr->conf->conv_table;
254 int high, low, mid;
255
256 low = 0;
257 high = ts_data->adc_end_val - ts_data->adc_start_val;
258 mid = (high + low) / 2;
259
260 if (temp < conv_table[low] || temp > conv_table[high])
261 return -EINVAL;
262
263 while (low < high) {
264 if (temp < conv_table[mid])
265 high = mid - 1;
266 else
267 low = mid + 1;
268 mid = (low + high) / 2;
269 }
270
271 *adc = ts_data->adc_start_val + low;
272
273 return 0;
274 }
275
276 /* Talert masks. Call it only if HAS(TALERT) is set */
277 static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id,
278 u32 t_hot, u32 t_cold)
279 {
280 struct temp_sensor_registers *tsr;
281 u32 temp, reg_val;
282
283 /* Read the current on die temperature */
284 temp = omap_bandgap_read_temp(bg_ptr, id);
285
286 tsr = bg_ptr->conf->sensors[id].registers;
287 reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
288
289 if (temp < t_hot)
290 reg_val |= tsr->mask_hot_mask;
291 else
292 reg_val &= ~tsr->mask_hot_mask;
293
294 if (t_cold < temp)
295 reg_val |= tsr->mask_cold_mask;
296 else
297 reg_val &= ~tsr->mask_cold_mask;
298 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl);
299
300 return 0;
301 }
302
303 static
304 int add_hyst(int adc_val, int hyst_val, struct omap_bandgap *bg_ptr, int i,
305 u32 *sum)
306 {
307 int temp, ret;
308
309 ret = adc_to_temp_conversion(bg_ptr, i, adc_val, &temp);
310 if (ret < 0)
311 return ret;
312
313 temp += hyst_val;
314
315 return temp_to_adc_conversion(temp, bg_ptr, i, sum);
316 }
317
318 /* Talert Thot threshold. Call it only if HAS(TALERT) is set */
319 static
320 int temp_sensor_configure_thot(struct omap_bandgap *bg_ptr, int id, int t_hot)
321 {
322 struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
323 struct temp_sensor_registers *tsr;
324 u32 thresh_val, reg_val;
325 int cold, err = 0;
326
327 tsr = bg_ptr->conf->sensors[id].registers;
328
329 /* obtain the T cold value */
330 thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
331 cold = (thresh_val & tsr->threshold_tcold_mask) >>
332 __ffs(tsr->threshold_tcold_mask);
333 if (t_hot <= cold) {
334 /* change the t_cold to t_hot - 5000 millidegrees */
335 err |= add_hyst(t_hot, -ts_data->hyst_val, bg_ptr, id, &cold);
336 /* write the new t_cold value */
337 reg_val = thresh_val & (~tsr->threshold_tcold_mask);
338 reg_val |= cold << __ffs(tsr->threshold_tcold_mask);
339 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
340 thresh_val = reg_val;
341 }
342
343 /* write the new t_hot value */
344 reg_val = thresh_val & ~tsr->threshold_thot_mask;
345 reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
346 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
347 if (err) {
348 dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
349 return -EIO;
350 }
351
352 return temp_sensor_unmask_interrupts(bg_ptr, id, t_hot, cold);
353 }
354
355 /* Talert Tcold threshold. Call it only if HAS(TALERT) is set */
356 static
357 int temp_sensor_configure_tcold(struct omap_bandgap *bg_ptr, int id,
358 int t_cold)
359 {
360 struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
361 struct temp_sensor_registers *tsr;
362 u32 thresh_val, reg_val;
363 int hot, err = 0;
364
365 tsr = bg_ptr->conf->sensors[id].registers;
366 /* obtain the T cold value */
367 thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
368 hot = (thresh_val & tsr->threshold_thot_mask) >>
369 __ffs(tsr->threshold_thot_mask);
370
371 if (t_cold >= hot) {
372 /* change the t_hot to t_cold + 5000 millidegrees */
373 err |= add_hyst(t_cold, ts_data->hyst_val, bg_ptr, id, &hot);
374 /* write the new t_hot value */
375 reg_val = thresh_val & (~tsr->threshold_thot_mask);
376 reg_val |= hot << __ffs(tsr->threshold_thot_mask);
377 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
378 thresh_val = reg_val;
379 }
380
381 /* write the new t_cold value */
382 reg_val = thresh_val & ~tsr->threshold_tcold_mask;
383 reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
384 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
385 if (err) {
386 dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
387 return -EIO;
388 }
389
390 return temp_sensor_unmask_interrupts(bg_ptr, id, hot, t_cold);
391 }
392
393 #define bandgap_is_valid(b) \
394 (!IS_ERR_OR_NULL(b))
395 #define bandgap_is_valid_sensor_id(b, i) \
396 ((i) >= 0 && (i) < (b)->conf->sensor_count)
397 static inline int omap_bandgap_validate(struct omap_bandgap *bg_ptr, int id)
398 {
399 if (!bandgap_is_valid(bg_ptr)) {
400 pr_err("%s: invalid bandgap pointer\n", __func__);
401 return -EINVAL;
402 }
403
404 if (!bandgap_is_valid_sensor_id(bg_ptr, id)) {
405 dev_err(bg_ptr->dev, "%s: sensor id out of range (%d)\n",
406 __func__, id);
407 return -ERANGE;
408 }
409
410 return 0;
411 }
412
413 /* Exposed APIs */
414 /**
415 * omap_bandgap_read_thot() - reads sensor current thot
416 * @bg_ptr - pointer to bandgap instance
417 * @id - sensor id
418 * @thot - resulting current thot value
419 *
420 * returns 0 on success or the proper error code
421 */
422 int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id,
423 int *thot)
424 {
425 struct temp_sensor_registers *tsr;
426 u32 temp;
427 int ret;
428
429 ret = omap_bandgap_validate(bg_ptr, id);
430 if (ret)
431 return ret;
432
433 if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
434 return -ENOTSUPP;
435
436 tsr = bg_ptr->conf->sensors[id].registers;
437 temp = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
438 temp = (temp & tsr->threshold_thot_mask) >>
439 __ffs(tsr->threshold_thot_mask);
440 ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
441 if (ret) {
442 dev_err(bg_ptr->dev, "failed to read thot\n");
443 return -EIO;
444 }
445
446 *thot = temp;
447
448 return 0;
449 }
450
451 /**
452 * omap_bandgap_write_thot() - sets sensor current thot
453 * @bg_ptr - pointer to bandgap instance
454 * @id - sensor id
455 * @val - desired thot value
456 *
457 * returns 0 on success or the proper error code
458 */
459 int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val)
460 {
461 struct temp_sensor_data *ts_data;
462 struct temp_sensor_registers *tsr;
463 u32 t_hot;
464 int ret;
465
466 ret = omap_bandgap_validate(bg_ptr, id);
467 if (ret)
468 return ret;
469
470 if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
471 return -ENOTSUPP;
472
473 ts_data = bg_ptr->conf->sensors[id].ts_data;
474 tsr = bg_ptr->conf->sensors[id].registers;
475
476 if (val < ts_data->min_temp + ts_data->hyst_val)
477 return -EINVAL;
478 ret = temp_to_adc_conversion(val, bg_ptr, id, &t_hot);
479 if (ret < 0)
480 return ret;
481
482 mutex_lock(&bg_ptr->bg_mutex);
483 temp_sensor_configure_thot(bg_ptr, id, t_hot);
484 mutex_unlock(&bg_ptr->bg_mutex);
485
486 return 0;
487 }
488
489 /**
490 * omap_bandgap_read_tcold() - reads sensor current tcold
491 * @bg_ptr - pointer to bandgap instance
492 * @id - sensor id
493 * @tcold - resulting current tcold value
494 *
495 * returns 0 on success or the proper error code
496 */
497 int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id,
498 int *tcold)
499 {
500 struct temp_sensor_registers *tsr;
501 u32 temp;
502 int ret;
503
504 ret = omap_bandgap_validate(bg_ptr, id);
505 if (ret)
506 return ret;
507
508 if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
509 return -ENOTSUPP;
510
511 tsr = bg_ptr->conf->sensors[id].registers;
512 temp = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
513 temp = (temp & tsr->threshold_tcold_mask)
514 >> __ffs(tsr->threshold_tcold_mask);
515 ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
516 if (ret)
517 return -EIO;
518
519 *tcold = temp;
520
521 return 0;
522 }
523
524 /**
525 * omap_bandgap_write_tcold() - sets the sensor tcold
526 * @bg_ptr - pointer to bandgap instance
527 * @id - sensor id
528 * @val - desired tcold value
529 *
530 * returns 0 on success or the proper error code
531 */
532 int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val)
533 {
534 struct temp_sensor_data *ts_data;
535 struct temp_sensor_registers *tsr;
536 u32 t_cold;
537 int ret;
538
539 ret = omap_bandgap_validate(bg_ptr, id);
540 if (ret)
541 return ret;
542
543 if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
544 return -ENOTSUPP;
545
546 ts_data = bg_ptr->conf->sensors[id].ts_data;
547 tsr = bg_ptr->conf->sensors[id].registers;
548 if (val > ts_data->max_temp + ts_data->hyst_val)
549 return -EINVAL;
550
551 ret = temp_to_adc_conversion(val, bg_ptr, id, &t_cold);
552 if (ret < 0)
553 return ret;
554
555 mutex_lock(&bg_ptr->bg_mutex);
556 temp_sensor_configure_tcold(bg_ptr, id, t_cold);
557 mutex_unlock(&bg_ptr->bg_mutex);
558
559 return 0;
560 }
561
562 /**
563 * omap_bandgap_read_update_interval() - read the sensor update interval
564 * @bg_ptr - pointer to bandgap instance
565 * @id - sensor id
566 * @interval - resulting update interval in miliseconds
567 *
568 * returns 0 on success or the proper error code
569 */
570 int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
571 int *interval)
572 {
573 struct temp_sensor_registers *tsr;
574 u32 time;
575 int ret;
576
577 ret = omap_bandgap_validate(bg_ptr, id);
578 if (ret)
579 return ret;
580
581 if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
582 return -ENOTSUPP;
583
584 tsr = bg_ptr->conf->sensors[id].registers;
585 time = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
586 time = (time & tsr->counter_mask) >> __ffs(tsr->counter_mask);
587 time = time * 1000 / bg_ptr->clk_rate;
588
589 *interval = time;
590
591 return 0;
592 }
593
594 /**
595 * omap_bandgap_write_update_interval() - set the update interval
596 * @bg_ptr - pointer to bandgap instance
597 * @id - sensor id
598 * @interval - desired update interval in miliseconds
599 *
600 * returns 0 on success or the proper error code
601 */
602 int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr,
603 int id, u32 interval)
604 {
605 int ret = omap_bandgap_validate(bg_ptr, id);
606 if (ret)
607 return ret;
608
609 if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
610 return -ENOTSUPP;
611
612 interval = interval * bg_ptr->clk_rate / 1000;
613 mutex_lock(&bg_ptr->bg_mutex);
614 RMW_BITS(bg_ptr, id, bgap_counter, counter_mask, interval);
615 mutex_unlock(&bg_ptr->bg_mutex);
616
617 return 0;
618 }
619
620 /**
621 * omap_bandgap_read_temperature() - report current temperature
622 * @bg_ptr - pointer to bandgap instance
623 * @id - sensor id
624 * @temperature - resulting temperature
625 *
626 * returns 0 on success or the proper error code
627 */
628 int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
629 int *temperature)
630 {
631 u32 temp;
632 int ret;
633
634 ret = omap_bandgap_validate(bg_ptr, id);
635 if (ret)
636 return ret;
637
638 mutex_lock(&bg_ptr->bg_mutex);
639 temp = omap_bandgap_read_temp(bg_ptr, id);
640 mutex_unlock(&bg_ptr->bg_mutex);
641
642 ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
643 if (ret)
644 return -EIO;
645
646 *temperature = temp;
647
648 return 0;
649 }
650
651 /**
652 * omap_bandgap_set_sensor_data() - helper function to store thermal
653 * framework related data.
654 * @bg_ptr - pointer to bandgap instance
655 * @id - sensor id
656 * @data - thermal framework related data to be stored
657 *
658 * returns 0 on success or the proper error code
659 */
660 int omap_bandgap_set_sensor_data(struct omap_bandgap *bg_ptr, int id,
661 void *data)
662 {
663 int ret = omap_bandgap_validate(bg_ptr, id);
664 if (ret)
665 return ret;
666
667 bg_ptr->conf->sensors[id].data = data;
668
669 return 0;
670 }
671
672 /**
673 * omap_bandgap_get_sensor_data() - helper function to get thermal
674 * framework related data.
675 * @bg_ptr - pointer to bandgap instance
676 * @id - sensor id
677 *
678 * returns data stored by set function with sensor id on success or NULL
679 */
680 void *omap_bandgap_get_sensor_data(struct omap_bandgap *bg_ptr, int id)
681 {
682 int ret = omap_bandgap_validate(bg_ptr, id);
683 if (ret)
684 return ERR_PTR(ret);
685
686 return bg_ptr->conf->sensors[id].data;
687 }
688
689 static int
690 omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
691 {
692 u32 temp = 0, counter = 1000;
693
694 /* Select single conversion mode */
695 if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
696 RMW_BITS(bg_ptr, id, bgap_mode_ctrl, mode_ctrl_mask, 0);
697
698 /* Start of Conversion = 1 */
699 RMW_BITS(bg_ptr, id, temp_sensor_ctrl, bgap_soc_mask, 1);
700 /* Wait until DTEMP is updated */
701 temp = omap_bandgap_read_temp(bg_ptr, id);
702
703 while ((temp == 0) && --counter)
704 temp = omap_bandgap_read_temp(bg_ptr, id);
705 /* REVISIT: Check correct condition for end of conversion */
706
707 /* Start of Conversion = 0 */
708 RMW_BITS(bg_ptr, id, temp_sensor_ctrl, bgap_soc_mask, 0);
709
710 return 0;
711 }
712
713 /**
714 * enable_continuous_mode() - One time enabling of continuous conversion mode
715 * @bg_ptr - pointer to scm instance
716 *
717 * Call this function only if HAS(MODE_CONFIG) is set
718 */
719 static int enable_continuous_mode(struct omap_bandgap *bg_ptr)
720 {
721 int i;
722
723 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
724 /* Perform a single read just before enabling continuous */
725 omap_bandgap_force_single_read(bg_ptr, i);
726 RMW_BITS(bg_ptr, i, bgap_mode_ctrl, mode_ctrl_mask, 1);
727 }
728
729 return 0;
730 }
731
732 static int omap_bandgap_tshut_init(struct omap_bandgap *bg_ptr,
733 struct platform_device *pdev)
734 {
735 int gpio_nr = bg_ptr->tshut_gpio;
736 int status;
737
738 /* Request for gpio_86 line */
739 status = gpio_request(gpio_nr, "tshut");
740 if (status < 0) {
741 dev_err(bg_ptr->dev,
742 "Could not request for TSHUT GPIO:%i\n", 86);
743 return status;
744 }
745 status = gpio_direction_input(gpio_nr);
746 if (status) {
747 dev_err(bg_ptr->dev,
748 "Cannot set input TSHUT GPIO %d\n", gpio_nr);
749 return status;
750 }
751
752 status = request_irq(gpio_to_irq(gpio_nr),
753 omap_bandgap_tshut_irq_handler,
754 IRQF_TRIGGER_RISING, "tshut",
755 NULL);
756 if (status) {
757 gpio_free(gpio_nr);
758 dev_err(bg_ptr->dev, "request irq failed for TSHUT");
759 }
760
761 return 0;
762 }
763
764 /* Initialization of Talert. Call it only if HAS(TALERT) is set */
765 static int omap_bandgap_talert_init(struct omap_bandgap *bg_ptr,
766 struct platform_device *pdev)
767 {
768 int ret;
769
770 bg_ptr->irq = platform_get_irq(pdev, 0);
771 if (bg_ptr->irq < 0) {
772 dev_err(&pdev->dev, "get_irq failed\n");
773 return bg_ptr->irq;
774 }
775 ret = request_threaded_irq(bg_ptr->irq, NULL,
776 omap_bandgap_talert_irq_handler,
777 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
778 "talert", bg_ptr);
779 if (ret) {
780 dev_err(&pdev->dev, "Request threaded irq failed.\n");
781 return ret;
782 }
783
784 return 0;
785 }
786
787 static const struct of_device_id of_omap_bandgap_match[];
788 static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
789 {
790 struct device_node *node = pdev->dev.of_node;
791 const struct of_device_id *of_id;
792 struct omap_bandgap *bg_ptr;
793 struct resource *res;
794 u32 prop;
795 int i;
796
797 /* just for the sake */
798 if (!node) {
799 dev_err(&pdev->dev, "no platform information available\n");
800 return ERR_PTR(-EINVAL);
801 }
802
803 bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap),
804 GFP_KERNEL);
805 if (!bg_ptr) {
806 dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
807 return ERR_PTR(-ENOMEM);
808 }
809
810 of_id = of_match_device(of_omap_bandgap_match, &pdev->dev);
811 if (of_id)
812 bg_ptr->conf = of_id->data;
813
814 i = 0;
815 do {
816 void __iomem *chunk;
817
818 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
819 if (!res)
820 break;
821 chunk = devm_ioremap_resource(&pdev->dev, res);
822 if (i == 0)
823 bg_ptr->base = chunk;
824 if (IS_ERR(chunk))
825 return ERR_CAST(chunk);
826
827 i++;
828 } while (res);
829
830 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
831 if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) {
832 dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
833 return ERR_PTR(-EINVAL);
834 }
835 bg_ptr->tshut_gpio = prop;
836 if (!gpio_is_valid(bg_ptr->tshut_gpio)) {
837 dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
838 bg_ptr->tshut_gpio);
839 return ERR_PTR(-EINVAL);
840 }
841 }
842
843 return bg_ptr;
844 }
845
846 static
847 int omap_bandgap_probe(struct platform_device *pdev)
848 {
849 struct omap_bandgap *bg_ptr;
850 int clk_rate, ret = 0, i;
851
852 bg_ptr = omap_bandgap_build(pdev);
853 if (IS_ERR_OR_NULL(bg_ptr)) {
854 dev_err(&pdev->dev, "failed to fetch platform data\n");
855 return PTR_ERR(bg_ptr);
856 }
857 bg_ptr->dev = &pdev->dev;
858
859 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
860 ret = omap_bandgap_tshut_init(bg_ptr, pdev);
861 if (ret) {
862 dev_err(&pdev->dev,
863 "failed to initialize system tshut IRQ\n");
864 return ret;
865 }
866 }
867
868 bg_ptr->fclock = clk_get(NULL, bg_ptr->conf->fclock_name);
869 ret = IS_ERR_OR_NULL(bg_ptr->fclock);
870 if (ret) {
871 dev_err(&pdev->dev, "failed to request fclock reference\n");
872 goto free_irqs;
873 }
874
875 bg_ptr->div_clk = clk_get(NULL, bg_ptr->conf->div_ck_name);
876 ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
877 if (ret) {
878 dev_err(&pdev->dev,
879 "failed to request div_ts_ck clock ref\n");
880 goto free_irqs;
881 }
882
883 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
884 struct temp_sensor_registers *tsr;
885 u32 val;
886
887 tsr = bg_ptr->conf->sensors[i].registers;
888 /*
889 * check if the efuse has a non-zero value if not
890 * it is an untrimmed sample and the temperatures
891 * may not be accurate
892 */
893 val = omap_bandgap_readl(bg_ptr, tsr->bgap_efuse);
894 if (ret || !val)
895 dev_info(&pdev->dev,
896 "Non-trimmed BGAP, Temp not accurate\n");
897 }
898
899 clk_rate = clk_round_rate(bg_ptr->div_clk,
900 bg_ptr->conf->sensors[0].ts_data->max_freq);
901 if (clk_rate < bg_ptr->conf->sensors[0].ts_data->min_freq ||
902 clk_rate == 0xffffffff) {
903 ret = -ENODEV;
904 dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
905 goto put_clks;
906 }
907
908 ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
909 if (ret)
910 dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");
911
912 bg_ptr->clk_rate = clk_rate;
913 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
914 clk_prepare_enable(bg_ptr->fclock);
915
916
917 mutex_init(&bg_ptr->bg_mutex);
918 bg_ptr->dev = &pdev->dev;
919 platform_set_drvdata(pdev, bg_ptr);
920
921 omap_bandgap_power(bg_ptr, true);
922
923 /* Set default counter to 1 for now */
924 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
925 for (i = 0; i < bg_ptr->conf->sensor_count; i++)
926 RMW_BITS(bg_ptr, i, bgap_counter, counter_mask, 1);
927
928 /* Set default thresholds for alert and shutdown */
929 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
930 struct temp_sensor_data *ts_data;
931
932 ts_data = bg_ptr->conf->sensors[i].ts_data;
933
934 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
935 /* Set initial Talert thresholds */
936 RMW_BITS(bg_ptr, i, bgap_threshold,
937 threshold_tcold_mask, ts_data->t_cold);
938 RMW_BITS(bg_ptr, i, bgap_threshold,
939 threshold_thot_mask, ts_data->t_hot);
940 /* Enable the alert events */
941 RMW_BITS(bg_ptr, i, bgap_mask_ctrl, mask_hot_mask, 1);
942 RMW_BITS(bg_ptr, i, bgap_mask_ctrl, mask_cold_mask, 1);
943 }
944
945 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) {
946 /* Set initial Tshut thresholds */
947 RMW_BITS(bg_ptr, i, tshut_threshold,
948 tshut_hot_mask, ts_data->tshut_hot);
949 RMW_BITS(bg_ptr, i, tshut_threshold,
950 tshut_cold_mask, ts_data->tshut_cold);
951 }
952 }
953
954 if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
955 enable_continuous_mode(bg_ptr);
956
957 /* Set .250 seconds time as default counter */
958 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
959 for (i = 0; i < bg_ptr->conf->sensor_count; i++)
960 RMW_BITS(bg_ptr, i, bgap_counter, counter_mask,
961 bg_ptr->clk_rate / 4);
962
963 /* Every thing is good? Then expose the sensors */
964 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
965 char *domain;
966
967 if (bg_ptr->conf->sensors[i].register_cooling)
968 bg_ptr->conf->sensors[i].register_cooling(bg_ptr, i);
969
970 domain = bg_ptr->conf->sensors[i].domain;
971 if (bg_ptr->conf->expose_sensor)
972 bg_ptr->conf->expose_sensor(bg_ptr, i, domain);
973 }
974
975 /*
976 * Enable the Interrupts once everything is set. Otherwise irq handler
977 * might be called as soon as it is enabled where as rest of framework
978 * is still getting initialised.
979 */
980 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
981 ret = omap_bandgap_talert_init(bg_ptr, pdev);
982 if (ret) {
983 dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
984 i = bg_ptr->conf->sensor_count;
985 goto disable_clk;
986 }
987 }
988
989 return 0;
990
991 disable_clk:
992 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
993 clk_disable_unprepare(bg_ptr->fclock);
994 put_clks:
995 clk_put(bg_ptr->fclock);
996 clk_put(bg_ptr->div_clk);
997 free_irqs:
998 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
999 free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
1000 gpio_free(bg_ptr->tshut_gpio);
1001 }
1002
1003 return ret;
1004 }
1005
1006 static
1007 int omap_bandgap_remove(struct platform_device *pdev)
1008 {
1009 struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
1010 int i;
1011
1012 /* First thing is to remove sensor interfaces */
1013 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
1014 if (bg_ptr->conf->sensors[i].register_cooling)
1015 bg_ptr->conf->sensors[i].unregister_cooling(bg_ptr, i);
1016
1017 if (bg_ptr->conf->remove_sensor)
1018 bg_ptr->conf->remove_sensor(bg_ptr, i);
1019 }
1020
1021 omap_bandgap_power(bg_ptr, false);
1022
1023 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
1024 clk_disable_unprepare(bg_ptr->fclock);
1025 clk_put(bg_ptr->fclock);
1026 clk_put(bg_ptr->div_clk);
1027
1028 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT))
1029 free_irq(bg_ptr->irq, bg_ptr);
1030
1031 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
1032 free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
1033 gpio_free(bg_ptr->tshut_gpio);
1034 }
1035
1036 return 0;
1037 }
1038
1039 #ifdef CONFIG_PM
1040 static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
1041 {
1042 int i;
1043
1044 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
1045 struct temp_sensor_registers *tsr;
1046 struct temp_sensor_regval *rval;
1047
1048 rval = &bg_ptr->conf->sensors[i].regval;
1049 tsr = bg_ptr->conf->sensors[i].registers;
1050
1051 if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
1052 rval->bg_mode_ctrl = omap_bandgap_readl(bg_ptr,
1053 tsr->bgap_mode_ctrl);
1054 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
1055 rval->bg_counter = omap_bandgap_readl(bg_ptr,
1056 tsr->bgap_counter);
1057 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
1058 rval->bg_threshold = omap_bandgap_readl(bg_ptr,
1059 tsr->bgap_threshold);
1060 rval->bg_ctrl = omap_bandgap_readl(bg_ptr,
1061 tsr->bgap_mask_ctrl);
1062 }
1063
1064 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
1065 rval->tshut_threshold = omap_bandgap_readl(bg_ptr,
1066 tsr->tshut_threshold);
1067 }
1068
1069 return 0;
1070 }
1071
1072 static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
1073 {
1074 int i;
1075
1076 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
1077 struct temp_sensor_registers *tsr;
1078 struct temp_sensor_regval *rval;
1079 u32 val = 0;
1080
1081 rval = &bg_ptr->conf->sensors[i].regval;
1082 tsr = bg_ptr->conf->sensors[i].registers;
1083
1084 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
1085 val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
1086
1087 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
1088 omap_bandgap_writel(bg_ptr, rval->tshut_threshold,
1089 tsr->tshut_threshold);
1090 /* Force immediate temperature measurement and update
1091 * of the DTEMP field
1092 */
1093 omap_bandgap_force_single_read(bg_ptr, i);
1094
1095 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
1096 omap_bandgap_writel(bg_ptr, rval->bg_counter,
1097 tsr->bgap_counter);
1098 if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
1099 omap_bandgap_writel(bg_ptr, rval->bg_mode_ctrl,
1100 tsr->bgap_mode_ctrl);
1101 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
1102 omap_bandgap_writel(bg_ptr, rval->bg_threshold,
1103 tsr->bgap_threshold);
1104 omap_bandgap_writel(bg_ptr, rval->bg_ctrl,
1105 tsr->bgap_mask_ctrl);
1106 }
1107 }
1108
1109 return 0;
1110 }
1111
1112 static int omap_bandgap_suspend(struct device *dev)
1113 {
1114 struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
1115 int err;
1116
1117 err = omap_bandgap_save_ctxt(bg_ptr);
1118 omap_bandgap_power(bg_ptr, false);
1119
1120 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
1121 clk_disable_unprepare(bg_ptr->fclock);
1122
1123 return err;
1124 }
1125
1126 static int omap_bandgap_resume(struct device *dev)
1127 {
1128 struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
1129
1130 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
1131 clk_prepare_enable(bg_ptr->fclock);
1132
1133 omap_bandgap_power(bg_ptr, true);
1134
1135 return omap_bandgap_restore_ctxt(bg_ptr);
1136 }
1137 static const struct dev_pm_ops omap_bandgap_dev_pm_ops = {
1138 SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend,
1139 omap_bandgap_resume)
1140 };
1141
1142 #define DEV_PM_OPS (&omap_bandgap_dev_pm_ops)
1143 #else
1144 #define DEV_PM_OPS NULL
1145 #endif
1146
1147 static const struct of_device_id of_omap_bandgap_match[] = {
1148 #ifdef CONFIG_OMAP4_THERMAL
1149 {
1150 .compatible = "ti,omap4430-bandgap",
1151 .data = (void *)&omap4430_data,
1152 },
1153 {
1154 .compatible = "ti,omap4460-bandgap",
1155 .data = (void *)&omap4460_data,
1156 },
1157 {
1158 .compatible = "ti,omap4470-bandgap",
1159 .data = (void *)&omap4470_data,
1160 },
1161 #endif
1162 #ifdef CONFIG_OMAP5_THERMAL
1163 {
1164 .compatible = "ti,omap5430-bandgap",
1165 .data = (void *)&omap5430_data,
1166 },
1167 #endif
1168 /* Sentinel */
1169 { },
1170 };
1171 MODULE_DEVICE_TABLE(of, of_omap_bandgap_match);
1172
1173 static struct platform_driver omap_bandgap_sensor_driver = {
1174 .probe = omap_bandgap_probe,
1175 .remove = omap_bandgap_remove,
1176 .driver = {
1177 .name = "omap-bandgap",
1178 .pm = DEV_PM_OPS,
1179 .of_match_table = of_omap_bandgap_match,
1180 },
1181 };
1182
1183 module_platform_driver(omap_bandgap_sensor_driver);
1184
1185 MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
1186 MODULE_LICENSE("GPL v2");
1187 MODULE_ALIAS("platform:omap-bandgap");
1188 MODULE_AUTHOR("Texas Instrument Inc.");
This page took 0.117108 seconds and 4 git commands to generate.