diff options
author | Abhilash Kesavan <a.kesavan@samsung.com> | 2015-01-27 00:48:22 -0500 |
---|---|---|
committer | Eduardo Valentin <edubezval@gmail.com> | 2015-01-31 14:20:45 -0500 |
commit | 6c247393cfdd6695717f80ff31f9fd9af8c2c525 (patch) | |
tree | 15133debdf0ce9d9b8fdacd650b6b52899d29434 | |
parent | 14ccc17a37c291172c557070f4faf77445494aff (diff) |
thermal: exynos: Add TMU support for Exynos7 SoC
Add registers, bit fields and compatible strings for Exynos7 TMU
(Thermal Management Unit). Following are a few of the differences
in the Exynos7 TMU from earlier SoCs:
- 8 trigger levels
- Different bit offsets and more registers for the rising
and falling thresholds.
- New power down detection bit in the TMU_CONTROL register
which does not update the CURRENT_TEMP0 when tmu power down
is detected.
- Change in bit offset for the NEXT_DATA field of EMUL_CON
register. EMUL_CON register address has also changed.
- INTSTAT and INTCLEAR registers present in earlier SoCs
have been combined into one INTPEND register. The register
address for INTCLEAR and INTPEND is also different.
- Since there are 8 rising/falling interrupts as against
at most 4 in earlier SoCs the INTEN bit offsets are different.
- Multiple probe support which is handled by a TMU_CONTROL1
register (No support for this in the current patch).
This patch adds special clock support required only for Exynos7. It
also updates the "code_to_temp" prototype as Exynos7 has 9 bit
code-temp mapping.
Acked-by: Lukasz Majewski <l.majewski@samsung.com>
Tested-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu.c | 205 | ||||
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu.h | 1 |
2 files changed, 198 insertions, 8 deletions
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index b6a6e90ba340..fbeedc072cc2 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c | |||
@@ -119,6 +119,26 @@ | |||
119 | #define EXYNOS5440_TMU_TH_RISE4_SHIFT 24 | 119 | #define EXYNOS5440_TMU_TH_RISE4_SHIFT 24 |
120 | #define EXYNOS5440_EFUSE_SWAP_OFFSET 8 | 120 | #define EXYNOS5440_EFUSE_SWAP_OFFSET 8 |
121 | 121 | ||
122 | /* Exynos7 specific registers */ | ||
123 | #define EXYNOS7_THD_TEMP_RISE7_6 0x50 | ||
124 | #define EXYNOS7_THD_TEMP_FALL7_6 0x60 | ||
125 | #define EXYNOS7_TMU_REG_INTEN 0x110 | ||
126 | #define EXYNOS7_TMU_REG_INTPEND 0x118 | ||
127 | #define EXYNOS7_TMU_REG_EMUL_CON 0x160 | ||
128 | |||
129 | #define EXYNOS7_TMU_TEMP_MASK 0x1ff | ||
130 | #define EXYNOS7_PD_DET_EN_SHIFT 23 | ||
131 | #define EXYNOS7_TMU_INTEN_RISE0_SHIFT 0 | ||
132 | #define EXYNOS7_TMU_INTEN_RISE1_SHIFT 1 | ||
133 | #define EXYNOS7_TMU_INTEN_RISE2_SHIFT 2 | ||
134 | #define EXYNOS7_TMU_INTEN_RISE3_SHIFT 3 | ||
135 | #define EXYNOS7_TMU_INTEN_RISE4_SHIFT 4 | ||
136 | #define EXYNOS7_TMU_INTEN_RISE5_SHIFT 5 | ||
137 | #define EXYNOS7_TMU_INTEN_RISE6_SHIFT 6 | ||
138 | #define EXYNOS7_TMU_INTEN_RISE7_SHIFT 7 | ||
139 | #define EXYNOS7_EMUL_DATA_SHIFT 7 | ||
140 | #define EXYNOS7_EMUL_DATA_MASK 0x1ff | ||
141 | |||
122 | #define MCELSIUS 1000 | 142 | #define MCELSIUS 1000 |
123 | /** | 143 | /** |
124 | * struct exynos_tmu_data : A structure to hold the private data of the TMU | 144 | * struct exynos_tmu_data : A structure to hold the private data of the TMU |
@@ -133,6 +153,7 @@ | |||
133 | * @lock: lock to implement synchronization. | 153 | * @lock: lock to implement synchronization. |
134 | * @clk: pointer to the clock structure. | 154 | * @clk: pointer to the clock structure. |
135 | * @clk_sec: pointer to the clock structure for accessing the base_second. | 155 | * @clk_sec: pointer to the clock structure for accessing the base_second. |
156 | * @sclk: pointer to the clock structure for accessing the tmu special clk. | ||
136 | * @temp_error1: fused value of the first point trim. | 157 | * @temp_error1: fused value of the first point trim. |
137 | * @temp_error2: fused value of the second point trim. | 158 | * @temp_error2: fused value of the second point trim. |
138 | * @regulator: pointer to the TMU regulator structure. | 159 | * @regulator: pointer to the TMU regulator structure. |
@@ -152,8 +173,8 @@ struct exynos_tmu_data { | |||
152 | enum soc_type soc; | 173 | enum soc_type soc; |
153 | struct work_struct irq_work; | 174 | struct work_struct irq_work; |
154 | struct mutex lock; | 175 | struct mutex lock; |
155 | struct clk *clk, *clk_sec; | 176 | struct clk *clk, *clk_sec, *sclk; |
156 | u8 temp_error1, temp_error2; | 177 | u16 temp_error1, temp_error2; |
157 | struct regulator *regulator; | 178 | struct regulator *regulator; |
158 | struct thermal_zone_device *tzd; | 179 | struct thermal_zone_device *tzd; |
159 | 180 | ||
@@ -223,7 +244,7 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp) | |||
223 | * Calculate a temperature value from a temperature code. | 244 | * Calculate a temperature value from a temperature code. |
224 | * The unit of the temperature is degree Celsius. | 245 | * The unit of the temperature is degree Celsius. |
225 | */ | 246 | */ |
226 | static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code) | 247 | static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code) |
227 | { | 248 | { |
228 | struct exynos_tmu_platform_data *pdata = data->pdata; | 249 | struct exynos_tmu_platform_data *pdata = data->pdata; |
229 | int temp; | 250 | int temp; |
@@ -513,6 +534,84 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev) | |||
513 | return ret; | 534 | return ret; |
514 | } | 535 | } |
515 | 536 | ||
537 | static int exynos7_tmu_initialize(struct platform_device *pdev) | ||
538 | { | ||
539 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | ||
540 | struct thermal_zone_device *tz = data->tzd; | ||
541 | struct exynos_tmu_platform_data *pdata = data->pdata; | ||
542 | unsigned int status, trim_info; | ||
543 | unsigned int rising_threshold = 0, falling_threshold = 0; | ||
544 | int ret = 0, threshold_code, i; | ||
545 | unsigned long temp, temp_hist; | ||
546 | unsigned int reg_off, bit_off; | ||
547 | |||
548 | status = readb(data->base + EXYNOS_TMU_REG_STATUS); | ||
549 | if (!status) { | ||
550 | ret = -EBUSY; | ||
551 | goto out; | ||
552 | } | ||
553 | |||
554 | trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); | ||
555 | |||
556 | data->temp_error1 = trim_info & EXYNOS7_TMU_TEMP_MASK; | ||
557 | if (!data->temp_error1 || | ||
558 | (pdata->min_efuse_value > data->temp_error1) || | ||
559 | (data->temp_error1 > pdata->max_efuse_value)) | ||
560 | data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK; | ||
561 | |||
562 | /* Write temperature code for rising and falling threshold */ | ||
563 | for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) { | ||
564 | /* | ||
565 | * On exynos7 there are 4 rising and 4 falling threshold | ||
566 | * registers (0x50-0x5c and 0x60-0x6c respectively). Each | ||
567 | * register holds the value of two threshold levels (at bit | ||
568 | * offsets 0 and 16). Based on the fact that there are atmost | ||
569 | * eight possible trigger levels, calculate the register and | ||
570 | * bit offsets where the threshold levels are to be written. | ||
571 | * | ||
572 | * e.g. EXYNOS7_THD_TEMP_RISE7_6 (0x50) | ||
573 | * [24:16] - Threshold level 7 | ||
574 | * [8:0] - Threshold level 6 | ||
575 | * e.g. EXYNOS7_THD_TEMP_RISE5_4 (0x54) | ||
576 | * [24:16] - Threshold level 5 | ||
577 | * [8:0] - Threshold level 4 | ||
578 | * | ||
579 | * and similarly for falling thresholds. | ||
580 | * | ||
581 | * Based on the above, calculate the register and bit offsets | ||
582 | * for rising/falling threshold levels and populate them. | ||
583 | */ | ||
584 | reg_off = ((7 - i) / 2) * 4; | ||
585 | bit_off = ((8 - i) % 2); | ||
586 | |||
587 | tz->ops->get_trip_temp(tz, i, &temp); | ||
588 | temp /= MCELSIUS; | ||
589 | |||
590 | tz->ops->get_trip_hyst(tz, i, &temp_hist); | ||
591 | temp_hist = temp - (temp_hist / MCELSIUS); | ||
592 | |||
593 | /* Set 9-bit temperature code for rising threshold levels */ | ||
594 | threshold_code = temp_to_code(data, temp); | ||
595 | rising_threshold = readl(data->base + | ||
596 | EXYNOS7_THD_TEMP_RISE7_6 + reg_off); | ||
597 | rising_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); | ||
598 | rising_threshold |= threshold_code << (16 * bit_off); | ||
599 | writel(rising_threshold, | ||
600 | data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off); | ||
601 | |||
602 | /* Set 9-bit temperature code for falling threshold levels */ | ||
603 | threshold_code = temp_to_code(data, temp_hist); | ||
604 | falling_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); | ||
605 | falling_threshold |= threshold_code << (16 * bit_off); | ||
606 | writel(falling_threshold, | ||
607 | data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off); | ||
608 | } | ||
609 | |||
610 | data->tmu_clear_irqs(data); | ||
611 | out: | ||
612 | return ret; | ||
613 | } | ||
614 | |||
516 | static void exynos4210_tmu_control(struct platform_device *pdev, bool on) | 615 | static void exynos4210_tmu_control(struct platform_device *pdev, bool on) |
517 | { | 616 | { |
518 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 617 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
@@ -573,6 +672,46 @@ static void exynos5440_tmu_control(struct platform_device *pdev, bool on) | |||
573 | writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL); | 672 | writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL); |
574 | } | 673 | } |
575 | 674 | ||
675 | static void exynos7_tmu_control(struct platform_device *pdev, bool on) | ||
676 | { | ||
677 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | ||
678 | struct thermal_zone_device *tz = data->tzd; | ||
679 | unsigned int con, interrupt_en; | ||
680 | |||
681 | con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); | ||
682 | |||
683 | if (on) { | ||
684 | con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); | ||
685 | interrupt_en = | ||
686 | (of_thermal_is_trip_valid(tz, 7) | ||
687 | << EXYNOS7_TMU_INTEN_RISE7_SHIFT) | | ||
688 | (of_thermal_is_trip_valid(tz, 6) | ||
689 | << EXYNOS7_TMU_INTEN_RISE6_SHIFT) | | ||
690 | (of_thermal_is_trip_valid(tz, 5) | ||
691 | << EXYNOS7_TMU_INTEN_RISE5_SHIFT) | | ||
692 | (of_thermal_is_trip_valid(tz, 4) | ||
693 | << EXYNOS7_TMU_INTEN_RISE4_SHIFT) | | ||
694 | (of_thermal_is_trip_valid(tz, 3) | ||
695 | << EXYNOS7_TMU_INTEN_RISE3_SHIFT) | | ||
696 | (of_thermal_is_trip_valid(tz, 2) | ||
697 | << EXYNOS7_TMU_INTEN_RISE2_SHIFT) | | ||
698 | (of_thermal_is_trip_valid(tz, 1) | ||
699 | << EXYNOS7_TMU_INTEN_RISE1_SHIFT) | | ||
700 | (of_thermal_is_trip_valid(tz, 0) | ||
701 | << EXYNOS7_TMU_INTEN_RISE0_SHIFT); | ||
702 | |||
703 | interrupt_en |= | ||
704 | interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; | ||
705 | } else { | ||
706 | con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); | ||
707 | interrupt_en = 0; /* Disable all interrupts */ | ||
708 | } | ||
709 | con |= 1 << EXYNOS7_PD_DET_EN_SHIFT; | ||
710 | |||
711 | writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN); | ||
712 | writel(con, data->base + EXYNOS_TMU_REG_CONTROL); | ||
713 | } | ||
714 | |||
576 | static int exynos_get_temp(void *p, long *temp) | 715 | static int exynos_get_temp(void *p, long *temp) |
577 | { | 716 | { |
578 | struct exynos_tmu_data *data = p; | 717 | struct exynos_tmu_data *data = p; |
@@ -602,9 +741,19 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val, | |||
602 | val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT); | 741 | val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT); |
603 | val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT); | 742 | val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT); |
604 | } | 743 | } |
605 | val &= ~(EXYNOS_EMUL_DATA_MASK << EXYNOS_EMUL_DATA_SHIFT); | 744 | if (data->soc == SOC_ARCH_EXYNOS7) { |
606 | val |= (temp_to_code(data, temp) << EXYNOS_EMUL_DATA_SHIFT) | | 745 | val &= ~(EXYNOS7_EMUL_DATA_MASK << |
607 | EXYNOS_EMUL_ENABLE; | 746 | EXYNOS7_EMUL_DATA_SHIFT); |
747 | val |= (temp_to_code(data, temp) << | ||
748 | EXYNOS7_EMUL_DATA_SHIFT) | | ||
749 | EXYNOS_EMUL_ENABLE; | ||
750 | } else { | ||
751 | val &= ~(EXYNOS_EMUL_DATA_MASK << | ||
752 | EXYNOS_EMUL_DATA_SHIFT); | ||
753 | val |= (temp_to_code(data, temp) << | ||
754 | EXYNOS_EMUL_DATA_SHIFT) | | ||
755 | EXYNOS_EMUL_ENABLE; | ||
756 | } | ||
608 | } else { | 757 | } else { |
609 | val &= ~EXYNOS_EMUL_ENABLE; | 758 | val &= ~EXYNOS_EMUL_ENABLE; |
610 | } | 759 | } |
@@ -620,6 +769,8 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data, | |||
620 | 769 | ||
621 | if (data->soc == SOC_ARCH_EXYNOS5260) | 770 | if (data->soc == SOC_ARCH_EXYNOS5260) |
622 | emul_con = EXYNOS5260_EMUL_CON; | 771 | emul_con = EXYNOS5260_EMUL_CON; |
772 | else if (data->soc == SOC_ARCH_EXYNOS7) | ||
773 | emul_con = EXYNOS7_TMU_REG_EMUL_CON; | ||
623 | else | 774 | else |
624 | emul_con = EXYNOS_EMUL_CON; | 775 | emul_con = EXYNOS_EMUL_CON; |
625 | 776 | ||
@@ -683,6 +834,12 @@ static int exynos5440_tmu_read(struct exynos_tmu_data *data) | |||
683 | return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP); | 834 | return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP); |
684 | } | 835 | } |
685 | 836 | ||
837 | static int exynos7_tmu_read(struct exynos_tmu_data *data) | ||
838 | { | ||
839 | return readw(data->base + EXYNOS_TMU_REG_CURRENT_TEMP) & | ||
840 | EXYNOS7_TMU_TEMP_MASK; | ||
841 | } | ||
842 | |||
686 | static void exynos_tmu_work(struct work_struct *work) | 843 | static void exynos_tmu_work(struct work_struct *work) |
687 | { | 844 | { |
688 | struct exynos_tmu_data *data = container_of(work, | 845 | struct exynos_tmu_data *data = container_of(work, |
@@ -721,6 +878,9 @@ static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data) | |||
721 | if (data->soc == SOC_ARCH_EXYNOS5260) { | 878 | if (data->soc == SOC_ARCH_EXYNOS5260) { |
722 | tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT; | 879 | tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT; |
723 | tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR; | 880 | tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR; |
881 | } else if (data->soc == SOC_ARCH_EXYNOS7) { | ||
882 | tmu_intstat = EXYNOS7_TMU_REG_INTPEND; | ||
883 | tmu_intclear = EXYNOS7_TMU_REG_INTPEND; | ||
724 | } else { | 884 | } else { |
725 | tmu_intstat = EXYNOS_TMU_REG_INTSTAT; | 885 | tmu_intstat = EXYNOS_TMU_REG_INTSTAT; |
726 | tmu_intclear = EXYNOS_TMU_REG_INTCLEAR; | 886 | tmu_intclear = EXYNOS_TMU_REG_INTCLEAR; |
@@ -782,6 +942,9 @@ static const struct of_device_id exynos_tmu_match[] = { | |||
782 | { | 942 | { |
783 | .compatible = "samsung,exynos5440-tmu", | 943 | .compatible = "samsung,exynos5440-tmu", |
784 | }, | 944 | }, |
945 | { | ||
946 | .compatible = "samsung,exynos7-tmu", | ||
947 | }, | ||
785 | {}, | 948 | {}, |
786 | }; | 949 | }; |
787 | MODULE_DEVICE_TABLE(of, exynos_tmu_match); | 950 | MODULE_DEVICE_TABLE(of, exynos_tmu_match); |
@@ -805,6 +968,8 @@ static int exynos_of_get_soc_type(struct device_node *np) | |||
805 | return SOC_ARCH_EXYNOS5420_TRIMINFO; | 968 | return SOC_ARCH_EXYNOS5420_TRIMINFO; |
806 | else if (of_device_is_compatible(np, "samsung,exynos5440-tmu")) | 969 | else if (of_device_is_compatible(np, "samsung,exynos5440-tmu")) |
807 | return SOC_ARCH_EXYNOS5440; | 970 | return SOC_ARCH_EXYNOS5440; |
971 | else if (of_device_is_compatible(np, "samsung,exynos7-tmu")) | ||
972 | return SOC_ARCH_EXYNOS7; | ||
808 | 973 | ||
809 | return -EINVAL; | 974 | return -EINVAL; |
810 | } | 975 | } |
@@ -928,6 +1093,13 @@ static int exynos_map_dt_data(struct platform_device *pdev) | |||
928 | data->tmu_set_emulation = exynos5440_tmu_set_emulation; | 1093 | data->tmu_set_emulation = exynos5440_tmu_set_emulation; |
929 | data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; | 1094 | data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; |
930 | break; | 1095 | break; |
1096 | case SOC_ARCH_EXYNOS7: | ||
1097 | data->tmu_initialize = exynos7_tmu_initialize; | ||
1098 | data->tmu_control = exynos7_tmu_control; | ||
1099 | data->tmu_read = exynos7_tmu_read; | ||
1100 | data->tmu_set_emulation = exynos4412_tmu_set_emulation; | ||
1101 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; | ||
1102 | break; | ||
931 | default: | 1103 | default: |
932 | dev_err(&pdev->dev, "Platform not supported\n"); | 1104 | dev_err(&pdev->dev, "Platform not supported\n"); |
933 | return -EINVAL; | 1105 | return -EINVAL; |
@@ -1017,21 +1189,37 @@ static int exynos_tmu_probe(struct platform_device *pdev) | |||
1017 | goto err_clk_sec; | 1189 | goto err_clk_sec; |
1018 | } | 1190 | } |
1019 | 1191 | ||
1192 | if (data->soc == SOC_ARCH_EXYNOS7) { | ||
1193 | data->sclk = devm_clk_get(&pdev->dev, "tmu_sclk"); | ||
1194 | if (IS_ERR(data->sclk)) { | ||
1195 | dev_err(&pdev->dev, "Failed to get sclk\n"); | ||
1196 | goto err_clk; | ||
1197 | } else { | ||
1198 | ret = clk_prepare_enable(data->sclk); | ||
1199 | if (ret) { | ||
1200 | dev_err(&pdev->dev, "Failed to enable sclk\n"); | ||
1201 | goto err_clk; | ||
1202 | } | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1020 | ret = exynos_tmu_initialize(pdev); | 1206 | ret = exynos_tmu_initialize(pdev); |
1021 | if (ret) { | 1207 | if (ret) { |
1022 | dev_err(&pdev->dev, "Failed to initialize TMU\n"); | 1208 | dev_err(&pdev->dev, "Failed to initialize TMU\n"); |
1023 | goto err_clk; | 1209 | goto err_sclk; |
1024 | } | 1210 | } |
1025 | 1211 | ||
1026 | ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq, | 1212 | ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq, |
1027 | IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data); | 1213 | IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data); |
1028 | if (ret) { | 1214 | if (ret) { |
1029 | dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq); | 1215 | dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq); |
1030 | goto err_clk; | 1216 | goto err_sclk; |
1031 | } | 1217 | } |
1032 | 1218 | ||
1033 | exynos_tmu_control(pdev, true); | 1219 | exynos_tmu_control(pdev, true); |
1034 | return 0; | 1220 | return 0; |
1221 | err_sclk: | ||
1222 | clk_disable_unprepare(data->sclk); | ||
1035 | err_clk: | 1223 | err_clk: |
1036 | clk_unprepare(data->clk); | 1224 | clk_unprepare(data->clk); |
1037 | err_clk_sec: | 1225 | err_clk_sec: |
@@ -1051,6 +1239,7 @@ static int exynos_tmu_remove(struct platform_device *pdev) | |||
1051 | thermal_zone_of_sensor_unregister(&pdev->dev, tzd); | 1239 | thermal_zone_of_sensor_unregister(&pdev->dev, tzd); |
1052 | exynos_tmu_control(pdev, false); | 1240 | exynos_tmu_control(pdev, false); |
1053 | 1241 | ||
1242 | clk_disable_unprepare(data->sclk); | ||
1054 | clk_unprepare(data->clk); | 1243 | clk_unprepare(data->clk); |
1055 | if (!IS_ERR(data->clk_sec)) | 1244 | if (!IS_ERR(data->clk_sec)) |
1056 | clk_unprepare(data->clk_sec); | 1245 | clk_unprepare(data->clk_sec); |
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index 9f9b1b810269..4d71ec6c9aa0 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h | |||
@@ -34,6 +34,7 @@ enum soc_type { | |||
34 | SOC_ARCH_EXYNOS5420, | 34 | SOC_ARCH_EXYNOS5420, |
35 | SOC_ARCH_EXYNOS5420_TRIMINFO, | 35 | SOC_ARCH_EXYNOS5420_TRIMINFO, |
36 | SOC_ARCH_EXYNOS5440, | 36 | SOC_ARCH_EXYNOS5440, |
37 | SOC_ARCH_EXYNOS7, | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | /** | 40 | /** |