thermal: exynos: Add support for instance based register/unregister
[firefly-linux-kernel-4.4.55.git] / drivers / thermal / samsung / exynos_tmu.c
1 /*
2  * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
3  *
4  *  Copyright (C) 2011 Samsung Electronics
5  *  Donggeun Kim <dg77.kim@samsung.com>
6  *  Amit Daniel Kachhap <amit.kachhap@linaro.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include <linux/clk.h>
25 #include <linux/io.h>
26 #include <linux/interrupt.h>
27 #include <linux/module.h>
28 #include <linux/of.h>
29 #include <linux/platform_device.h>
30
31 #include "exynos_thermal_common.h"
32 #include "exynos_tmu.h"
33 #include "exynos_tmu_data.h"
34
35 struct exynos_tmu_data {
36         struct exynos_tmu_platform_data *pdata;
37         struct resource *mem;
38         void __iomem *base;
39         int irq;
40         enum soc_type soc;
41         struct work_struct irq_work;
42         struct mutex lock;
43         struct clk *clk;
44         u8 temp_error1, temp_error2;
45 };
46
47 /*
48  * TMU treats temperature as a mapped temperature code.
49  * The temperature is converted differently depending on the calibration type.
50  */
51 static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
52 {
53         struct exynos_tmu_platform_data *pdata = data->pdata;
54         int temp_code;
55
56         if (data->soc == SOC_ARCH_EXYNOS4210)
57                 /* temp should range between 25 and 125 */
58                 if (temp < 25 || temp > 125) {
59                         temp_code = -EINVAL;
60                         goto out;
61                 }
62
63         switch (pdata->cal_type) {
64         case TYPE_TWO_POINT_TRIMMING:
65                 temp_code = (temp - pdata->first_point_trim) *
66                         (data->temp_error2 - data->temp_error1) /
67                         (pdata->second_point_trim - pdata->first_point_trim) +
68                         data->temp_error1;
69                 break;
70         case TYPE_ONE_POINT_TRIMMING:
71                 temp_code = temp + data->temp_error1 - pdata->first_point_trim;
72                 break;
73         default:
74                 temp_code = temp + pdata->default_temp_offset;
75                 break;
76         }
77 out:
78         return temp_code;
79 }
80
81 /*
82  * Calculate a temperature value from a temperature code.
83  * The unit of the temperature is degree Celsius.
84  */
85 static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
86 {
87         struct exynos_tmu_platform_data *pdata = data->pdata;
88         int temp;
89
90         if (data->soc == SOC_ARCH_EXYNOS4210)
91                 /* temp_code should range between 75 and 175 */
92                 if (temp_code < 75 || temp_code > 175) {
93                         temp = -ENODATA;
94                         goto out;
95                 }
96
97         switch (pdata->cal_type) {
98         case TYPE_TWO_POINT_TRIMMING:
99                 temp = (temp_code - data->temp_error1) *
100                         (pdata->second_point_trim - pdata->first_point_trim) /
101                         (data->temp_error2 - data->temp_error1) +
102                         pdata->first_point_trim;
103                 break;
104         case TYPE_ONE_POINT_TRIMMING:
105                 temp = temp_code - data->temp_error1 + pdata->first_point_trim;
106                 break;
107         default:
108                 temp = temp_code - pdata->default_temp_offset;
109                 break;
110         }
111 out:
112         return temp;
113 }
114
115 static int exynos_tmu_initialize(struct platform_device *pdev)
116 {
117         struct exynos_tmu_data *data = platform_get_drvdata(pdev);
118         struct exynos_tmu_platform_data *pdata = data->pdata;
119         const struct exynos_tmu_registers *reg = pdata->registers;
120         unsigned int status, trim_info = 0, con;
121         unsigned int rising_threshold = 0, falling_threshold = 0;
122         int ret = 0, threshold_code, i, trigger_levs = 0;
123
124         mutex_lock(&data->lock);
125         clk_enable(data->clk);
126
127         status = readb(data->base + reg->tmu_status);
128         if (!status) {
129                 ret = -EBUSY;
130                 goto out;
131         }
132
133         if (data->soc == SOC_ARCH_EXYNOS)
134                 __raw_writel(1, data->base + reg->triminfo_ctrl);
135
136         /* Save trimming info in order to perform calibration */
137         trim_info = readl(data->base + reg->triminfo_data);
138         data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
139         data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
140                                 EXYNOS_TMU_TEMP_MASK);
141
142         if ((pdata->min_efuse_value > data->temp_error1) ||
143                         (data->temp_error1 > pdata->max_efuse_value) ||
144                         (data->temp_error2 != 0))
145                 data->temp_error1 = pdata->efuse_value;
146
147         if (pdata->max_trigger_level > MAX_THRESHOLD_LEVS) {
148                 dev_err(&pdev->dev, "Invalid max trigger level\n");
149                 goto out;
150         }
151
152         for (i = 0; i < pdata->max_trigger_level; i++) {
153                 if (!pdata->trigger_levels[i])
154                         continue;
155
156                 if ((pdata->trigger_type[i] == HW_TRIP) &&
157                 (!pdata->trigger_levels[pdata->max_trigger_level - 1])) {
158                         dev_err(&pdev->dev, "Invalid hw trigger level\n");
159                         ret = -EINVAL;
160                         goto out;
161                 }
162
163                 /* Count trigger levels except the HW trip*/
164                 if (!(pdata->trigger_type[i] == HW_TRIP))
165                         trigger_levs++;
166         }
167
168         if (data->soc == SOC_ARCH_EXYNOS4210) {
169                 /* Write temperature code for threshold */
170                 threshold_code = temp_to_code(data, pdata->threshold);
171                 if (threshold_code < 0) {
172                         ret = threshold_code;
173                         goto out;
174                 }
175                 writeb(threshold_code,
176                         data->base + reg->threshold_temp);
177                 for (i = 0; i < trigger_levs; i++)
178                         writeb(pdata->trigger_levels[i], data->base +
179                         reg->threshold_th0 + i * sizeof(reg->threshold_th0));
180
181                 writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
182         } else if (data->soc == SOC_ARCH_EXYNOS) {
183                 /* Write temperature code for rising and falling threshold */
184                 for (i = 0;
185                 i < trigger_levs && i < EXYNOS_MAX_TRIGGER_PER_REG; i++) {
186                         threshold_code = temp_to_code(data,
187                                                 pdata->trigger_levels[i]);
188                         if (threshold_code < 0) {
189                                 ret = threshold_code;
190                                 goto out;
191                         }
192                         rising_threshold |= threshold_code << 8 * i;
193                         if (pdata->threshold_falling) {
194                                 threshold_code = temp_to_code(data,
195                                                 pdata->trigger_levels[i] -
196                                                 pdata->threshold_falling);
197                                 if (threshold_code > 0)
198                                         falling_threshold |=
199                                                 threshold_code << 8 * i;
200                         }
201                 }
202
203                 writel(rising_threshold,
204                                 data->base + reg->threshold_th0);
205                 writel(falling_threshold,
206                                 data->base + reg->threshold_th1);
207
208                 writel((reg->inten_rise_mask << reg->inten_rise_shift) |
209                         (reg->inten_fall_mask << reg->inten_fall_shift),
210                                 data->base + reg->tmu_intclear);
211
212                 /* if last threshold limit is also present */
213                 i = pdata->max_trigger_level - 1;
214                 if (pdata->trigger_levels[i] &&
215                                 (pdata->trigger_type[i] == HW_TRIP)) {
216                         threshold_code = temp_to_code(data,
217                                                 pdata->trigger_levels[i]);
218                         if (threshold_code < 0) {
219                                 ret = threshold_code;
220                                 goto out;
221                         }
222                         rising_threshold |= threshold_code << 8 * i;
223                         writel(rising_threshold,
224                                 data->base + reg->threshold_th0);
225                         con = readl(data->base + reg->tmu_ctrl);
226                         con |= (1 << reg->therm_trip_en_shift);
227                         writel(con, data->base + reg->tmu_ctrl);
228                 }
229         }
230 out:
231         clk_disable(data->clk);
232         mutex_unlock(&data->lock);
233
234         return ret;
235 }
236
237 static void exynos_tmu_control(struct platform_device *pdev, bool on)
238 {
239         struct exynos_tmu_data *data = platform_get_drvdata(pdev);
240         struct exynos_tmu_platform_data *pdata = data->pdata;
241         const struct exynos_tmu_registers *reg = pdata->registers;
242         unsigned int con, interrupt_en;
243
244         mutex_lock(&data->lock);
245         clk_enable(data->clk);
246
247         con = readl(data->base + reg->tmu_ctrl);
248
249         if (pdata->reference_voltage) {
250                 con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
251                 con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
252         }
253
254         if (pdata->gain) {
255                 con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
256                 con |= (pdata->gain << reg->buf_slope_sel_shift);
257         }
258
259         if (pdata->noise_cancel_mode) {
260                 con &= ~(reg->therm_trip_mode_mask <<
261                                         reg->therm_trip_mode_shift);
262                 con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
263         }
264
265         if (on) {
266                 con |= (1 << reg->core_en_shift);
267                 interrupt_en =
268                         pdata->trigger_enable[3] << reg->inten_rise3_shift |
269                         pdata->trigger_enable[2] << reg->inten_rise2_shift |
270                         pdata->trigger_enable[1] << reg->inten_rise1_shift |
271                         pdata->trigger_enable[0] << reg->inten_rise0_shift;
272                 if (pdata->threshold_falling)
273                         interrupt_en |=
274                                 interrupt_en << reg->inten_fall0_shift;
275         } else {
276                 con &= ~(1 << reg->core_en_shift);
277                 interrupt_en = 0; /* Disable all interrupts */
278         }
279         writel(interrupt_en, data->base + reg->tmu_inten);
280         writel(con, data->base + reg->tmu_ctrl);
281
282         clk_disable(data->clk);
283         mutex_unlock(&data->lock);
284 }
285
286 static int exynos_tmu_read(struct exynos_tmu_data *data)
287 {
288         struct exynos_tmu_platform_data *pdata = data->pdata;
289         const struct exynos_tmu_registers *reg = pdata->registers;
290         u8 temp_code;
291         int temp;
292
293         mutex_lock(&data->lock);
294         clk_enable(data->clk);
295
296         temp_code = readb(data->base + reg->tmu_cur_temp);
297         temp = code_to_temp(data, temp_code);
298
299         clk_disable(data->clk);
300         mutex_unlock(&data->lock);
301
302         return temp;
303 }
304
305 #ifdef CONFIG_THERMAL_EMULATION
306 static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
307 {
308         struct exynos_tmu_data *data = drv_data;
309         struct exynos_tmu_platform_data *pdata = data->pdata;
310         const struct exynos_tmu_registers *reg = pdata->registers;
311         unsigned int val;
312         int ret = -EINVAL;
313
314         if (data->soc == SOC_ARCH_EXYNOS4210)
315                 goto out;
316
317         if (temp && temp < MCELSIUS)
318                 goto out;
319
320         mutex_lock(&data->lock);
321         clk_enable(data->clk);
322
323         val = readl(data->base + reg->emul_con);
324
325         if (temp) {
326                 temp /= MCELSIUS;
327
328                 val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
329                         (temp_to_code(data, temp)
330                          << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
331         } else {
332                 val &= ~EXYNOS_EMUL_ENABLE;
333         }
334
335         writel(val, data->base + reg->emul_con);
336
337         clk_disable(data->clk);
338         mutex_unlock(&data->lock);
339         return 0;
340 out:
341         return ret;
342 }
343 #else
344 static int exynos_tmu_set_emulation(void *drv_data,     unsigned long temp)
345         { return -EINVAL; }
346 #endif/*CONFIG_THERMAL_EMULATION*/
347
348 static struct thermal_sensor_conf exynos_sensor_conf = {
349         .name                   = "exynos-therm",
350         .read_temperature       = (int (*)(void *))exynos_tmu_read,
351         .write_emul_temp        = exynos_tmu_set_emulation,
352 };
353
354 static void exynos_tmu_work(struct work_struct *work)
355 {
356         struct exynos_tmu_data *data = container_of(work,
357                         struct exynos_tmu_data, irq_work);
358         struct exynos_tmu_platform_data *pdata = data->pdata;
359         const struct exynos_tmu_registers *reg = pdata->registers;
360         unsigned int val_irq;
361
362         exynos_report_trigger(&exynos_sensor_conf);
363         mutex_lock(&data->lock);
364         clk_enable(data->clk);
365
366         /* TODO: take action based on particular interrupt */
367         val_irq = readl(data->base + reg->tmu_intstat);
368         /* clear the interrupts */
369         writel(val_irq, data->base + reg->tmu_intclear);
370
371         clk_disable(data->clk);
372         mutex_unlock(&data->lock);
373
374         enable_irq(data->irq);
375 }
376
377 static irqreturn_t exynos_tmu_irq(int irq, void *id)
378 {
379         struct exynos_tmu_data *data = id;
380
381         disable_irq_nosync(irq);
382         schedule_work(&data->irq_work);
383
384         return IRQ_HANDLED;
385 }
386
387 #ifdef CONFIG_OF
388 static const struct of_device_id exynos_tmu_match[] = {
389         {
390                 .compatible = "samsung,exynos4210-tmu",
391                 .data = (void *)EXYNOS4210_TMU_DRV_DATA,
392         },
393         {
394                 .compatible = "samsung,exynos4412-tmu",
395                 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
396         },
397         {
398                 .compatible = "samsung,exynos5250-tmu",
399                 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
400         },
401         {},
402 };
403 MODULE_DEVICE_TABLE(of, exynos_tmu_match);
404 #endif
405
406 static struct platform_device_id exynos_tmu_driver_ids[] = {
407         {
408                 .name           = "exynos4210-tmu",
409                 .driver_data    = (kernel_ulong_t)EXYNOS4210_TMU_DRV_DATA,
410         },
411         {
412                 .name           = "exynos5250-tmu",
413                 .driver_data    = (kernel_ulong_t)EXYNOS5250_TMU_DRV_DATA,
414         },
415         { },
416 };
417 MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
418
419 static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
420                         struct platform_device *pdev)
421 {
422 #ifdef CONFIG_OF
423         if (pdev->dev.of_node) {
424                 const struct of_device_id *match;
425                 match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
426                 if (!match)
427                         return NULL;
428                 return (struct exynos_tmu_platform_data *) match->data;
429         }
430 #endif
431         return (struct exynos_tmu_platform_data *)
432                         platform_get_device_id(pdev)->driver_data;
433 }
434
435 static int exynos_tmu_probe(struct platform_device *pdev)
436 {
437         struct exynos_tmu_data *data;
438         struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
439         int ret, i;
440
441         if (!pdata)
442                 pdata = exynos_get_driver_data(pdev);
443
444         if (!pdata) {
445                 dev_err(&pdev->dev, "No platform init data supplied.\n");
446                 return -ENODEV;
447         }
448         data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
449                                         GFP_KERNEL);
450         if (!data) {
451                 dev_err(&pdev->dev, "Failed to allocate driver structure\n");
452                 return -ENOMEM;
453         }
454
455         data->irq = platform_get_irq(pdev, 0);
456         if (data->irq < 0) {
457                 dev_err(&pdev->dev, "Failed to get platform irq\n");
458                 return data->irq;
459         }
460
461         INIT_WORK(&data->irq_work, exynos_tmu_work);
462
463         data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
464         data->base = devm_ioremap_resource(&pdev->dev, data->mem);
465         if (IS_ERR(data->base))
466                 return PTR_ERR(data->base);
467
468         ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
469                 IRQF_TRIGGER_RISING, "exynos-tmu", data);
470         if (ret) {
471                 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
472                 return ret;
473         }
474
475         data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
476         if (IS_ERR(data->clk)) {
477                 dev_err(&pdev->dev, "Failed to get clock\n");
478                 return  PTR_ERR(data->clk);
479         }
480
481         ret = clk_prepare(data->clk);
482         if (ret)
483                 return ret;
484
485         if (pdata->type == SOC_ARCH_EXYNOS ||
486                                 pdata->type == SOC_ARCH_EXYNOS4210)
487                 data->soc = pdata->type;
488         else {
489                 ret = -EINVAL;
490                 dev_err(&pdev->dev, "Platform not supported\n");
491                 goto err_clk;
492         }
493
494         data->pdata = pdata;
495         platform_set_drvdata(pdev, data);
496         mutex_init(&data->lock);
497
498         ret = exynos_tmu_initialize(pdev);
499         if (ret) {
500                 dev_err(&pdev->dev, "Failed to initialize TMU\n");
501                 goto err_clk;
502         }
503
504         exynos_tmu_control(pdev, true);
505
506         /* Register the sensor with thermal management interface */
507         (&exynos_sensor_conf)->private_data = data;
508         exynos_sensor_conf.trip_data.trip_count = pdata->trigger_enable[0] +
509                         pdata->trigger_enable[1] + pdata->trigger_enable[2]+
510                         pdata->trigger_enable[3];
511
512         for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
513                 exynos_sensor_conf.trip_data.trip_val[i] =
514                         pdata->threshold + pdata->trigger_levels[i];
515
516         exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
517
518         exynos_sensor_conf.cooling_data.freq_clip_count =
519                                                 pdata->freq_tab_count;
520         for (i = 0; i < pdata->freq_tab_count; i++) {
521                 exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
522                                         pdata->freq_tab[i].freq_clip_max;
523                 exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
524                                         pdata->freq_tab[i].temp_level;
525         }
526
527         ret = exynos_register_thermal(&exynos_sensor_conf);
528         if (ret) {
529                 dev_err(&pdev->dev, "Failed to register thermal interface\n");
530                 goto err_clk;
531         }
532
533         return 0;
534 err_clk:
535         clk_unprepare(data->clk);
536         return ret;
537 }
538
539 static int exynos_tmu_remove(struct platform_device *pdev)
540 {
541         struct exynos_tmu_data *data = platform_get_drvdata(pdev);
542
543         exynos_tmu_control(pdev, false);
544
545         exynos_unregister_thermal(&exynos_sensor_conf);
546
547         clk_unprepare(data->clk);
548
549         return 0;
550 }
551
552 #ifdef CONFIG_PM_SLEEP
553 static int exynos_tmu_suspend(struct device *dev)
554 {
555         exynos_tmu_control(to_platform_device(dev), false);
556
557         return 0;
558 }
559
560 static int exynos_tmu_resume(struct device *dev)
561 {
562         struct platform_device *pdev = to_platform_device(dev);
563
564         exynos_tmu_initialize(pdev);
565         exynos_tmu_control(pdev, true);
566
567         return 0;
568 }
569
570 static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
571                          exynos_tmu_suspend, exynos_tmu_resume);
572 #define EXYNOS_TMU_PM   (&exynos_tmu_pm)
573 #else
574 #define EXYNOS_TMU_PM   NULL
575 #endif
576
577 static struct platform_driver exynos_tmu_driver = {
578         .driver = {
579                 .name   = "exynos-tmu",
580                 .owner  = THIS_MODULE,
581                 .pm     = EXYNOS_TMU_PM,
582                 .of_match_table = of_match_ptr(exynos_tmu_match),
583         },
584         .probe = exynos_tmu_probe,
585         .remove = exynos_tmu_remove,
586         .id_table = exynos_tmu_driver_ids,
587 };
588
589 module_platform_driver(exynos_tmu_driver);
590
591 MODULE_DESCRIPTION("EXYNOS TMU Driver");
592 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
593 MODULE_LICENSE("GPL");
594 MODULE_ALIAS("platform:exynos-tmu");