6fd776f41ebccd0a40710c798dbb03d9fd6eadd7
[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;
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         /* Count trigger levels to be enabled */
148         for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
149                 if (pdata->trigger_levels[i])
150                         trigger_levs++;
151
152         if (data->soc == SOC_ARCH_EXYNOS4210) {
153                 /* Write temperature code for threshold */
154                 threshold_code = temp_to_code(data, pdata->threshold);
155                 if (threshold_code < 0) {
156                         ret = threshold_code;
157                         goto out;
158                 }
159                 writeb(threshold_code,
160                         data->base + reg->threshold_temp);
161                 for (i = 0; i < trigger_levs; i++)
162                         writeb(pdata->trigger_levels[i], data->base +
163                         reg->threshold_th0 + i * sizeof(reg->threshold_th0));
164
165                 writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
166         } else if (data->soc == SOC_ARCH_EXYNOS) {
167                 /* Write temperature code for rising and falling threshold */
168                 for (i = 0; i < trigger_levs; i++) {
169                         threshold_code = temp_to_code(data,
170                                                 pdata->trigger_levels[i]);
171                         if (threshold_code < 0) {
172                                 ret = threshold_code;
173                                 goto out;
174                         }
175                         rising_threshold |= threshold_code << 8 * i;
176                         if (pdata->threshold_falling) {
177                                 threshold_code = temp_to_code(data,
178                                                 pdata->trigger_levels[i] -
179                                                 pdata->threshold_falling);
180                                 if (threshold_code > 0)
181                                         falling_threshold |=
182                                                 threshold_code << 8 * i;
183                         }
184                 }
185
186                 writel(rising_threshold,
187                                 data->base + reg->threshold_th0);
188                 writel(falling_threshold,
189                                 data->base + reg->threshold_th1);
190
191                 writel((reg->inten_rise_mask << reg->inten_rise_shift) |
192                         (reg->inten_fall_mask << reg->inten_fall_shift),
193                                 data->base + reg->tmu_intclear);
194         }
195 out:
196         clk_disable(data->clk);
197         mutex_unlock(&data->lock);
198
199         return ret;
200 }
201
202 static void exynos_tmu_control(struct platform_device *pdev, bool on)
203 {
204         struct exynos_tmu_data *data = platform_get_drvdata(pdev);
205         struct exynos_tmu_platform_data *pdata = data->pdata;
206         const struct exynos_tmu_registers *reg = pdata->registers;
207         unsigned int con, interrupt_en;
208
209         mutex_lock(&data->lock);
210         clk_enable(data->clk);
211
212         con = readl(data->base + reg->tmu_ctrl);
213
214         if (pdata->reference_voltage) {
215                 con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
216                 con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
217         }
218
219         if (pdata->gain) {
220                 con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
221                 con |= (pdata->gain << reg->buf_slope_sel_shift);
222         }
223
224         if (pdata->noise_cancel_mode) {
225                 con &= ~(reg->therm_trip_mode_mask <<
226                                         reg->therm_trip_mode_shift);
227                 con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
228         }
229
230         if (on) {
231                 con |= (1 << reg->core_en_shift);
232                 interrupt_en =
233                         pdata->trigger_enable[3] << reg->inten_rise3_shift |
234                         pdata->trigger_enable[2] << reg->inten_rise2_shift |
235                         pdata->trigger_enable[1] << reg->inten_rise1_shift |
236                         pdata->trigger_enable[0] << reg->inten_rise0_shift;
237                 if (pdata->threshold_falling)
238                         interrupt_en |=
239                                 interrupt_en << reg->inten_fall0_shift;
240         } else {
241                 con &= ~(1 << reg->core_en_shift);
242                 interrupt_en = 0; /* Disable all interrupts */
243         }
244         writel(interrupt_en, data->base + reg->tmu_inten);
245         writel(con, data->base + reg->tmu_ctrl);
246
247         clk_disable(data->clk);
248         mutex_unlock(&data->lock);
249 }
250
251 static int exynos_tmu_read(struct exynos_tmu_data *data)
252 {
253         struct exynos_tmu_platform_data *pdata = data->pdata;
254         const struct exynos_tmu_registers *reg = pdata->registers;
255         u8 temp_code;
256         int temp;
257
258         mutex_lock(&data->lock);
259         clk_enable(data->clk);
260
261         temp_code = readb(data->base + reg->tmu_cur_temp);
262         temp = code_to_temp(data, temp_code);
263
264         clk_disable(data->clk);
265         mutex_unlock(&data->lock);
266
267         return temp;
268 }
269
270 #ifdef CONFIG_THERMAL_EMULATION
271 static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
272 {
273         struct exynos_tmu_data *data = drv_data;
274         struct exynos_tmu_platform_data *pdata = data->pdata;
275         const struct exynos_tmu_registers *reg = pdata->registers;
276         unsigned int val;
277         int ret = -EINVAL;
278
279         if (data->soc == SOC_ARCH_EXYNOS4210)
280                 goto out;
281
282         if (temp && temp < MCELSIUS)
283                 goto out;
284
285         mutex_lock(&data->lock);
286         clk_enable(data->clk);
287
288         val = readl(data->base + reg->emul_con);
289
290         if (temp) {
291                 temp /= MCELSIUS;
292
293                 val = (EXYNOS_EMUL_TIME << reg->emul_time_shift) |
294                         (temp_to_code(data, temp)
295                          << reg->emul_temp_shift) | EXYNOS_EMUL_ENABLE;
296         } else {
297                 val &= ~EXYNOS_EMUL_ENABLE;
298         }
299
300         writel(val, data->base + reg->emul_con);
301
302         clk_disable(data->clk);
303         mutex_unlock(&data->lock);
304         return 0;
305 out:
306         return ret;
307 }
308 #else
309 static int exynos_tmu_set_emulation(void *drv_data,     unsigned long temp)
310         { return -EINVAL; }
311 #endif/*CONFIG_THERMAL_EMULATION*/
312
313 static void exynos_tmu_work(struct work_struct *work)
314 {
315         struct exynos_tmu_data *data = container_of(work,
316                         struct exynos_tmu_data, irq_work);
317         struct exynos_tmu_platform_data *pdata = data->pdata;
318         const struct exynos_tmu_registers *reg = pdata->registers;
319
320         exynos_report_trigger();
321         mutex_lock(&data->lock);
322         clk_enable(data->clk);
323
324         if (data->soc == SOC_ARCH_EXYNOS)
325                 writel((reg->inten_rise_mask << reg->inten_rise_shift) |
326                         (reg->inten_fall_mask << reg->inten_fall_shift),
327                                 data->base + reg->tmu_intclear);
328         else
329                 writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
330
331         clk_disable(data->clk);
332         mutex_unlock(&data->lock);
333
334         enable_irq(data->irq);
335 }
336
337 static irqreturn_t exynos_tmu_irq(int irq, void *id)
338 {
339         struct exynos_tmu_data *data = id;
340
341         disable_irq_nosync(irq);
342         schedule_work(&data->irq_work);
343
344         return IRQ_HANDLED;
345 }
346 static struct thermal_sensor_conf exynos_sensor_conf = {
347         .name                   = "exynos-therm",
348         .read_temperature       = (int (*)(void *))exynos_tmu_read,
349         .write_emul_temp        = exynos_tmu_set_emulation,
350 };
351
352 #ifdef CONFIG_OF
353 static const struct of_device_id exynos_tmu_match[] = {
354         {
355                 .compatible = "samsung,exynos4210-tmu",
356                 .data = (void *)EXYNOS4210_TMU_DRV_DATA,
357         },
358         {
359                 .compatible = "samsung,exynos4412-tmu",
360                 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
361         },
362         {
363                 .compatible = "samsung,exynos5250-tmu",
364                 .data = (void *)EXYNOS5250_TMU_DRV_DATA,
365         },
366         {},
367 };
368 MODULE_DEVICE_TABLE(of, exynos_tmu_match);
369 #endif
370
371 static struct platform_device_id exynos_tmu_driver_ids[] = {
372         {
373                 .name           = "exynos4210-tmu",
374                 .driver_data    = (kernel_ulong_t)EXYNOS4210_TMU_DRV_DATA,
375         },
376         {
377                 .name           = "exynos5250-tmu",
378                 .driver_data    = (kernel_ulong_t)EXYNOS5250_TMU_DRV_DATA,
379         },
380         { },
381 };
382 MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
383
384 static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
385                         struct platform_device *pdev)
386 {
387 #ifdef CONFIG_OF
388         if (pdev->dev.of_node) {
389                 const struct of_device_id *match;
390                 match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
391                 if (!match)
392                         return NULL;
393                 return (struct exynos_tmu_platform_data *) match->data;
394         }
395 #endif
396         return (struct exynos_tmu_platform_data *)
397                         platform_get_device_id(pdev)->driver_data;
398 }
399
400 static int exynos_tmu_probe(struct platform_device *pdev)
401 {
402         struct exynos_tmu_data *data;
403         struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
404         int ret, i;
405
406         if (!pdata)
407                 pdata = exynos_get_driver_data(pdev);
408
409         if (!pdata) {
410                 dev_err(&pdev->dev, "No platform init data supplied.\n");
411                 return -ENODEV;
412         }
413         data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
414                                         GFP_KERNEL);
415         if (!data) {
416                 dev_err(&pdev->dev, "Failed to allocate driver structure\n");
417                 return -ENOMEM;
418         }
419
420         data->irq = platform_get_irq(pdev, 0);
421         if (data->irq < 0) {
422                 dev_err(&pdev->dev, "Failed to get platform irq\n");
423                 return data->irq;
424         }
425
426         INIT_WORK(&data->irq_work, exynos_tmu_work);
427
428         data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
429         data->base = devm_ioremap_resource(&pdev->dev, data->mem);
430         if (IS_ERR(data->base))
431                 return PTR_ERR(data->base);
432
433         ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
434                 IRQF_TRIGGER_RISING, "exynos-tmu", data);
435         if (ret) {
436                 dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
437                 return ret;
438         }
439
440         data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
441         if (IS_ERR(data->clk)) {
442                 dev_err(&pdev->dev, "Failed to get clock\n");
443                 return  PTR_ERR(data->clk);
444         }
445
446         ret = clk_prepare(data->clk);
447         if (ret)
448                 return ret;
449
450         if (pdata->type == SOC_ARCH_EXYNOS ||
451                                 pdata->type == SOC_ARCH_EXYNOS4210)
452                 data->soc = pdata->type;
453         else {
454                 ret = -EINVAL;
455                 dev_err(&pdev->dev, "Platform not supported\n");
456                 goto err_clk;
457         }
458
459         data->pdata = pdata;
460         platform_set_drvdata(pdev, data);
461         mutex_init(&data->lock);
462
463         ret = exynos_tmu_initialize(pdev);
464         if (ret) {
465                 dev_err(&pdev->dev, "Failed to initialize TMU\n");
466                 goto err_clk;
467         }
468
469         exynos_tmu_control(pdev, true);
470
471         /* Register the sensor with thermal management interface */
472         (&exynos_sensor_conf)->private_data = data;
473         exynos_sensor_conf.trip_data.trip_count = pdata->trigger_enable[0] +
474                         pdata->trigger_enable[1] + pdata->trigger_enable[2]+
475                         pdata->trigger_enable[3];
476
477         for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
478                 exynos_sensor_conf.trip_data.trip_val[i] =
479                         pdata->threshold + pdata->trigger_levels[i];
480
481         exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
482
483         exynos_sensor_conf.cooling_data.freq_clip_count =
484                                                 pdata->freq_tab_count;
485         for (i = 0; i < pdata->freq_tab_count; i++) {
486                 exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
487                                         pdata->freq_tab[i].freq_clip_max;
488                 exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
489                                         pdata->freq_tab[i].temp_level;
490         }
491
492         ret = exynos_register_thermal(&exynos_sensor_conf);
493         if (ret) {
494                 dev_err(&pdev->dev, "Failed to register thermal interface\n");
495                 goto err_clk;
496         }
497
498         return 0;
499 err_clk:
500         clk_unprepare(data->clk);
501         return ret;
502 }
503
504 static int exynos_tmu_remove(struct platform_device *pdev)
505 {
506         struct exynos_tmu_data *data = platform_get_drvdata(pdev);
507
508         exynos_tmu_control(pdev, false);
509
510         exynos_unregister_thermal();
511
512         clk_unprepare(data->clk);
513
514         return 0;
515 }
516
517 #ifdef CONFIG_PM_SLEEP
518 static int exynos_tmu_suspend(struct device *dev)
519 {
520         exynos_tmu_control(to_platform_device(dev), false);
521
522         return 0;
523 }
524
525 static int exynos_tmu_resume(struct device *dev)
526 {
527         struct platform_device *pdev = to_platform_device(dev);
528
529         exynos_tmu_initialize(pdev);
530         exynos_tmu_control(pdev, true);
531
532         return 0;
533 }
534
535 static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
536                          exynos_tmu_suspend, exynos_tmu_resume);
537 #define EXYNOS_TMU_PM   (&exynos_tmu_pm)
538 #else
539 #define EXYNOS_TMU_PM   NULL
540 #endif
541
542 static struct platform_driver exynos_tmu_driver = {
543         .driver = {
544                 .name   = "exynos-tmu",
545                 .owner  = THIS_MODULE,
546                 .pm     = EXYNOS_TMU_PM,
547                 .of_match_table = of_match_ptr(exynos_tmu_match),
548         },
549         .probe = exynos_tmu_probe,
550         .remove = exynos_tmu_remove,
551         .id_table = exynos_tmu_driver_ids,
552 };
553
554 module_platform_driver(exynos_tmu_driver);
555
556 MODULE_DESCRIPTION("EXYNOS TMU Driver");
557 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
558 MODULE_LICENSE("GPL");
559 MODULE_ALIAS("platform:exynos-tmu");