exynos_tmu.c (285d994a51e45ca59a9cde34a3a0ea316e263617) exynos_tmu.c (a7331f72d3eb2bf6a15405459f7c514607402ca6)
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

--- 42 unchanged lines hidden (view full) ---

51 * @temp_error1: fused value of the first point trim.
52 * @temp_error2: fused value of the second point trim.
53 * @regulator: pointer to the TMU regulator structure.
54 * @reg_conf: pointer to structure to register with core thermal.
55 * @tmu_initialize: SoC specific TMU initialization method
56 * @tmu_control: SoC specific TMU control method
57 * @tmu_read: SoC specific TMU temperature read method
58 * @tmu_set_emulation: SoC specific TMU emulation setting method
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

--- 42 unchanged lines hidden (view full) ---

51 * @temp_error1: fused value of the first point trim.
52 * @temp_error2: fused value of the second point trim.
53 * @regulator: pointer to the TMU regulator structure.
54 * @reg_conf: pointer to structure to register with core thermal.
55 * @tmu_initialize: SoC specific TMU initialization method
56 * @tmu_control: SoC specific TMU control method
57 * @tmu_read: SoC specific TMU temperature read method
58 * @tmu_set_emulation: SoC specific TMU emulation setting method
59 * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
59 */
60struct exynos_tmu_data {
61 int id;
62 struct exynos_tmu_platform_data *pdata;
63 void __iomem *base;
64 void __iomem *base_second;
65 int irq;
66 enum soc_type soc;
67 struct work_struct irq_work;
68 struct mutex lock;
69 struct clk *clk, *clk_sec;
70 u8 temp_error1, temp_error2;
71 struct regulator *regulator;
72 struct thermal_sensor_conf *reg_conf;
73 int (*tmu_initialize)(struct platform_device *pdev);
74 void (*tmu_control)(struct platform_device *pdev, bool on);
75 int (*tmu_read)(struct exynos_tmu_data *data);
76 void (*tmu_set_emulation)(struct exynos_tmu_data *data,
77 unsigned long temp);
60 */
61struct exynos_tmu_data {
62 int id;
63 struct exynos_tmu_platform_data *pdata;
64 void __iomem *base;
65 void __iomem *base_second;
66 int irq;
67 enum soc_type soc;
68 struct work_struct irq_work;
69 struct mutex lock;
70 struct clk *clk, *clk_sec;
71 u8 temp_error1, temp_error2;
72 struct regulator *regulator;
73 struct thermal_sensor_conf *reg_conf;
74 int (*tmu_initialize)(struct platform_device *pdev);
75 void (*tmu_control)(struct platform_device *pdev, bool on);
76 int (*tmu_read)(struct exynos_tmu_data *data);
77 void (*tmu_set_emulation)(struct exynos_tmu_data *data,
78 unsigned long temp);
79 void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
78};
79
80/*
81 * TMU treats temperature as a mapped temperature code.
82 * The temperature is converted differently depending on the calibration type.
83 */
84static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
85{

--- 40 unchanged lines hidden (view full) ---

126 default:
127 temp = temp_code - pdata->default_temp_offset;
128 break;
129 }
130
131 return temp;
132}
133
80};
81
82/*
83 * TMU treats temperature as a mapped temperature code.
84 * The temperature is converted differently depending on the calibration type.
85 */
86static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
87{

--- 40 unchanged lines hidden (view full) ---

128 default:
129 temp = temp_code - pdata->default_temp_offset;
130 break;
131 }
132
133 return temp;
134}
135
134static void exynos_tmu_clear_irqs(struct exynos_tmu_data *data)
135{
136 const struct exynos_tmu_registers *reg = data->pdata->registers;
137 unsigned int val_irq;
138
139 val_irq = readl(data->base + reg->tmu_intstat);
140 /*
141 * Clear the interrupts. Please note that the documentation for
142 * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
143 * states that INTCLEAR register has a different placing of bits
144 * responsible for FALL IRQs than INTSTAT register. Exynos5420
145 * and Exynos5440 documentation is correct (Exynos4210 doesn't
146 * support FALL IRQs at all).
147 */
148 writel(val_irq, data->base + reg->tmu_intclear);
149}
150
151static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
152{
153 struct exynos_tmu_platform_data *pdata = data->pdata;
154
155 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
156 data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
157 EXYNOS_TMU_TEMP_MASK);
158

--- 95 unchanged lines hidden (view full) ---

