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