diff options
Diffstat (limited to 'drivers/thermal/samsung/exynos_tmu.c')
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu.c | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 01aa5481c13e..1b3c2f4a846b 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c | |||
@@ -56,6 +56,7 @@ | |||
56 | * @tmu_control: SoC specific TMU control method | 56 | * @tmu_control: SoC specific TMU control method |
57 | * @tmu_read: SoC specific TMU temperature read method | 57 | * @tmu_read: SoC specific TMU temperature read method |
58 | * @tmu_set_emulation: SoC specific TMU emulation setting method | 58 | * @tmu_set_emulation: SoC specific TMU emulation setting method |
59 | * @tmu_clear_irqs: SoC specific TMU interrupts clearing method | ||
59 | */ | 60 | */ |
60 | struct exynos_tmu_data { | 61 | struct exynos_tmu_data { |
61 | int id; | 62 | int id; |
@@ -75,6 +76,7 @@ struct exynos_tmu_data { | |||
75 | int (*tmu_read)(struct exynos_tmu_data *data); | 76 | int (*tmu_read)(struct exynos_tmu_data *data); |
76 | void (*tmu_set_emulation)(struct exynos_tmu_data *data, | 77 | void (*tmu_set_emulation)(struct exynos_tmu_data *data, |
77 | unsigned long temp); | 78 | unsigned long temp); |
79 | void (*tmu_clear_irqs)(struct exynos_tmu_data *data); | ||
78 | }; | 80 | }; |
79 | 81 | ||
80 | /* | 82 | /* |
@@ -131,23 +133,6 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code) | |||
131 | return temp; | 133 | return temp; |
132 | } | 134 | } |
133 | 135 | ||
134 | static 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 | |||
151 | static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) | 136 | static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) |
152 | { | 137 | { |
153 | struct exynos_tmu_platform_data *pdata = data->pdata; | 138 | struct exynos_tmu_platform_data *pdata = data->pdata; |
@@ -259,7 +244,7 @@ static int exynos4210_tmu_initialize(struct platform_device *pdev) | |||
259 | writeb(pdata->trigger_levels[i], data->base + | 244 | writeb(pdata->trigger_levels[i], data->base + |
260 | EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4); | 245 | EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4); |
261 | 246 | ||
262 | exynos_tmu_clear_irqs(data); | 247 | data->tmu_clear_irqs(data); |
263 | out: | 248 | out: |
264 | return ret; | 249 | return ret; |
265 | } | 250 | } |
@@ -304,7 +289,7 @@ static int exynos4412_tmu_initialize(struct platform_device *pdev) | |||
304 | writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE); | 289 | writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE); |
305 | writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL); | 290 | writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL); |
306 | 291 | ||
307 | exynos_tmu_clear_irqs(data); | 292 | data->tmu_clear_irqs(data); |
308 | 293 | ||
309 | /* if last threshold limit is also present */ | 294 | /* if last threshold limit is also present */ |
310 | i = pdata->max_trigger_level - 1; | 295 | i = pdata->max_trigger_level - 1; |
@@ -353,7 +338,7 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev) | |||
353 | writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0); | 338 | writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0); |
354 | writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1); | 339 | writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1); |
355 | 340 | ||
356 | exynos_tmu_clear_irqs(data); | 341 | data->tmu_clear_irqs(data); |
357 | 342 | ||
358 | /* if last threshold limit is also present */ | 343 | /* if last threshold limit is also present */ |
359 | i = pdata->max_trigger_level - 1; | 344 | i = pdata->max_trigger_level - 1; |
@@ -557,7 +542,7 @@ static void exynos_tmu_work(struct work_struct *work) | |||
557 | clk_enable(data->clk); | 542 | clk_enable(data->clk); |
558 | 543 | ||
559 | /* TODO: take action based on particular interrupt */ | 544 | /* TODO: take action based on particular interrupt */ |
560 | exynos_tmu_clear_irqs(data); | 545 | data->tmu_clear_irqs(data); |
561 | 546 | ||
562 | clk_disable(data->clk); | 547 | clk_disable(data->clk); |
563 | mutex_unlock(&data->lock); | 548 | mutex_unlock(&data->lock); |
@@ -565,6 +550,40 @@ out: | |||
565 | enable_irq(data->irq); | 550 | enable_irq(data->irq); |
566 | } | 551 | } |
567 | 552 | ||
553 | static 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 | |||
578 | static 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 | |||
568 | static irqreturn_t exynos_tmu_irq(int irq, void *id) | 587 | static irqreturn_t exynos_tmu_irq(int irq, void *id) |
569 | { | 588 | { |
570 | struct exynos_tmu_data *data = id; | 589 | struct exynos_tmu_data *data = id; |
@@ -760,6 +779,7 @@ static int exynos_tmu_probe(struct platform_device *pdev) | |||
760 | data->tmu_initialize = exynos4210_tmu_initialize; | 779 | data->tmu_initialize = exynos4210_tmu_initialize; |
761 | data->tmu_control = exynos4210_tmu_control; | 780 | data->tmu_control = exynos4210_tmu_control; |
762 | data->tmu_read = exynos4210_tmu_read; | 781 | data->tmu_read = exynos4210_tmu_read; |
782 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; | ||
763 | break; | 783 | break; |
764 | case SOC_ARCH_EXYNOS3250: | 784 | case SOC_ARCH_EXYNOS3250: |
765 | case SOC_ARCH_EXYNOS4412: | 785 | case SOC_ARCH_EXYNOS4412: |
@@ -771,12 +791,14 @@ static int exynos_tmu_probe(struct platform_device *pdev) | |||
771 | data->tmu_control = exynos4210_tmu_control; | 791 | data->tmu_control = exynos4210_tmu_control; |
772 | data->tmu_read = exynos4412_tmu_read; | 792 | data->tmu_read = exynos4412_tmu_read; |
773 | data->tmu_set_emulation = exynos4412_tmu_set_emulation; | 793 | data->tmu_set_emulation = exynos4412_tmu_set_emulation; |
794 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; | ||
774 | break; | 795 | break; |
775 | case SOC_ARCH_EXYNOS5440: | 796 | case SOC_ARCH_EXYNOS5440: |
776 | data->tmu_initialize = exynos5440_tmu_initialize; | 797 | data->tmu_initialize = exynos5440_tmu_initialize; |
777 | data->tmu_control = exynos5440_tmu_control; | 798 | data->tmu_control = exynos5440_tmu_control; |
778 | data->tmu_read = exynos5440_tmu_read; | 799 | data->tmu_read = exynos5440_tmu_read; |
779 | data->tmu_set_emulation = exynos5440_tmu_set_emulation; | 800 | data->tmu_set_emulation = exynos5440_tmu_set_emulation; |
801 | data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; | ||
780 | break; | 802 | break; |
781 | default: | 803 | default: |
782 | ret = -EINVAL; | 804 | ret = -EINVAL; |