254 /* Write temperature code for threshold */
255 threshold_code = temp_to_code(data, pdata->threshold);
256 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
257
258 for (i = 0; i < pdata->non_hw_trigger_levels; i++)
259 writeb(pdata->trigger_levels[i], data->base +
260 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
261
136static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
137{
138 struct exynos_tmu_platform_data *pdata = data->pdata;
139
140 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
141 data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
142 EXYNOS_TMU_TEMP_MASK);
143

--- 95 unchanged lines hidden (view full) ---

239 /* Write temperature code for threshold */
240 threshold_code = temp_to_code(data, pdata->threshold);
241 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
242
243 for (i = 0; i < pdata->non_hw_trigger_levels; i++)
244 writeb(pdata->trigger_levels[i], data->base +
245 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
246
262 exynos_tmu_clear_irqs(data);
247 data->tmu_clear_irqs(data);
263out:
264 return ret;
265}
266
267static int exynos4412_tmu_initialize(struct platform_device *pdev)
268{
269 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
270 struct exynos_tmu_platform_data *pdata = data->pdata;

--- 28 unchanged lines hidden (view full) ---

299 sanitize_temp_error(data, trim_info);
300
301 /* Write temperature code for rising and falling threshold */
302 rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE);
303 rising_threshold = get_th_reg(data, rising_threshold, false);
304 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
305 writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL);
306
248out:
249 return ret;
250}
251
252static int exynos4412_tmu_initialize(struct platform_device *pdev)
253{
254 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
255 struct exynos_tmu_platform_data *pdata = data->pdata;

--- 28 unchanged lines hidden (view full) ---

284 sanitize_temp_error(data, trim_info);
285
286 /* Write temperature code for rising and falling threshold */
287 rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE);
288 rising_threshold = get_th_reg(data, rising_threshold, false);
289 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
290 writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL);
291
307 exynos_tmu_clear_irqs(data);
292 data->tmu_clear_irqs(data);
308
309 /* if last threshold limit is also present */
310 i = pdata->max_trigger_level - 1;
311 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
312 threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
313 /* 1-4 level to be assigned in th0 reg */
314 rising_threshold &= ~(0xff << 8 * i);
315 rising_threshold |= threshold_code << 8 * i;

--- 32 unchanged lines hidden (view full) ---

348 sanitize_temp_error(data, trim_info);
349
350 /* Write temperature code for rising and falling threshold */
351 rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0);
352 rising_threshold = get_th_reg(data, rising_threshold, false);
353 writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0);
354 writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1);
355
293
294 /* if last threshold limit is also present */
295 i = pdata->max_trigger_level - 1;
296 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
297 threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
298 /* 1-4 level to be assigned in th0 reg */
299 rising_threshold &= ~(0xff << 8 * i);
300 rising_threshold |= threshold_code << 8 * i;

--- 32 unchanged lines hidden (view full) ---

333 sanitize_temp_error(data, trim_info);
334
335 /* Write temperature code for rising and falling threshold */
336 rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0);
337 rising_threshold = get_th_reg(data, rising_threshold, false);
338 writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0);
339 writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1);
340
356 exynos_tmu_clear_irqs(data);
341 data->tmu_clear_irqs(data);
357
358 /* if last threshold limit is also present */
359 i = pdata->max_trigger_level - 1;
360 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
361 threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
362 /* 5th level to be assigned in th2 reg */
363 rising_threshold =
364 threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;

--- 187 unchanged lines hidden (view full) ---

552 if (!IS_ERR(data->clk_sec))
553 clk_disable(data->clk_sec);
554
555 exynos_report_trigger(data->reg_conf);
556 mutex_lock(&data->lock);
557 clk_enable(data->clk);
558
559 /* TODO: take action based on particular interrupt */
342
343 /* if last threshold limit is also present */
344 i = pdata->max_trigger_level - 1;
345 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
346 threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
347 /* 5th level to be assigned in th2 reg */
348 rising_threshold =
349 threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;

--- 187 unchanged lines hidden (view full) ---

