2 * OMAP4 Bandgap temperature sensor driver
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>
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.
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.
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
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>
43 #include "omap-bandgap.h"
45 static u32 omap_bandgap_readl(struct omap_bandgap *bg_ptr, u32 reg)
47 return readl(bg_ptr->base + reg);
50 static void omap_bandgap_writel(struct omap_bandgap *bg_ptr, u32 val, u32 reg)
52 writel(val, bg_ptr->base + reg);
55 static int omap_bandgap_power(struct omap_bandgap *bg_ptr, bool on)
57 struct temp_sensor_registers *tsr;
61 if (!OMAP_BANDGAP_HAS(bg_ptr, POWER_SWITCH))
64 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
65 tsr = bg_ptr->conf->sensors[i].registers;
66 ctrl = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
67 ctrl &= ~tsr->bgap_tempsoff_mask;
69 ctrl |= !on << __ffs(tsr->bgap_tempsoff_mask);
71 /* write BGAP_TEMPSOFF should be reset to 0 */
72 omap_bandgap_writel(bg_ptr, ctrl, tsr->temp_sensor_ctrl);
78 static u32 omap_bandgap_read_temp(struct omap_bandgap *bg_ptr, int id)
80 struct temp_sensor_registers *tsr;
83 tsr = bg_ptr->conf->sensors[id].registers;
84 reg = tsr->temp_sensor_ctrl;
86 if (OMAP_BANDGAP_HAS(bg_ptr, FREEZE_BIT)) {
87 ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
88 ctrl |= tsr->mask_freeze_mask;
89 omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
91 * In case we cannot read from cur_dtemp / dtemp_0,
92 * then we read from the last valid temp read
94 reg = tsr->ctrl_dtemp_1;
97 /* read temperature */
98 temp = omap_bandgap_readl(bg_ptr, reg);
99 temp &= tsr->bgap_dtemp_mask;
101 if (OMAP_BANDGAP_HAS(bg_ptr, FREEZE_BIT)) {
102 ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
103 ctrl &= ~tsr->mask_freeze_mask;
104 omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
110 /* This is the Talert handler. Call it only if HAS(TALERT) is set */
111 static irqreturn_t talert_irq_handler(int irq, void *data)
113 struct omap_bandgap *bg_ptr = data;
114 struct temp_sensor_registers *tsr;
115 u32 t_hot = 0, t_cold = 0, ctrl;
119 /* Read the status of t_hot */
120 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
121 tsr = bg_ptr->conf->sensors[i].registers;
122 t_hot = omap_bandgap_readl(bg_ptr, tsr->bgap_status);
123 t_hot &= tsr->status_hot_mask;
125 /* Read the status of t_cold */
126 t_cold = omap_bandgap_readl(bg_ptr, tsr->bgap_status);
127 t_cold &= tsr->status_cold_mask;
129 if (!t_cold && !t_hot)
132 ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
134 * One TALERT interrupt: Two sources
135 * If the interrupt is due to t_hot then mask t_hot and
136 * and unmask t_cold else mask t_cold and unmask t_hot
139 ctrl &= ~tsr->mask_hot_mask;
140 ctrl |= tsr->mask_cold_mask;
142 ctrl &= ~tsr->mask_cold_mask;
143 ctrl |= tsr->mask_hot_mask;
146 omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
149 "%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
150 __func__, bg_ptr->conf->sensors[i].domain,
153 /* report temperature to whom may concern */
154 if (bg_ptr->conf->report_temperature)
155 bg_ptr->conf->report_temperature(bg_ptr, i);
161 /* This is the Tshut handler. Call it only if HAS(TSHUT) is set */
162 static irqreturn_t omap_bandgap_tshut_irq_handler(int irq, void *data)
164 pr_emerg("%s: TSHUT temperature reached. Needs shut down...\n",
167 orderly_poweroff(true);
173 int adc_to_temp_conversion(struct omap_bandgap *bg_ptr, int id, int adc_val,
176 struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
178 /* look up for temperature in the table and return the temperature */
179 if (adc_val < ts_data->adc_start_val || adc_val > ts_data->adc_end_val)
182 *t = bg_ptr->conf->conv_table[adc_val - ts_data->adc_start_val];
187 static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i,
190 struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[i].ts_data;
191 const int *conv_table = bg_ptr->conf->conv_table;
195 high = ts_data->adc_end_val - ts_data->adc_start_val;
196 mid = (high + low) / 2;
198 if (temp < conv_table[low] || temp > conv_table[high])
202 if (temp < conv_table[mid])
206 mid = (low + high) / 2;
209 *adc = ts_data->adc_start_val + low;
214 /* Talert masks. Call it only if HAS(TALERT) is set */
215 static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id,
216 u32 t_hot, u32 t_cold)
218 struct temp_sensor_registers *tsr;
221 /* Read the current on die temperature */
222 temp = omap_bandgap_read_temp(bg_ptr, id);
224 tsr = bg_ptr->conf->sensors[id].registers;
225 reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
228 reg_val |= tsr->mask_hot_mask;
230 reg_val &= ~tsr->mask_hot_mask;
233 reg_val |= tsr->mask_cold_mask;
235 reg_val &= ~tsr->mask_cold_mask;
236 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl);
242 int add_hyst(int adc_val, int hyst_val, struct omap_bandgap *bg_ptr, int i,
247 ret = adc_to_temp_conversion(bg_ptr, i, adc_val, &temp);
253 return temp_to_adc_conversion(temp, bg_ptr, i, sum);
256 /* Talert Thot threshold. Call it only if HAS(TALERT) is set */
258 int temp_sensor_configure_thot(struct omap_bandgap *bg_ptr, int id, int t_hot)
260 struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
261 struct temp_sensor_registers *tsr;
262 u32 thresh_val, reg_val;
265 tsr = bg_ptr->conf->sensors[id].registers;
267 /* obtain the T cold value */
268 thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
269 cold = (thresh_val & tsr->threshold_tcold_mask) >>
270 __ffs(tsr->threshold_tcold_mask);
272 /* change the t_cold to t_hot - 5000 millidegrees */
273 err |= add_hyst(t_hot, -ts_data->hyst_val, bg_ptr, id, &cold);
274 /* write the new t_cold value */
275 reg_val = thresh_val & (~tsr->threshold_tcold_mask);
276 reg_val |= cold << __ffs(tsr->threshold_tcold_mask);
277 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
278 thresh_val = reg_val;
281 /* write the new t_hot value */
282 reg_val = thresh_val & ~tsr->threshold_thot_mask;
283 reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
284 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
286 dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
290 return temp_sensor_unmask_interrupts(bg_ptr, id, t_hot, cold);
293 /* Talert Thot and Tcold thresholds. Call it only if HAS(TALERT) is set */
295 int temp_sensor_init_talert_thresholds(struct omap_bandgap *bg_ptr, int id,
296 int t_hot, int t_cold)
298 struct temp_sensor_registers *tsr;
299 u32 reg_val, thresh_val;
301 tsr = bg_ptr->conf->sensors[id].registers;
302 thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
304 /* write the new t_cold value */
305 reg_val = thresh_val & ~tsr->threshold_tcold_mask;
306 reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
307 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
309 thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
311 /* write the new t_hot value */
312 reg_val = thresh_val & ~tsr->threshold_thot_mask;
313 reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
314 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
316 reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
317 reg_val |= tsr->mask_hot_mask;
318 reg_val |= tsr->mask_cold_mask;
319 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl);
324 /* Talert Tcold threshold. Call it only if HAS(TALERT) is set */
326 int temp_sensor_configure_tcold(struct omap_bandgap *bg_ptr, int id,
329 struct temp_sensor_data *ts_data = bg_ptr->conf->sensors[id].ts_data;
330 struct temp_sensor_registers *tsr;
331 u32 thresh_val, reg_val;
334 tsr = bg_ptr->conf->sensors[id].registers;
335 /* obtain the T cold value */
336 thresh_val = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
337 hot = (thresh_val & tsr->threshold_thot_mask) >>
338 __ffs(tsr->threshold_thot_mask);
341 /* change the t_hot to t_cold + 5000 millidegrees */
342 err |= add_hyst(t_cold, ts_data->hyst_val, bg_ptr, id, &hot);
343 /* write the new t_hot value */
344 reg_val = thresh_val & (~tsr->threshold_thot_mask);
345 reg_val |= hot << __ffs(tsr->threshold_thot_mask);
346 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
347 thresh_val = reg_val;
350 /* write the new t_cold value */
351 reg_val = thresh_val & ~tsr->threshold_tcold_mask;
352 reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
353 omap_bandgap_writel(bg_ptr, reg_val, tsr->bgap_threshold);
355 dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
359 return temp_sensor_unmask_interrupts(bg_ptr, id, hot, t_cold);
362 /* This is Tshut Thot config. Call it only if HAS(TSHUT_CONFIG) is set */
363 static int temp_sensor_configure_tshut_hot(struct omap_bandgap *bg_ptr,
364 int id, int tshut_hot)
366 struct temp_sensor_registers *tsr;
369 tsr = bg_ptr->conf->sensors[id].registers;
370 reg_val = omap_bandgap_readl(bg_ptr, tsr->tshut_threshold);
371 reg_val &= ~tsr->tshut_hot_mask;
372 reg_val |= tshut_hot << __ffs(tsr->tshut_hot_mask);
373 omap_bandgap_writel(bg_ptr, reg_val, tsr->tshut_threshold);
378 /* This is Tshut Tcold config. Call it only if HAS(TSHUT_CONFIG) is set */
379 static int temp_sensor_configure_tshut_cold(struct omap_bandgap *bg_ptr,
380 int id, int tshut_cold)
382 struct temp_sensor_registers *tsr;
385 tsr = bg_ptr->conf->sensors[id].registers;
386 reg_val = omap_bandgap_readl(bg_ptr, tsr->tshut_threshold);
387 reg_val &= ~tsr->tshut_cold_mask;
388 reg_val |= tshut_cold << __ffs(tsr->tshut_cold_mask);
389 omap_bandgap_writel(bg_ptr, reg_val, tsr->tshut_threshold);
394 /* This is counter config. Call it only if HAS(COUNTER) is set */
395 static int configure_temp_sensor_counter(struct omap_bandgap *bg_ptr, int id,
398 struct temp_sensor_registers *tsr;
401 tsr = bg_ptr->conf->sensors[id].registers;
402 val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
403 val &= ~tsr->counter_mask;
404 val |= counter << __ffs(tsr->counter_mask);
405 omap_bandgap_writel(bg_ptr, val, tsr->bgap_counter);
410 #define bandgap_is_valid(b) \
412 #define bandgap_is_valid_sensor_id(b, i) \
413 ((i) >= 0 && (i) < (b)->conf->sensor_count)
414 static inline int omap_bandgap_validate(struct omap_bandgap *bg_ptr, int id)
416 if (!bandgap_is_valid(bg_ptr)) {
417 pr_err("%s: invalid bandgap pointer\n", __func__);
421 if (!bandgap_is_valid_sensor_id(bg_ptr, id)) {
422 dev_err(bg_ptr->dev, "%s: sensor id out of range (%d)\n",
432 * omap_bandgap_read_thot() - reads sensor current thot
433 * @bg_ptr - pointer to bandgap instance
435 * @thot - resulting current thot value
437 * returns 0 on success or the proper error code
439 int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id,
442 struct temp_sensor_registers *tsr;
446 ret = omap_bandgap_validate(bg_ptr, id);
450 if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
453 tsr = bg_ptr->conf->sensors[id].registers;
454 temp = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
455 temp = (temp & tsr->threshold_thot_mask) >>
456 __ffs(tsr->threshold_thot_mask);
457 ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
459 dev_err(bg_ptr->dev, "failed to read thot\n");
469 * omap_bandgap_write_thot() - sets sensor current thot
470 * @bg_ptr - pointer to bandgap instance
472 * @val - desired thot value
474 * returns 0 on success or the proper error code
476 int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val)
478 struct temp_sensor_data *ts_data;
479 struct temp_sensor_registers *tsr;
483 ret = omap_bandgap_validate(bg_ptr, id);
487 if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
490 ts_data = bg_ptr->conf->sensors[id].ts_data;
491 tsr = bg_ptr->conf->sensors[id].registers;
493 if (val < ts_data->min_temp + ts_data->hyst_val)
495 ret = temp_to_adc_conversion(val, bg_ptr, id, &t_hot);
499 mutex_lock(&bg_ptr->bg_mutex);
500 temp_sensor_configure_thot(bg_ptr, id, t_hot);
501 mutex_unlock(&bg_ptr->bg_mutex);
507 * omap_bandgap_read_tcold() - reads sensor current tcold
508 * @bg_ptr - pointer to bandgap instance
510 * @tcold - resulting current tcold value
512 * returns 0 on success or the proper error code
514 int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id,
517 struct temp_sensor_registers *tsr;
521 ret = omap_bandgap_validate(bg_ptr, id);
525 if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
528 tsr = bg_ptr->conf->sensors[id].registers;
529 temp = omap_bandgap_readl(bg_ptr, tsr->bgap_threshold);
530 temp = (temp & tsr->threshold_tcold_mask)
531 >> __ffs(tsr->threshold_tcold_mask);
532 ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
542 * omap_bandgap_write_tcold() - sets the sensor tcold
543 * @bg_ptr - pointer to bandgap instance
545 * @val - desired tcold value
547 * returns 0 on success or the proper error code
549 int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val)
551 struct temp_sensor_data *ts_data;
552 struct temp_sensor_registers *tsr;
556 ret = omap_bandgap_validate(bg_ptr, id);
560 if (!OMAP_BANDGAP_HAS(bg_ptr, TALERT))
563 ts_data = bg_ptr->conf->sensors[id].ts_data;
564 tsr = bg_ptr->conf->sensors[id].registers;
565 if (val > ts_data->max_temp + ts_data->hyst_val)
568 ret = temp_to_adc_conversion(val, bg_ptr, id, &t_cold);
572 mutex_lock(&bg_ptr->bg_mutex);
573 temp_sensor_configure_tcold(bg_ptr, id, t_cold);
574 mutex_unlock(&bg_ptr->bg_mutex);
580 * omap_bandgap_read_update_interval() - read the sensor update interval
581 * @bg_ptr - pointer to bandgap instance
583 * @interval - resulting update interval in miliseconds
585 * returns 0 on success or the proper error code
587 int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
590 struct temp_sensor_registers *tsr;
594 ret = omap_bandgap_validate(bg_ptr, id);
598 if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
601 tsr = bg_ptr->conf->sensors[id].registers;
602 time = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
603 time = (time & tsr->counter_mask) >> __ffs(tsr->counter_mask);
604 time = time * 1000 / bg_ptr->clk_rate;
612 * omap_bandgap_write_update_interval() - set the update interval
613 * @bg_ptr - pointer to bandgap instance
615 * @interval - desired update interval in miliseconds
617 * returns 0 on success or the proper error code
619 int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr,
620 int id, u32 interval)
622 int ret = omap_bandgap_validate(bg_ptr, id);
626 if (!OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
629 interval = interval * bg_ptr->clk_rate / 1000;
630 mutex_lock(&bg_ptr->bg_mutex);
631 configure_temp_sensor_counter(bg_ptr, id, interval);
632 mutex_unlock(&bg_ptr->bg_mutex);
638 * omap_bandgap_read_temperature() - report current temperature
639 * @bg_ptr - pointer to bandgap instance
641 * @temperature - resulting temperature
643 * returns 0 on success or the proper error code
645 int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
648 struct temp_sensor_registers *tsr;
652 ret = omap_bandgap_validate(bg_ptr, id);
656 tsr = bg_ptr->conf->sensors[id].registers;
657 mutex_lock(&bg_ptr->bg_mutex);
658 temp = omap_bandgap_read_temp(bg_ptr, id);
659 mutex_unlock(&bg_ptr->bg_mutex);
661 ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
671 * omap_bandgap_set_sensor_data() - helper function to store thermal
672 * framework related data.
673 * @bg_ptr - pointer to bandgap instance
675 * @data - thermal framework related data to be stored
677 * returns 0 on success or the proper error code
679 int omap_bandgap_set_sensor_data(struct omap_bandgap *bg_ptr, int id,
682 int ret = omap_bandgap_validate(bg_ptr, id);
686 bg_ptr->conf->sensors[id].data = data;
692 * omap_bandgap_get_sensor_data() - helper function to get thermal
693 * framework related data.
694 * @bg_ptr - pointer to bandgap instance
697 * returns data stored by set function with sensor id on success or NULL
699 void *omap_bandgap_get_sensor_data(struct omap_bandgap *bg_ptr, int id)
701 int ret = omap_bandgap_validate(bg_ptr, id);
705 return bg_ptr->conf->sensors[id].data;
709 omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
711 struct temp_sensor_registers *tsr;
712 u32 temp = 0, counter = 1000;
714 tsr = bg_ptr->conf->sensors[id].registers;
715 /* Select single conversion mode */
716 if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG)) {
717 temp = omap_bandgap_readl(bg_ptr, tsr->bgap_mode_ctrl);
718 temp &= ~(1 << __ffs(tsr->mode_ctrl_mask));
719 omap_bandgap_writel(bg_ptr, temp, tsr->bgap_mode_ctrl);
722 /* Start of Conversion = 1 */
723 temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
724 temp |= 1 << __ffs(tsr->bgap_soc_mask);
725 omap_bandgap_writel(bg_ptr, temp, tsr->temp_sensor_ctrl);
726 /* Wait until DTEMP is updated */
727 temp = omap_bandgap_read_temp(bg_ptr, id);
729 while ((temp == 0) && --counter)
730 temp = omap_bandgap_read_temp(bg_ptr, id);
732 /* Start of Conversion = 0 */
733 temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
734 temp &= ~(1 << __ffs(tsr->bgap_soc_mask));
735 omap_bandgap_writel(bg_ptr, temp, tsr->temp_sensor_ctrl);
741 * enable_continuous_mode() - One time enabling of continuous conversion mode
742 * @bg_ptr - pointer to scm instance
744 * Call this function only if HAS(MODE_CONFIG) is set
746 static int enable_continuous_mode(struct omap_bandgap *bg_ptr)
748 struct temp_sensor_registers *tsr;
752 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
753 /* Perform a single read just before enabling continuous */
754 omap_bandgap_force_single_read(bg_ptr, i);
755 tsr = bg_ptr->conf->sensors[i].registers;
756 val = omap_bandgap_readl(bg_ptr, tsr->bgap_mode_ctrl);
757 val |= 1 << __ffs(tsr->mode_ctrl_mask);
758 omap_bandgap_writel(bg_ptr, val, tsr->bgap_mode_ctrl);
764 static int omap_bandgap_tshut_init(struct omap_bandgap *bg_ptr,
765 struct platform_device *pdev)
767 int gpio_nr = bg_ptr->tshut_gpio;
770 /* Request for gpio_86 line */
771 status = gpio_request(gpio_nr, "tshut");
774 "Could not request for TSHUT GPIO:%i\n", 86);
777 status = gpio_direction_input(gpio_nr);
780 "Cannot set input TSHUT GPIO %d\n", gpio_nr);
784 status = request_irq(gpio_to_irq(gpio_nr),
785 omap_bandgap_tshut_irq_handler,
786 IRQF_TRIGGER_RISING, "tshut",
790 dev_err(bg_ptr->dev, "request irq failed for TSHUT");
796 /* Initialization of Talert. Call it only if HAS(TALERT) is set */
797 static int omap_bandgap_talert_init(struct omap_bandgap *bg_ptr,
798 struct platform_device *pdev)
802 bg_ptr->irq = platform_get_irq(pdev, 0);
803 if (bg_ptr->irq < 0) {
804 dev_err(&pdev->dev, "get_irq failed\n");
807 ret = request_threaded_irq(bg_ptr->irq, NULL,
809 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
812 dev_err(&pdev->dev, "Request threaded irq failed.\n");
819 static const struct of_device_id of_omap_bandgap_match[];
820 static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
822 struct device_node *node = pdev->dev.of_node;
823 const struct of_device_id *of_id;
824 struct omap_bandgap *bg_ptr;
825 struct resource *res;
829 /* just for the sake */
831 dev_err(&pdev->dev, "no platform information available\n");
832 return ERR_PTR(-EINVAL);
835 bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap),
838 dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
839 return ERR_PTR(-ENOMEM);
842 of_id = of_match_device(of_omap_bandgap_match, &pdev->dev);
844 bg_ptr->conf = of_id->data;
850 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
853 chunk = devm_ioremap_resource(&pdev->dev, res);
855 bg_ptr->base = chunk;
857 return ERR_CAST(chunk);
862 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
863 if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) {
864 dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
865 return ERR_PTR(-EINVAL);
867 bg_ptr->tshut_gpio = prop;
868 if (!gpio_is_valid(bg_ptr->tshut_gpio)) {
869 dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
871 return ERR_PTR(-EINVAL);
879 int omap_bandgap_probe(struct platform_device *pdev)
881 struct omap_bandgap *bg_ptr;
882 int clk_rate, ret = 0, i;
884 bg_ptr = omap_bandgap_build(pdev);
885 if (IS_ERR_OR_NULL(bg_ptr)) {
886 dev_err(&pdev->dev, "failed to fetch platform data\n");
887 return PTR_ERR(bg_ptr);
889 bg_ptr->dev = &pdev->dev;
891 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
892 ret = omap_bandgap_tshut_init(bg_ptr, pdev);
895 "failed to initialize system tshut IRQ\n");
900 bg_ptr->fclock = clk_get(NULL, bg_ptr->conf->fclock_name);
901 ret = IS_ERR_OR_NULL(bg_ptr->fclock);
903 dev_err(&pdev->dev, "failed to request fclock reference\n");
907 bg_ptr->div_clk = clk_get(NULL, bg_ptr->conf->div_ck_name);
908 ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
911 "failed to request div_ts_ck clock ref\n");
915 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
916 struct temp_sensor_registers *tsr;
919 tsr = bg_ptr->conf->sensors[i].registers;
921 * check if the efuse has a non-zero value if not
922 * it is an untrimmed sample and the temperatures
923 * may not be accurate
925 val = omap_bandgap_readl(bg_ptr, tsr->bgap_efuse);
928 "Non-trimmed BGAP, Temp not accurate\n");
931 clk_rate = clk_round_rate(bg_ptr->div_clk,
932 bg_ptr->conf->sensors[0].ts_data->max_freq);
933 if (clk_rate < bg_ptr->conf->sensors[0].ts_data->min_freq ||
934 clk_rate == 0xffffffff) {
936 dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
940 ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
942 dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");
944 bg_ptr->clk_rate = clk_rate;
945 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
946 clk_prepare_enable(bg_ptr->fclock);
949 mutex_init(&bg_ptr->bg_mutex);
950 bg_ptr->dev = &pdev->dev;
951 platform_set_drvdata(pdev, bg_ptr);
953 omap_bandgap_power(bg_ptr, true);
955 /* Set default counter to 1 for now */
956 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
957 for (i = 0; i < bg_ptr->conf->sensor_count; i++)
958 configure_temp_sensor_counter(bg_ptr, i, 1);
960 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
961 struct temp_sensor_data *ts_data;
963 ts_data = bg_ptr->conf->sensors[i].ts_data;
965 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT))
966 temp_sensor_init_talert_thresholds(bg_ptr, i,
969 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG)) {
970 temp_sensor_configure_tshut_hot(bg_ptr, i,
972 temp_sensor_configure_tshut_cold(bg_ptr, i,
973 ts_data->tshut_cold);
977 if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
978 enable_continuous_mode(bg_ptr);
980 /* Set .250 seconds time as default counter */
981 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
982 for (i = 0; i < bg_ptr->conf->sensor_count; i++)
983 configure_temp_sensor_counter(bg_ptr, i,
984 bg_ptr->clk_rate / 4);
986 /* Every thing is good? Then expose the sensors */
987 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
990 if (bg_ptr->conf->sensors[i].register_cooling)
991 bg_ptr->conf->sensors[i].register_cooling(bg_ptr, i);
993 domain = bg_ptr->conf->sensors[i].domain;
994 if (bg_ptr->conf->expose_sensor)
995 bg_ptr->conf->expose_sensor(bg_ptr, i, domain);
999 * Enable the Interrupts once everything is set. Otherwise irq handler
1000 * might be called as soon as it is enabled where as rest of framework
1001 * is still getting initialised.
1003 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
1004 ret = omap_bandgap_talert_init(bg_ptr, pdev);
1006 dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
1007 i = bg_ptr->conf->sensor_count;
1015 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
1016 clk_disable_unprepare(bg_ptr->fclock);
1018 clk_put(bg_ptr->fclock);
1019 clk_put(bg_ptr->div_clk);
1021 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
1022 free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
1023 gpio_free(bg_ptr->tshut_gpio);
1030 int omap_bandgap_remove(struct platform_device *pdev)
1032 struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
1035 /* First thing is to remove sensor interfaces */
1036 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
1037 if (bg_ptr->conf->sensors[i].register_cooling)
1038 bg_ptr->conf->sensors[i].unregister_cooling(bg_ptr, i);
1040 if (bg_ptr->conf->remove_sensor)
1041 bg_ptr->conf->remove_sensor(bg_ptr, i);
1044 omap_bandgap_power(bg_ptr, false);
1046 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
1047 clk_disable_unprepare(bg_ptr->fclock);
1048 clk_put(bg_ptr->fclock);
1049 clk_put(bg_ptr->div_clk);
1051 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT))
1052 free_irq(bg_ptr->irq, bg_ptr);
1054 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT)) {
1055 free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
1056 gpio_free(bg_ptr->tshut_gpio);
1063 static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
1067 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
1068 struct temp_sensor_registers *tsr;
1069 struct temp_sensor_regval *rval;
1071 rval = &bg_ptr->conf->sensors[i].regval;
1072 tsr = bg_ptr->conf->sensors[i].registers;
1074 if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
1075 rval->bg_mode_ctrl = omap_bandgap_readl(bg_ptr,
1076 tsr->bgap_mode_ctrl);
1077 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
1078 rval->bg_counter = omap_bandgap_readl(bg_ptr,
1080 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
1081 rval->bg_threshold = omap_bandgap_readl(bg_ptr,
1082 tsr->bgap_threshold);
1083 rval->bg_ctrl = omap_bandgap_readl(bg_ptr,
1084 tsr->bgap_mask_ctrl);
1087 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
1088 rval->tshut_threshold = omap_bandgap_readl(bg_ptr,
1089 tsr->tshut_threshold);
1095 static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
1099 for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
1100 struct temp_sensor_registers *tsr;
1101 struct temp_sensor_regval *rval;
1104 rval = &bg_ptr->conf->sensors[i].regval;
1105 tsr = bg_ptr->conf->sensors[i].registers;
1107 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
1108 val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
1110 if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
1111 omap_bandgap_writel(bg_ptr, rval->tshut_threshold,
1112 tsr->tshut_threshold);
1113 /* Force immediate temperature measurement and update
1114 * of the DTEMP field
1116 omap_bandgap_force_single_read(bg_ptr, i);
1118 if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
1119 omap_bandgap_writel(bg_ptr, rval->bg_counter,
1121 if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
1122 omap_bandgap_writel(bg_ptr, rval->bg_mode_ctrl,
1123 tsr->bgap_mode_ctrl);
1124 if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
1125 omap_bandgap_writel(bg_ptr, rval->bg_threshold,
1126 tsr->bgap_threshold);
1127 omap_bandgap_writel(bg_ptr, rval->bg_ctrl,
1128 tsr->bgap_mask_ctrl);
1135 static int omap_bandgap_suspend(struct device *dev)
1137 struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
1140 err = omap_bandgap_save_ctxt(bg_ptr);
1141 omap_bandgap_power(bg_ptr, false);
1143 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
1144 clk_disable_unprepare(bg_ptr->fclock);
1149 static int omap_bandgap_resume(struct device *dev)
1151 struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
1153 if (OMAP_BANDGAP_HAS(bg_ptr, CLK_CTRL))
1154 clk_prepare_enable(bg_ptr->fclock);
1156 omap_bandgap_power(bg_ptr, true);
1158 return omap_bandgap_restore_ctxt(bg_ptr);
1160 static const struct dev_pm_ops omap_bandgap_dev_pm_ops = {
1161 SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend,
1162 omap_bandgap_resume)
1165 #define DEV_PM_OPS (&omap_bandgap_dev_pm_ops)
1167 #define DEV_PM_OPS NULL
1170 static const struct of_device_id of_omap_bandgap_match[] = {
1171 #ifdef CONFIG_OMAP4_THERMAL
1173 .compatible = "ti,omap4430-bandgap",
1174 .data = (void *)&omap4430_data,
1177 .compatible = "ti,omap4460-bandgap",
1178 .data = (void *)&omap4460_data,
1181 .compatible = "ti,omap4470-bandgap",
1182 .data = (void *)&omap4470_data,
1185 #ifdef CONFIG_OMAP5_THERMAL
1187 .compatible = "ti,omap5430-bandgap",
1188 .data = (void *)&omap5430_data,
1194 MODULE_DEVICE_TABLE(of, of_omap_bandgap_match);
1196 static struct platform_driver omap_bandgap_sensor_driver = {
1197 .probe = omap_bandgap_probe,
1198 .remove = omap_bandgap_remove,
1200 .name = "omap-bandgap",
1202 .of_match_table = of_omap_bandgap_match,
1206 module_platform_driver(omap_bandgap_sensor_driver);
1208 MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
1209 MODULE_LICENSE("GPL v2");
1210 MODULE_ALIAS("platform:omap-bandgap");
1211 MODULE_AUTHOR("Texas Instrument Inc.");