Root/drivers/thermal/exynos_thermal.c

1/*
2 * exynos_thermal.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/module.h>
25#include <linux/err.h>
26#include <linux/kernel.h>
27#include <linux/slab.h>
28#include <linux/platform_device.h>
29#include <linux/interrupt.h>
30#include <linux/clk.h>
31#include <linux/workqueue.h>
32#include <linux/sysfs.h>
33#include <linux/kobject.h>
34#include <linux/io.h>
35#include <linux/mutex.h>
36#include <linux/platform_data/exynos_thermal.h>
37#include <linux/thermal.h>
38#include <linux/cpufreq.h>
39#include <linux/cpu_cooling.h>
40#include <linux/of.h>
41
42#include <plat/cpu.h>
43
44/* Exynos generic registers */
45#define EXYNOS_TMU_REG_TRIMINFO 0x0
46#define EXYNOS_TMU_REG_CONTROL 0x20
47#define EXYNOS_TMU_REG_STATUS 0x28
48#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
49#define EXYNOS_TMU_REG_INTEN 0x70
50#define EXYNOS_TMU_REG_INTSTAT 0x74
51#define EXYNOS_TMU_REG_INTCLEAR 0x78
52
53#define EXYNOS_TMU_TRIM_TEMP_MASK 0xff
54#define EXYNOS_TMU_GAIN_SHIFT 8
55#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
56#define EXYNOS_TMU_CORE_ON 3
57#define EXYNOS_TMU_CORE_OFF 2
58#define EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET 50
59
60/* Exynos4210 specific registers */
61#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
62#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
63#define EXYNOS4210_TMU_REG_TRIG_LEVEL1 0x54
64#define EXYNOS4210_TMU_REG_TRIG_LEVEL2 0x58
65#define EXYNOS4210_TMU_REG_TRIG_LEVEL3 0x5C
66#define EXYNOS4210_TMU_REG_PAST_TEMP0 0x60
67#define EXYNOS4210_TMU_REG_PAST_TEMP1 0x64
68#define EXYNOS4210_TMU_REG_PAST_TEMP2 0x68
69#define EXYNOS4210_TMU_REG_PAST_TEMP3 0x6C
70
71#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK 0x1
72#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK 0x10
73#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK 0x100
74#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK 0x1000
75#define EXYNOS4210_TMU_INTCLEAR_VAL 0x1111
76
77/* Exynos5250 and Exynos4412 specific registers */
78#define EXYNOS_TMU_TRIMINFO_CON 0x14
79#define EXYNOS_THD_TEMP_RISE 0x50
80#define EXYNOS_THD_TEMP_FALL 0x54
81#define EXYNOS_EMUL_CON 0x80
82
83#define EXYNOS_TRIMINFO_RELOAD 0x1
84#define EXYNOS_TMU_CLEAR_RISE_INT 0x111
85#define EXYNOS_TMU_CLEAR_FALL_INT (0x111 << 12)
86#define EXYNOS_MUX_ADDR_VALUE 6
87#define EXYNOS_MUX_ADDR_SHIFT 20
88#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
89
90#define EFUSE_MIN_VALUE 40
91#define EFUSE_MAX_VALUE 100
92
93/* In-kernel thermal framework related macros & definations */
94#define SENSOR_NAME_LEN 16
95#define MAX_TRIP_COUNT 8
96#define MAX_COOLING_DEVICE 4
97#define MAX_THRESHOLD_LEVS 4
98
99#define ACTIVE_INTERVAL 500
100#define IDLE_INTERVAL 10000
101#define MCELSIUS 1000
102
103#ifdef CONFIG_EXYNOS_THERMAL_EMUL
104#define EXYNOS_EMUL_TIME 0x57F0
105#define EXYNOS_EMUL_TIME_SHIFT 16
106#define EXYNOS_EMUL_DATA_SHIFT 8
107#define EXYNOS_EMUL_DATA_MASK 0xFF
108#define EXYNOS_EMUL_ENABLE 0x1
109#endif /* CONFIG_EXYNOS_THERMAL_EMUL */
110
111/* CPU Zone information */
112#define PANIC_ZONE 4
113#define WARN_ZONE 3
114#define MONITOR_ZONE 2
115#define SAFE_ZONE 1
116
117#define GET_ZONE(trip) (trip + 2)
118#define GET_TRIP(zone) (zone - 2)
119
120#define EXYNOS_ZONE_COUNT 3
121
122struct exynos_tmu_data {
123    struct exynos_tmu_platform_data *pdata;
124    struct resource *mem;
125    void __iomem *base;
126    int irq;
127    enum soc_type soc;
128    struct work_struct irq_work;
129    struct mutex lock;
130    struct clk *clk;
131    u8 temp_error1, temp_error2;
132};
133
134struct thermal_trip_point_conf {
135    int trip_val[MAX_TRIP_COUNT];
136    int trip_count;
137    u8 trigger_falling;
138};
139
140struct thermal_cooling_conf {
141    struct freq_clip_table freq_data[MAX_TRIP_COUNT];
142    int freq_clip_count;
143};
144
145struct thermal_sensor_conf {
146    char name[SENSOR_NAME_LEN];
147    int (*read_temperature)(void *data);
148    struct thermal_trip_point_conf trip_data;
149    struct thermal_cooling_conf cooling_data;
150    void *private_data;
151};
152
153struct exynos_thermal_zone {
154    enum thermal_device_mode mode;
155    struct thermal_zone_device *therm_dev;
156    struct thermal_cooling_device *cool_dev[MAX_COOLING_DEVICE];
157    unsigned int cool_dev_size;
158    struct platform_device *exynos4_dev;
159    struct thermal_sensor_conf *sensor_conf;
160    bool bind;
161};
162
163static struct exynos_thermal_zone *th_zone;
164static void exynos_unregister_thermal(void);
165static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf);
166
167/* Get mode callback functions for thermal zone */
168static int exynos_get_mode(struct thermal_zone_device *thermal,
169            enum thermal_device_mode *mode)
170{
171    if (th_zone)
172        *mode = th_zone->mode;
173    return 0;
174}
175
176/* Set mode callback functions for thermal zone */
177static int exynos_set_mode(struct thermal_zone_device *thermal,
178            enum thermal_device_mode mode)
179{
180    if (!th_zone->therm_dev) {
181        pr_notice("thermal zone not registered\n");
182        return 0;
183    }
184
185    mutex_lock(&th_zone->therm_dev->lock);
186
187    if (mode == THERMAL_DEVICE_ENABLED &&
188        !th_zone->sensor_conf->trip_data.trigger_falling)
189        th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
190    else
191        th_zone->therm_dev->polling_delay = 0;
192
193    mutex_unlock(&th_zone->therm_dev->lock);
194
195    th_zone->mode = mode;
196    thermal_zone_device_update(th_zone->therm_dev);
197    pr_info("thermal polling set for duration=%d msec\n",
198                th_zone->therm_dev->polling_delay);
199    return 0;
200}
201
202
203/* Get trip type callback functions for thermal zone */
204static int exynos_get_trip_type(struct thermal_zone_device *thermal, int trip,
205                 enum thermal_trip_type *type)
206{
207    switch (GET_ZONE(trip)) {
208    case MONITOR_ZONE:
209    case WARN_ZONE:
210        *type = THERMAL_TRIP_ACTIVE;
211        break;
212    case PANIC_ZONE:
213        *type = THERMAL_TRIP_CRITICAL;
214        break;
215    default:
216        return -EINVAL;
217    }
218    return 0;
219}
220
221/* Get trip temperature callback functions for thermal zone */
222static int exynos_get_trip_temp(struct thermal_zone_device *thermal, int trip,
223                unsigned long *temp)
224{
225    if (trip < GET_TRIP(MONITOR_ZONE) || trip > GET_TRIP(PANIC_ZONE))
226        return -EINVAL;
227
228    *temp = th_zone->sensor_conf->trip_data.trip_val[trip];
229    /* convert the temperature into millicelsius */
230    *temp = *temp * MCELSIUS;
231
232    return 0;
233}
234
235/* Get critical temperature callback functions for thermal zone */
236static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
237                unsigned long *temp)
238{
239    int ret;
240    /* Panic zone */
241    ret = exynos_get_trip_temp(thermal, GET_TRIP(PANIC_ZONE), temp);
242    return ret;
243}
244
245static int exynos_get_frequency_level(unsigned int cpu, unsigned int freq)
246{
247    int i = 0, ret = -EINVAL;
248    struct cpufreq_frequency_table *table = NULL;
249#ifdef CONFIG_CPU_FREQ
250    table = cpufreq_frequency_get_table(cpu);
251#endif
252    if (!table)
253        return ret;
254
255    while (table[i].frequency != CPUFREQ_TABLE_END) {
256        if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
257            continue;
258        if (table[i].frequency == freq)
259            return i;
260        i++;
261    }
262    return ret;
263}
264
265/* Bind callback functions for thermal zone */
266static int exynos_bind(struct thermal_zone_device *thermal,
267            struct thermal_cooling_device *cdev)
268{
269    int ret = 0, i, tab_size, level;
270    struct freq_clip_table *tab_ptr, *clip_data;
271    struct thermal_sensor_conf *data = th_zone->sensor_conf;
272
273    tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
274    tab_size = data->cooling_data.freq_clip_count;
275
276    if (tab_ptr == NULL || tab_size == 0)
277        return -EINVAL;
278
279    /* find the cooling device registered*/
280    for (i = 0; i < th_zone->cool_dev_size; i++)
281        if (cdev == th_zone->cool_dev[i])
282            break;
283
284    /* No matching cooling device */
285    if (i == th_zone->cool_dev_size)
286        return 0;
287
288    /* Bind the thermal zone to the cpufreq cooling device */
289    for (i = 0; i < tab_size; i++) {
290        clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
291        level = exynos_get_frequency_level(0, clip_data->freq_clip_max);
292        if (level < 0)
293            return 0;
294        switch (GET_ZONE(i)) {
295        case MONITOR_ZONE:
296        case WARN_ZONE:
297            if (thermal_zone_bind_cooling_device(thermal, i, cdev,
298                                level, 0)) {
299                pr_err("error binding cdev inst %d\n", i);
300                ret = -EINVAL;
301            }
302            th_zone->bind = true;
303            break;
304        default:
305            ret = -EINVAL;
306        }
307    }
308
309    return ret;
310}
311
312/* Unbind callback functions for thermal zone */
313static int exynos_unbind(struct thermal_zone_device *thermal,
314            struct thermal_cooling_device *cdev)
315{
316    int ret = 0, i, tab_size;
317    struct thermal_sensor_conf *data = th_zone->sensor_conf;
318
319    if (th_zone->bind == false)
320        return 0;
321
322    tab_size = data->cooling_data.freq_clip_count;
323
324    if (tab_size == 0)
325        return -EINVAL;
326
327    /* find the cooling device registered*/
328    for (i = 0; i < th_zone->cool_dev_size; i++)
329        if (cdev == th_zone->cool_dev[i])
330            break;
331
332    /* No matching cooling device */
333    if (i == th_zone->cool_dev_size)
334        return 0;
335
336    /* Bind the thermal zone to the cpufreq cooling device */
337    for (i = 0; i < tab_size; i++) {
338        switch (GET_ZONE(i)) {
339        case MONITOR_ZONE:
340        case WARN_ZONE:
341            if (thermal_zone_unbind_cooling_device(thermal, i,
342                                cdev)) {
343                pr_err("error unbinding cdev inst=%d\n", i);
344                ret = -EINVAL;
345            }
346            th_zone->bind = false;
347            break;
348        default:
349            ret = -EINVAL;
350        }
351    }
352    return ret;
353}
354
355/* Get temperature callback functions for thermal zone */
356static int exynos_get_temp(struct thermal_zone_device *thermal,
357            unsigned long *temp)
358{
359    void *data;
360
361    if (!th_zone->sensor_conf) {
362        pr_info("Temperature sensor not initialised\n");
363        return -EINVAL;
364    }
365    data = th_zone->sensor_conf->private_data;
366    *temp = th_zone->sensor_conf->read_temperature(data);
367    /* convert the temperature into millicelsius */
368    *temp = *temp * MCELSIUS;
369    return 0;
370}
371
372/* Get the temperature trend */
373static int exynos_get_trend(struct thermal_zone_device *thermal,
374            int trip, enum thermal_trend *trend)
375{
376    int ret;
377    unsigned long trip_temp;
378
379    ret = exynos_get_trip_temp(thermal, trip, &trip_temp);
380    if (ret < 0)
381        return ret;
382
383    if (thermal->temperature >= trip_temp)
384        *trend = THERMAL_TREND_RAISE_FULL;
385    else
386        *trend = THERMAL_TREND_DROP_FULL;
387
388    return 0;
389}
390/* Operation callback functions for thermal zone */
391static struct thermal_zone_device_ops const exynos_dev_ops = {
392    .bind = exynos_bind,
393    .unbind = exynos_unbind,
394    .get_temp = exynos_get_temp,
395    .get_trend = exynos_get_trend,
396    .get_mode = exynos_get_mode,
397    .set_mode = exynos_set_mode,
398    .get_trip_type = exynos_get_trip_type,
399    .get_trip_temp = exynos_get_trip_temp,
400    .get_crit_temp = exynos_get_crit_temp,
401};
402
403/*
404 * This function may be called from interrupt based temperature sensor
405 * when threshold is changed.
406 */
407static void exynos_report_trigger(void)
408{
409    unsigned int i;
410    char data[10];
411    char *envp[] = { data, NULL };
412
413    if (!th_zone || !th_zone->therm_dev)
414        return;
415    if (th_zone->bind == false) {
416        for (i = 0; i < th_zone->cool_dev_size; i++) {
417            if (!th_zone->cool_dev[i])
418                continue;
419            exynos_bind(th_zone->therm_dev,
420                    th_zone->cool_dev[i]);
421        }
422    }
423
424    thermal_zone_device_update(th_zone->therm_dev);
425
426    mutex_lock(&th_zone->therm_dev->lock);
427    /* Find the level for which trip happened */
428    for (i = 0; i < th_zone->sensor_conf->trip_data.trip_count; i++) {
429        if (th_zone->therm_dev->last_temperature <
430            th_zone->sensor_conf->trip_data.trip_val[i] * MCELSIUS)
431            break;
432    }
433
434    if (th_zone->mode == THERMAL_DEVICE_ENABLED &&
435        !th_zone->sensor_conf->trip_data.trigger_falling) {
436        if (i > 0)
437            th_zone->therm_dev->polling_delay = ACTIVE_INTERVAL;
438        else
439            th_zone->therm_dev->polling_delay = IDLE_INTERVAL;
440    }
441
442    snprintf(data, sizeof(data), "%u", i);
443    kobject_uevent_env(&th_zone->therm_dev->device.kobj, KOBJ_CHANGE, envp);
444    mutex_unlock(&th_zone->therm_dev->lock);
445}
446
447/* Register with the in-kernel thermal management */
448static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
449{
450    int ret;
451    struct cpumask mask_val;
452
453    if (!sensor_conf || !sensor_conf->read_temperature) {
454        pr_err("Temperature sensor not initialised\n");
455        return -EINVAL;
456    }
457
458    th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
459    if (!th_zone)
460        return -ENOMEM;
461
462    th_zone->sensor_conf = sensor_conf;
463    cpumask_set_cpu(0, &mask_val);
464    th_zone->cool_dev[0] = cpufreq_cooling_register(&mask_val);
465    if (IS_ERR(th_zone->cool_dev[0])) {
466        pr_err("Failed to register cpufreq cooling device\n");
467        ret = -EINVAL;
468        goto err_unregister;
469    }
470    th_zone->cool_dev_size++;
471
472    th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
473            EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
474            sensor_conf->trip_data.trigger_falling ?
475            0 : IDLE_INTERVAL);
476
477    if (IS_ERR(th_zone->therm_dev)) {
478        pr_err("Failed to register thermal zone device\n");
479        ret = PTR_ERR(th_zone->therm_dev);
480        goto err_unregister;
481    }
482    th_zone->mode = THERMAL_DEVICE_ENABLED;
483
484    pr_info("Exynos: Kernel Thermal management registered\n");
485
486    return 0;
487
488err_unregister:
489    exynos_unregister_thermal();
490    return ret;
491}
492
493/* Un-Register with the in-kernel thermal management */
494static void exynos_unregister_thermal(void)
495{
496    int i;
497
498    if (!th_zone)
499        return;
500
501    if (th_zone->therm_dev)
502        thermal_zone_device_unregister(th_zone->therm_dev);
503
504    for (i = 0; i < th_zone->cool_dev_size; i++) {
505        if (th_zone->cool_dev[i])
506            cpufreq_cooling_unregister(th_zone->cool_dev[i]);
507    }
508
509    kfree(th_zone);
510    pr_info("Exynos: Kernel Thermal management unregistered\n");
511}
512
513/*
514 * TMU treats temperature as a mapped temperature code.
515 * The temperature is converted differently depending on the calibration type.
516 */
517static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
518{
519    struct exynos_tmu_platform_data *pdata = data->pdata;
520    int temp_code;
521
522    if (data->soc == SOC_ARCH_EXYNOS4210)
523        /* temp should range between 25 and 125 */
524        if (temp < 25 || temp > 125) {
525            temp_code = -EINVAL;
526            goto out;
527        }
528
529    switch (pdata->cal_type) {
530    case TYPE_TWO_POINT_TRIMMING:
531        temp_code = (temp - 25) *
532            (data->temp_error2 - data->temp_error1) /
533            (85 - 25) + data->temp_error1;
534        break;
535    case TYPE_ONE_POINT_TRIMMING:
536        temp_code = temp + data->temp_error1 - 25;
537        break;
538    default:
539        temp_code = temp + EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
540        break;
541    }
542out:
543    return temp_code;
544}
545
546/*
547 * Calculate a temperature value from a temperature code.
548 * The unit of the temperature is degree Celsius.
549 */
550static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
551{
552    struct exynos_tmu_platform_data *pdata = data->pdata;
553    int temp;
554
555    if (data->soc == SOC_ARCH_EXYNOS4210)
556        /* temp_code should range between 75 and 175 */
557        if (temp_code < 75 || temp_code > 175) {
558            temp = -ENODATA;
559            goto out;
560        }
561
562    switch (pdata->cal_type) {
563    case TYPE_TWO_POINT_TRIMMING:
564        temp = (temp_code - data->temp_error1) * (85 - 25) /
565            (data->temp_error2 - data->temp_error1) + 25;
566        break;
567    case TYPE_ONE_POINT_TRIMMING:
568        temp = temp_code - data->temp_error1 + 25;
569        break;
570    default:
571        temp = temp_code - EXYNOS_TMU_DEF_CODE_TO_TEMP_OFFSET;
572        break;
573    }
574out:
575    return temp;
576}
577
578static int exynos_tmu_initialize(struct platform_device *pdev)
579{
580    struct exynos_tmu_data *data = platform_get_drvdata(pdev);
581    struct exynos_tmu_platform_data *pdata = data->pdata;
582    unsigned int status, trim_info;
583    unsigned int rising_threshold = 0, falling_threshold = 0;
584    int ret = 0, threshold_code, i, trigger_levs = 0;
585
586    mutex_lock(&data->lock);
587    clk_enable(data->clk);
588
589    status = readb(data->base + EXYNOS_TMU_REG_STATUS);
590    if (!status) {
591        ret = -EBUSY;
592        goto out;
593    }
594
595    if (data->soc == SOC_ARCH_EXYNOS) {
596        __raw_writel(EXYNOS_TRIMINFO_RELOAD,
597                data->base + EXYNOS_TMU_TRIMINFO_CON);
598    }
599    /* Save trimming info in order to perform calibration */
600    trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
601    data->temp_error1 = trim_info & EXYNOS_TMU_TRIM_TEMP_MASK;
602    data->temp_error2 = ((trim_info >> 8) & EXYNOS_TMU_TRIM_TEMP_MASK);
603
604    if ((EFUSE_MIN_VALUE > data->temp_error1) ||
605            (data->temp_error1 > EFUSE_MAX_VALUE) ||
606            (data->temp_error2 != 0))
607        data->temp_error1 = pdata->efuse_value;
608
609    /* Count trigger levels to be enabled */
610    for (i = 0; i < MAX_THRESHOLD_LEVS; i++)
611        if (pdata->trigger_levels[i])
612            trigger_levs++;
613
614    if (data->soc == SOC_ARCH_EXYNOS4210) {
615        /* Write temperature code for threshold */
616        threshold_code = temp_to_code(data, pdata->threshold);
617        if (threshold_code < 0) {
618            ret = threshold_code;
619            goto out;
620        }
621        writeb(threshold_code,
622            data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
623        for (i = 0; i < trigger_levs; i++)
624            writeb(pdata->trigger_levels[i],
625            data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
626
627        writel(EXYNOS4210_TMU_INTCLEAR_VAL,
628            data->base + EXYNOS_TMU_REG_INTCLEAR);
629    } else if (data->soc == SOC_ARCH_EXYNOS) {
630        /* Write temperature code for rising and falling threshold */
631        for (i = 0; i < trigger_levs; i++) {
632            threshold_code = temp_to_code(data,
633                        pdata->trigger_levels[i]);
634            if (threshold_code < 0) {
635                ret = threshold_code;
636                goto out;
637            }
638            rising_threshold |= threshold_code << 8 * i;
639            if (pdata->threshold_falling) {
640                threshold_code = temp_to_code(data,
641                        pdata->trigger_levels[i] -
642                        pdata->threshold_falling);
643                if (threshold_code > 0)
644                    falling_threshold |=
645                        threshold_code << 8 * i;
646            }
647        }
648
649        writel(rising_threshold,
650                data->base + EXYNOS_THD_TEMP_RISE);
651        writel(falling_threshold,
652                data->base + EXYNOS_THD_TEMP_FALL);
653
654        writel(EXYNOS_TMU_CLEAR_RISE_INT | EXYNOS_TMU_CLEAR_FALL_INT,
655                data->base + EXYNOS_TMU_REG_INTCLEAR);
656    }
657out:
658    clk_disable(data->clk);
659    mutex_unlock(&data->lock);
660
661    return ret;
662}
663
664static void exynos_tmu_control(struct platform_device *pdev, bool on)
665{
666    struct exynos_tmu_data *data = platform_get_drvdata(pdev);
667    struct exynos_tmu_platform_data *pdata = data->pdata;
668    unsigned int con, interrupt_en;
669
670    mutex_lock(&data->lock);
671    clk_enable(data->clk);
672
673    con = pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT |
674        pdata->gain << EXYNOS_TMU_GAIN_SHIFT;
675
676    if (data->soc == SOC_ARCH_EXYNOS) {
677        con |= pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT;
678        con |= (EXYNOS_MUX_ADDR_VALUE << EXYNOS_MUX_ADDR_SHIFT);
679    }
680
681    if (on) {
682        con |= EXYNOS_TMU_CORE_ON;
683        interrupt_en = pdata->trigger_level3_en << 12 |
684            pdata->trigger_level2_en << 8 |
685            pdata->trigger_level1_en << 4 |
686            pdata->trigger_level0_en;
687        if (pdata->threshold_falling)
688            interrupt_en |= interrupt_en << 16;
689    } else {
690        con |= EXYNOS_TMU_CORE_OFF;
691        interrupt_en = 0; /* Disable all interrupts */
692    }
693    writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
694    writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
695
696    clk_disable(data->clk);
697    mutex_unlock(&data->lock);
698}
699
700static int exynos_tmu_read(struct exynos_tmu_data *data)
701{
702    u8 temp_code;
703    int temp;
704
705    mutex_lock(&data->lock);
706    clk_enable(data->clk);
707
708    temp_code = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
709    temp = code_to_temp(data, temp_code);
710
711    clk_disable(data->clk);
712    mutex_unlock(&data->lock);
713
714    return temp;
715}
716
717static void exynos_tmu_work(struct work_struct *work)
718{
719    struct exynos_tmu_data *data = container_of(work,
720            struct exynos_tmu_data, irq_work);
721
722    exynos_report_trigger();
723    mutex_lock(&data->lock);
724    clk_enable(data->clk);
725    if (data->soc == SOC_ARCH_EXYNOS)
726        writel(EXYNOS_TMU_CLEAR_RISE_INT |
727                EXYNOS_TMU_CLEAR_FALL_INT,
728                data->base + EXYNOS_TMU_REG_INTCLEAR);
729    else
730        writel(EXYNOS4210_TMU_INTCLEAR_VAL,
731                data->base + EXYNOS_TMU_REG_INTCLEAR);
732    clk_disable(data->clk);
733    mutex_unlock(&data->lock);
734
735    enable_irq(data->irq);
736}
737
738static irqreturn_t exynos_tmu_irq(int irq, void *id)
739{
740    struct exynos_tmu_data *data = id;
741
742    disable_irq_nosync(irq);
743    schedule_work(&data->irq_work);
744
745    return IRQ_HANDLED;
746}
747static struct thermal_sensor_conf exynos_sensor_conf = {
748    .name = "exynos-therm",
749    .read_temperature = (int (*)(void *))exynos_tmu_read,
750};
751
752#if defined(CONFIG_CPU_EXYNOS4210)
753static struct exynos_tmu_platform_data const exynos4210_default_tmu_data = {
754    .threshold = 80,
755    .trigger_levels[0] = 5,
756    .trigger_levels[1] = 20,
757    .trigger_levels[2] = 30,
758    .trigger_level0_en = 1,
759    .trigger_level1_en = 1,
760    .trigger_level2_en = 1,
761    .trigger_level3_en = 0,
762    .gain = 15,
763    .reference_voltage = 7,
764    .cal_type = TYPE_ONE_POINT_TRIMMING,
765    .freq_tab[0] = {
766        .freq_clip_max = 800 * 1000,
767        .temp_level = 85,
768    },
769    .freq_tab[1] = {
770        .freq_clip_max = 200 * 1000,
771        .temp_level = 100,
772    },
773    .freq_tab_count = 2,
774    .type = SOC_ARCH_EXYNOS4210,
775};
776#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
777#else
778#define EXYNOS4210_TMU_DRV_DATA (NULL)
779#endif
780
781#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
782static struct exynos_tmu_platform_data const exynos_default_tmu_data = {
783    .threshold_falling = 10,
784    .trigger_levels[0] = 85,
785    .trigger_levels[1] = 103,
786    .trigger_levels[2] = 110,
787    .trigger_level0_en = 1,
788    .trigger_level1_en = 1,
789    .trigger_level2_en = 1,
790    .trigger_level3_en = 0,
791    .gain = 8,
792    .reference_voltage = 16,
793    .noise_cancel_mode = 4,
794    .cal_type = TYPE_ONE_POINT_TRIMMING,
795    .efuse_value = 55,
796    .freq_tab[0] = {
797        .freq_clip_max = 800 * 1000,
798        .temp_level = 85,
799    },
800    .freq_tab[1] = {
801        .freq_clip_max = 200 * 1000,
802        .temp_level = 103,
803    },
804    .freq_tab_count = 2,
805    .type = SOC_ARCH_EXYNOS,
806};
807#define EXYNOS_TMU_DRV_DATA (&exynos_default_tmu_data)
808#else
809#define EXYNOS_TMU_DRV_DATA (NULL)
810#endif
811
812#ifdef CONFIG_OF
813static const struct of_device_id exynos_tmu_match[] = {
814    {
815        .compatible = "samsung,exynos4210-tmu",
816        .data = (void *)EXYNOS4210_TMU_DRV_DATA,
817    },
818    {
819        .compatible = "samsung,exynos5250-tmu",
820        .data = (void *)EXYNOS_TMU_DRV_DATA,
821    },
822    {},
823};
824MODULE_DEVICE_TABLE(of, exynos_tmu_match);
825#endif
826
827static struct platform_device_id exynos_tmu_driver_ids[] = {
828    {
829        .name = "exynos4210-tmu",
830        .driver_data = (kernel_ulong_t)EXYNOS4210_TMU_DRV_DATA,
831    },
832    {
833        .name = "exynos5250-tmu",
834        .driver_data = (kernel_ulong_t)EXYNOS_TMU_DRV_DATA,
835    },
836    { },
837};
838MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
839
840static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
841            struct platform_device *pdev)
842{
843#ifdef CONFIG_OF
844    if (pdev->dev.of_node) {
845        const struct of_device_id *match;
846        match = of_match_node(exynos_tmu_match, pdev->dev.of_node);
847        if (!match)
848            return NULL;
849        return (struct exynos_tmu_platform_data *) match->data;
850    }
851#endif
852    return (struct exynos_tmu_platform_data *)
853            platform_get_device_id(pdev)->driver_data;
854}
855
856#ifdef CONFIG_EXYNOS_THERMAL_EMUL
857static ssize_t exynos_tmu_emulation_show(struct device *dev,
858                     struct device_attribute *attr,
859                     char *buf)
860{
861    struct platform_device *pdev = container_of(dev,
862                    struct platform_device, dev);
863    struct exynos_tmu_data *data = platform_get_drvdata(pdev);
864    unsigned int reg;
865    u8 temp_code;
866    int temp = 0;
867
868    if (data->soc == SOC_ARCH_EXYNOS4210)
869        goto out;
870
871    mutex_lock(&data->lock);
872    clk_enable(data->clk);
873    reg = readl(data->base + EXYNOS_EMUL_CON);
874    clk_disable(data->clk);
875    mutex_unlock(&data->lock);
876
877    if (reg & EXYNOS_EMUL_ENABLE) {
878        reg >>= EXYNOS_EMUL_DATA_SHIFT;
879        temp_code = reg & EXYNOS_EMUL_DATA_MASK;
880        temp = code_to_temp(data, temp_code);
881    }
882out:
883    return sprintf(buf, "%d\n", temp * MCELSIUS);
884}
885
886static ssize_t exynos_tmu_emulation_store(struct device *dev,
887                    struct device_attribute *attr,
888                    const char *buf, size_t count)
889{
890    struct platform_device *pdev = container_of(dev,
891                    struct platform_device, dev);
892    struct exynos_tmu_data *data = platform_get_drvdata(pdev);
893    unsigned int reg;
894    int temp;
895
896    if (data->soc == SOC_ARCH_EXYNOS4210)
897        goto out;
898
899    if (!sscanf(buf, "%d\n", &temp) || temp < 0)
900        return -EINVAL;
901
902    mutex_lock(&data->lock);
903    clk_enable(data->clk);
904
905    reg = readl(data->base + EXYNOS_EMUL_CON);
906
907    if (temp) {
908        /* Both CELSIUS and MCELSIUS type are available for input */
909        if (temp > MCELSIUS)
910            temp /= MCELSIUS;
911
912        reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
913            (temp_to_code(data, (temp / MCELSIUS))
914             << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
915    } else {
916        reg &= ~EXYNOS_EMUL_ENABLE;
917    }
918
919    writel(reg, data->base + EXYNOS_EMUL_CON);
920
921    clk_disable(data->clk);
922    mutex_unlock(&data->lock);
923
924out:
925    return count;
926}
927
928static DEVICE_ATTR(emulation, 0644, exynos_tmu_emulation_show,
929                    exynos_tmu_emulation_store);
930static int create_emulation_sysfs(struct device *dev)
931{
932    return device_create_file(dev, &dev_attr_emulation);
933}
934static void remove_emulation_sysfs(struct device *dev)
935{
936    device_remove_file(dev, &dev_attr_emulation);
937}
938#else
939static inline int create_emulation_sysfs(struct device *dev) { return 0; }
940static inline void remove_emulation_sysfs(struct device *dev) {}
941#endif
942
943static int exynos_tmu_probe(struct platform_device *pdev)
944{
945    struct exynos_tmu_data *data;
946    struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
947    int ret, i;
948
949    if (!pdata)
950        pdata = exynos_get_driver_data(pdev);
951
952    if (!pdata) {
953        dev_err(&pdev->dev, "No platform init data supplied.\n");
954        return -ENODEV;
955    }
956    data = devm_kzalloc(&pdev->dev, sizeof(struct exynos_tmu_data),
957                    GFP_KERNEL);
958    if (!data) {
959        dev_err(&pdev->dev, "Failed to allocate driver structure\n");
960        return -ENOMEM;
961    }
962
963    data->irq = platform_get_irq(pdev, 0);
964    if (data->irq < 0) {
965        dev_err(&pdev->dev, "Failed to get platform irq\n");
966        return data->irq;
967    }
968
969    INIT_WORK(&data->irq_work, exynos_tmu_work);
970
971    data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
972    if (!data->mem) {
973        dev_err(&pdev->dev, "Failed to get platform resource\n");
974        return -ENOENT;
975    }
976
977    data->base = devm_ioremap_resource(&pdev->dev, data->mem);
978    if (IS_ERR(data->base))
979        return PTR_ERR(data->base);
980
981    ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq,
982        IRQF_TRIGGER_RISING, "exynos-tmu", data);
983    if (ret) {
984        dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
985        return ret;
986    }
987
988    data->clk = clk_get(NULL, "tmu_apbif");
989    if (IS_ERR(data->clk)) {
990        dev_err(&pdev->dev, "Failed to get clock\n");
991        return PTR_ERR(data->clk);
992    }
993
994    if (pdata->type == SOC_ARCH_EXYNOS ||
995                pdata->type == SOC_ARCH_EXYNOS4210)
996        data->soc = pdata->type;
997    else {
998        ret = -EINVAL;
999        dev_err(&pdev->dev, "Platform not supported\n");
1000        goto err_clk;
1001    }
1002
1003    data->pdata = pdata;
1004    platform_set_drvdata(pdev, data);
1005    mutex_init(&data->lock);
1006
1007    ret = exynos_tmu_initialize(pdev);
1008    if (ret) {
1009        dev_err(&pdev->dev, "Failed to initialize TMU\n");
1010        goto err_clk;
1011    }
1012
1013    exynos_tmu_control(pdev, true);
1014
1015    /* Register the sensor with thermal management interface */
1016    (&exynos_sensor_conf)->private_data = data;
1017    exynos_sensor_conf.trip_data.trip_count = pdata->trigger_level0_en +
1018            pdata->trigger_level1_en + pdata->trigger_level2_en +
1019            pdata->trigger_level3_en;
1020
1021    for (i = 0; i < exynos_sensor_conf.trip_data.trip_count; i++)
1022        exynos_sensor_conf.trip_data.trip_val[i] =
1023            pdata->threshold + pdata->trigger_levels[i];
1024
1025    exynos_sensor_conf.trip_data.trigger_falling = pdata->threshold_falling;
1026
1027    exynos_sensor_conf.cooling_data.freq_clip_count =
1028                        pdata->freq_tab_count;
1029    for (i = 0; i < pdata->freq_tab_count; i++) {
1030        exynos_sensor_conf.cooling_data.freq_data[i].freq_clip_max =
1031                    pdata->freq_tab[i].freq_clip_max;
1032        exynos_sensor_conf.cooling_data.freq_data[i].temp_level =
1033                    pdata->freq_tab[i].temp_level;
1034    }
1035
1036    ret = exynos_register_thermal(&exynos_sensor_conf);
1037    if (ret) {
1038        dev_err(&pdev->dev, "Failed to register thermal interface\n");
1039        goto err_clk;
1040    }
1041
1042    ret = create_emulation_sysfs(&pdev->dev);
1043    if (ret)
1044        dev_err(&pdev->dev, "Failed to create emulation mode sysfs node\n");
1045
1046    return 0;
1047err_clk:
1048    platform_set_drvdata(pdev, NULL);
1049    clk_put(data->clk);
1050    return ret;
1051}
1052
1053static int exynos_tmu_remove(struct platform_device *pdev)
1054{
1055    struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1056
1057    remove_emulation_sysfs(&pdev->dev);
1058
1059    exynos_tmu_control(pdev, false);
1060
1061    exynos_unregister_thermal();
1062
1063    clk_put(data->clk);
1064
1065    platform_set_drvdata(pdev, NULL);
1066
1067    return 0;
1068}
1069
1070#ifdef CONFIG_PM_SLEEP
1071static int exynos_tmu_suspend(struct device *dev)
1072{
1073    exynos_tmu_control(to_platform_device(dev), false);
1074
1075    return 0;
1076}
1077
1078static int exynos_tmu_resume(struct device *dev)
1079{
1080    struct platform_device *pdev = to_platform_device(dev);
1081
1082    exynos_tmu_initialize(pdev);
1083    exynos_tmu_control(pdev, true);
1084
1085    return 0;
1086}
1087
1088static SIMPLE_DEV_PM_OPS(exynos_tmu_pm,
1089             exynos_tmu_suspend, exynos_tmu_resume);
1090#define EXYNOS_TMU_PM (&exynos_tmu_pm)
1091#else
1092#define EXYNOS_TMU_PM NULL
1093#endif
1094
1095static struct platform_driver exynos_tmu_driver = {
1096    .driver = {
1097        .name = "exynos-tmu",
1098        .owner = THIS_MODULE,
1099        .pm = EXYNOS_TMU_PM,
1100        .of_match_table = of_match_ptr(exynos_tmu_match),
1101    },
1102    .probe = exynos_tmu_probe,
1103    .remove = exynos_tmu_remove,
1104    .id_table = exynos_tmu_driver_ids,
1105};
1106
1107module_platform_driver(exynos_tmu_driver);
1108
1109MODULE_DESCRIPTION("EXYNOS TMU Driver");
1110MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
1111MODULE_LICENSE("GPL");
1112MODULE_ALIAS("platform:exynos-tmu");
1113

Archive Download this file



interactive