537 if (!IS_ERR(data->clk_sec))
538 clk_disable(data->clk_sec);
539
540 exynos_report_trigger(data->reg_conf);
541 mutex_lock(&data->lock);
542 clk_enable(data->clk);
543
544 /* TODO: take action based on particular interrupt */
560 exynos_tmu_clear_irqs(data);
545 data->tmu_clear_irqs(data);
561
562 clk_disable(data->clk);
563 mutex_unlock(&data->lock);
564out:
565 enable_irq(data->irq);
566}
567
546
547 clk_disable(data->clk);
548 mutex_unlock(&data->lock);
549out:
550 enable_irq(data->irq);
551}
552
553static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data)
554{
555 unsigned int val_irq;
556 u32 tmu_intstat, tmu_intclear;
557
558 if (data->soc == SOC_ARCH_EXYNOS5260) {
559 tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
560 tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR;
561 } else {
562 tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
563 tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
564 }
565
566 val_irq = readl(data->base + tmu_intstat);
567 /*
568 * Clear the interrupts. Please note that the documentation for
569 * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
570 * states that INTCLEAR register has a different placing of bits
571 * responsible for FALL IRQs than INTSTAT register. Exynos5420
572 * and Exynos5440 documentation is correct (Exynos4210 doesn't
573 * support FALL IRQs at all).
574 */
575 writel(val_irq, data->base + tmu_intclear);
576}
577
578static void exynos5440_tmu_clear_irqs(struct exynos_tmu_data *data)
579{
580 unsigned int val_irq;
581
582 val_irq = readl(data->base + EXYNOS5440_TMU_S0_7_IRQ);
583 /* clear the interrupts */
584 writel(val_irq, data->base + EXYNOS5440_TMU_S0_7_IRQ);
585}
586
568static irqreturn_t exynos_tmu_irq(int irq, void *id)
569{
570 struct exynos_tmu_data *data = id;
571
572 disable_irq_nosync(irq);
573 schedule_work(&data->irq_work);
574
575 return IRQ_HANDLED;

--- 179 unchanged lines hidden (view full) ---

755
756 data->soc = pdata->type;
757
758 switch (data->soc) {
759 case SOC_ARCH_EXYNOS4210:
760 data->tmu_initialize = exynos4210_tmu_initialize;
761 data->tmu_control = exynos4210_tmu_control;
762 data->tmu_read = exynos4210_tmu_read;
587static irqreturn_t exynos_tmu_irq(int irq, void *id)
588{
589 struct exynos_tmu_data *data = id;
590
591 disable_irq_nosync(irq);
592 schedule_work(&data->irq_work);
593
594 return IRQ_HANDLED;

--- 179 unchanged lines hidden (view full) ---

774
775 data->soc = pdata->type;
776
777 switch (data->soc) {
778 case SOC_ARCH_EXYNOS4210:
779 data->tmu_initialize = exynos4210_tmu_initialize;
780 data->tmu_control = exynos4210_tmu_control;
781 data->tmu_read = exynos4210_tmu_read;
782 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
763 break;
764 case SOC_ARCH_EXYNOS3250:
765 case SOC_ARCH_EXYNOS4412:
766 case SOC_ARCH_EXYNOS5250:
767 case SOC_ARCH_EXYNOS5260:
768 case SOC_ARCH_EXYNOS5420:
769 case SOC_ARCH_EXYNOS5420_TRIMINFO:
770 data->tmu_initialize = exynos4412_tmu_initialize;
771 data->tmu_control = exynos4210_tmu_control;
772 data->tmu_read = exynos4412_tmu_read;
773 data->tmu_set_emulation = exynos4412_tmu_set_emulation;
783 break;
784 case SOC_ARCH_EXYNOS3250:
785 case SOC_ARCH_EXYNOS4412:
786 case SOC_ARCH_EXYNOS5250:
787 case SOC_ARCH_EXYNOS5260:
788 case SOC_ARCH_EXYNOS5420:
789 case SOC_ARCH_EXYNOS5420_TRIMINFO:
790 data->tmu_initialize = exynos4412_tmu_initialize;
791 data->tmu_control = exynos4210_tmu_control;
792 data->tmu_read = exynos4412_tmu_read;
793 data->tmu_set_emulation = exynos4412_tmu_set_emulation;
794 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
774 break;
775 case SOC_ARCH_EXYNOS5440:
776 data->tmu_initialize = exynos5440_tmu_initialize;
777 data->tmu_control = exynos5440_tmu_control;
778 data->tmu_read = exynos5440_tmu_read;
779 data->tmu_set_emulation = exynos5440_tmu_set_emulation;
795 break;
796 case SOC_ARCH_EXYNOS5440:
797 data->tmu_initialize = exynos5440_tmu_initialize;
798 data->tmu_control = exynos5440_tmu_control;
799 data->tmu_read = exynos5440_tmu_read;
800 data->tmu_set_emulation = exynos5440_tmu_set_emulation;
801 data->tmu_clear_irqs = exynos5440_tmu_clear_irqs;
780 break;
781 default:
782 ret = -EINVAL;
783 dev_err(&pdev->dev, "Platform not supported\n");
784 goto err_clk;
785 }
786
787 ret = exynos_tmu_initialize(pdev);

--- 124 unchanged lines hidden ---
802 break;
803 default:
804 ret = -EINVAL;
805 dev_err(&pdev->dev, "Platform not supported\n");
806 goto err_clk;
807 }
808
809 ret = exynos_tmu_initialize(pdev);

--- 124 unchanged lines hidden ---