diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-12 16:23:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-12 16:23:51 -0400 |
commit | 19785cf93b6c4252981894394f2dbd35c5e5d1ec (patch) | |
tree | 837d86ff16a56bd681974f933813937985225277 | |
parent | 98db5e5503c21c27705c49ebda782b4252b5f7a7 (diff) | |
parent | 6d7c70d1cd6526dc79e3d3b3faae1c40c1681168 (diff) |
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal
Pull thermal SoC updates from Zhang Rui:
"Thermal SoC management updates:
- imx thermal driver now supports i.MX7 thermal sensor (Anson Huang)
- exynos thermal driver dropped support for exynos 5440 (Krzysztof
Kozlowski)
- rcar_thermal now supports r8a77995 (Yoshihiro Kaneko)
- rcar_gen3_thermal now supports r8a77965 (Niklas Söderlund)
- qcom-spmi-temp-alarm now supports GEN2 PMIC peripherals (David
Collins)
- uniphier thermal now supports UniPhier PXs3 (Kunihiko Hayashi)
- mediatek thermal now supports MT7622 SoC (Sean Wang)
- considerable refactoring of exynos driver (Bartlomiej
Zolnierkiewicz)
- small fixes all over the place on different drivers"
* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal: (50 commits)
thermal: qcom: tsens: Allow number of sensors to come from DT
thermal: tegra: soctherm: add const to struct thermal_cooling_device_ops
thermal: exynos: Reduce severity of too early temperature read
thermal: imx: Switch to SPDX identifier
thermal: qcom-spmi-temp-alarm: add support for GEN2 PMIC peripherals
thermal: ti-soc-thermal: fix incorrect entry in omap5430_adc_to_temp[]
thermal: rcar_thermal: add r8a77995 support
dt-bindings: thermal: rcar-thermal: add R8A77995 support
thermal: mediatek: use of_device_get_match_data()
thermal: exynos: remove trip reporting to user-space
thermal: exynos: remove unused defines for Exynos5433
thermal: exynos: cleanup code for enabling threshold interrupts
thermal: exynos: check return values of ->get_trip_[temp, hyst] methods
thermal: exynos: move trips setting to exynos_tmu_initialize()
thermal: exynos: set trips in ascending order in exynos7_tmu_initialize()
thermal: exynos: do not use trips structure directly in ->tmu_initialize
thermal: exynos: add exynos*_tmu_set_[trip,hyst]() helpers
thermal: exynos: move IRQs clearing to exynos_tmu_initialize()
thermal: exynos: clear IRQs later in exynos4412_tmu_initialize()
thermal: exynos: make ->tmu_initialize method void
...
18 files changed, 851 insertions, 881 deletions
diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt index b957acff57aa..ad648d93d961 100644 --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt | |||
@@ -12,7 +12,6 @@ | |||
12 | "samsung,exynos5420-tmu-ext-triminfo" for TMU channels 2, 3 and 4 | 12 | "samsung,exynos5420-tmu-ext-triminfo" for TMU channels 2, 3 and 4 |
13 | Exynos5420 (Must pass triminfo base and triminfo clock) | 13 | Exynos5420 (Must pass triminfo base and triminfo clock) |
14 | "samsung,exynos5433-tmu" | 14 | "samsung,exynos5433-tmu" |
15 | "samsung,exynos5440-tmu" | ||
16 | "samsung,exynos7-tmu" | 15 | "samsung,exynos7-tmu" |
17 | - interrupt-parent : The phandle for the interrupt controller | 16 | - interrupt-parent : The phandle for the interrupt controller |
18 | - reg : Address range of the thermal registers. For soc's which has multiple | 17 | - reg : Address range of the thermal registers. For soc's which has multiple |
@@ -68,18 +67,7 @@ Example 1): | |||
68 | #thermal-sensor-cells = <0>; | 67 | #thermal-sensor-cells = <0>; |
69 | }; | 68 | }; |
70 | 69 | ||
71 | Example 2): | 70 | Example 2): (In case of Exynos5420 "with misplaced TRIMINFO register") |
72 | |||
73 | tmuctrl_0: tmuctrl@160118 { | ||
74 | compatible = "samsung,exynos5440-tmu"; | ||
75 | reg = <0x160118 0x230>, <0x160368 0x10>; | ||
76 | interrupts = <0 58 0>; | ||
77 | clocks = <&clock 21>; | ||
78 | clock-names = "tmu_apbif"; | ||
79 | #thermal-sensor-cells = <0>; | ||
80 | }; | ||
81 | |||
82 | Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register") | ||
83 | tmu_cpu2: tmu@10068000 { | 71 | tmu_cpu2: tmu@10068000 { |
84 | compatible = "samsung,exynos5420-tmu-ext-triminfo"; | 72 | compatible = "samsung,exynos5420-tmu-ext-triminfo"; |
85 | reg = <0x10068000 0x100>, <0x1006c000 0x4>; | 73 | reg = <0x10068000 0x100>, <0x1006c000 0x4>; |
diff --git a/Documentation/devicetree/bindings/thermal/imx-thermal.txt b/Documentation/devicetree/bindings/thermal/imx-thermal.txt index 379eb763073e..823e4176eef8 100644 --- a/Documentation/devicetree/bindings/thermal/imx-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/imx-thermal.txt | |||
@@ -1,8 +1,13 @@ | |||
1 | * Temperature Monitor (TEMPMON) on Freescale i.MX SoCs | 1 | * Temperature Monitor (TEMPMON) on Freescale i.MX SoCs |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible : "fsl,imx6q-tempmon" for i.MX6Q, "fsl,imx6sx-tempmon" for i.MX6SX. | 4 | - compatible : must be one of following: |
5 | i.MX6SX has two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC, | 5 | - "fsl,imx6q-tempmon" for i.MX6Q, |
6 | - "fsl,imx6sx-tempmon" for i.MX6SX, | ||
7 | - "fsl,imx7d-tempmon" for i.MX7S/D. | ||
8 | - interrupts : the interrupt output of the controller: | ||
9 | i.MX6Q has one IRQ which will be triggered when temperature is higher than high threshold, | ||
10 | i.MX6SX and i.MX7S/D have two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC, | ||
6 | when temperature is below than low threshold, IRQ_LOW will be triggered, when temperature | 11 | when temperature is below than low threshold, IRQ_LOW will be triggered, when temperature |
7 | is higher than panic threshold, system will auto reboot by SRC module. | 12 | is higher than panic threshold, system will auto reboot by SRC module. |
8 | - fsl,tempmon : phandle pointer to system controller that contains TEMPMON | 13 | - fsl,tempmon : phandle pointer to system controller that contains TEMPMON |
diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt index 0d73ea5e9c0c..41d6a443ad66 100644 --- a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt | |||
@@ -12,6 +12,7 @@ Required properties: | |||
12 | - "mediatek,mt8173-thermal" : For MT8173 family of SoCs | 12 | - "mediatek,mt8173-thermal" : For MT8173 family of SoCs |
13 | - "mediatek,mt2701-thermal" : For MT2701 family of SoCs | 13 | - "mediatek,mt2701-thermal" : For MT2701 family of SoCs |
14 | - "mediatek,mt2712-thermal" : For MT2712 family of SoCs | 14 | - "mediatek,mt2712-thermal" : For MT2712 family of SoCs |
15 | - "mediatek,mt7622-thermal" : For MT7622 SoC | ||
15 | - reg: Address range of the thermal controller | 16 | - reg: Address range of the thermal controller |
16 | - interrupts: IRQ for the thermal controller | 17 | - interrupts: IRQ for the thermal controller |
17 | - clocks, clock-names: Clocks needed for the thermal controller. required | 18 | - clocks, clock-names: Clocks needed for the thermal controller. required |
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt index 292ed89d900b..06195e8f35e2 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt | |||
@@ -8,6 +8,7 @@ Required properties: | |||
8 | 8 | ||
9 | - reg: Address range of the thermal registers | 9 | - reg: Address range of the thermal registers |
10 | - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description. | 10 | - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description. |
11 | - #qcom,sensors: Number of sensors in tsens block | ||
11 | - Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify | 12 | - Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify |
12 | nvmem cells | 13 | nvmem cells |
13 | 14 | ||
diff --git a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt index 39e7d4e61a63..cfa154bb0fa7 100644 --- a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt | |||
@@ -9,6 +9,7 @@ Required properties: | |||
9 | Examples with soctypes are: | 9 | Examples with soctypes are: |
10 | - "renesas,r8a7795-thermal" (R-Car H3) | 10 | - "renesas,r8a7795-thermal" (R-Car H3) |
11 | - "renesas,r8a7796-thermal" (R-Car M3-W) | 11 | - "renesas,r8a7796-thermal" (R-Car M3-W) |
12 | - "renesas,r8a77965-thermal" (R-Car M3-N) | ||
12 | - reg : Address ranges of the thermal registers. Each sensor | 13 | - reg : Address ranges of the thermal registers. Each sensor |
13 | needs one address range. Sorting must be done in | 14 | needs one address range. Sorting must be done in |
14 | increasing order according to datasheet, i.e. | 15 | increasing order according to datasheet, i.e. |
@@ -18,7 +19,7 @@ Required properties: | |||
18 | 19 | ||
19 | Optional properties: | 20 | Optional properties: |
20 | 21 | ||
21 | - interrupts : interrupts routed to the TSC (3 for H3 and M3-W) | 22 | - interrupts : interrupts routed to the TSC (3 for H3, M3-W and M3-N) |
22 | - power-domain : Must contain a reference to the power domain. This | 23 | - power-domain : Must contain a reference to the power domain. This |
23 | property is mandatory if the thermal sensor instance | 24 | property is mandatory if the thermal sensor instance |
24 | is part of a controllable power domain. | 25 | is part of a controllable power domain. |
diff --git a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt index 349e635f2d87..67c563f1b4c4 100644 --- a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt | |||
@@ -3,7 +3,8 @@ | |||
3 | Required properties: | 3 | Required properties: |
4 | - compatible : "renesas,thermal-<soctype>", | 4 | - compatible : "renesas,thermal-<soctype>", |
5 | "renesas,rcar-gen2-thermal" (with thermal-zone) or | 5 | "renesas,rcar-gen2-thermal" (with thermal-zone) or |
6 | "renesas,rcar-thermal" (without thermal-zone) as fallback. | 6 | "renesas,rcar-thermal" (without thermal-zone) as |
7 | fallback except R-Car D3. | ||
7 | Examples with soctypes are: | 8 | Examples with soctypes are: |
8 | - "renesas,thermal-r8a73a4" (R-Mobile APE6) | 9 | - "renesas,thermal-r8a73a4" (R-Mobile APE6) |
9 | - "renesas,thermal-r8a7743" (RZ/G1M) | 10 | - "renesas,thermal-r8a7743" (RZ/G1M) |
@@ -12,13 +13,15 @@ Required properties: | |||
12 | - "renesas,thermal-r8a7791" (R-Car M2-W) | 13 | - "renesas,thermal-r8a7791" (R-Car M2-W) |
13 | - "renesas,thermal-r8a7792" (R-Car V2H) | 14 | - "renesas,thermal-r8a7792" (R-Car V2H) |
14 | - "renesas,thermal-r8a7793" (R-Car M2-N) | 15 | - "renesas,thermal-r8a7793" (R-Car M2-N) |
16 | - "renesas,thermal-r8a77995" (R-Car D3) | ||
15 | - reg : Address range of the thermal registers. | 17 | - reg : Address range of the thermal registers. |
16 | The 1st reg will be recognized as common register | 18 | The 1st reg will be recognized as common register |
17 | if it has "interrupts". | 19 | if it has "interrupts". |
18 | 20 | ||
19 | Option properties: | 21 | Option properties: |
20 | 22 | ||
21 | - interrupts : use interrupt | 23 | - interrupts : If present should contain 3 interrupts for |
24 | R-Car D3 or 1 interrupt otherwise. | ||
22 | 25 | ||
23 | Example (non interrupt support): | 26 | Example (non interrupt support): |
24 | 27 | ||
diff --git a/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt b/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt index 686c0b42ed3f..ceb92a95727a 100644 --- a/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt | |||
@@ -8,6 +8,7 @@ Required properties: | |||
8 | - compatible : | 8 | - compatible : |
9 | - "socionext,uniphier-pxs2-thermal" : For UniPhier PXs2 SoC | 9 | - "socionext,uniphier-pxs2-thermal" : For UniPhier PXs2 SoC |
10 | - "socionext,uniphier-ld20-thermal" : For UniPhier LD20 SoC | 10 | - "socionext,uniphier-ld20-thermal" : For UniPhier LD20 SoC |
11 | - "socionext,uniphier-pxs3-thermal" : For UniPhier PXs3 SoC | ||
11 | - interrupts : IRQ for the temperature alarm | 12 | - interrupts : IRQ for the temperature alarm |
12 | - #thermal-sensor-cells : Should be 0. See ./thermal.txt for details. | 13 | - #thermal-sensor-cells : Should be 0. See ./thermal.txt for details. |
13 | 14 | ||
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index ee3a215b333a..334d98be03b9 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c | |||
@@ -1,11 +1,6 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * Copyright 2013 Freescale Semiconductor, Inc. | 2 | // |
3 | * | 3 | // Copyright 2013 Freescale Semiconductor, Inc. |
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | */ | ||
9 | 4 | ||
10 | #include <linux/clk.h> | 5 | #include <linux/clk.h> |
11 | #include <linux/cpufreq.h> | 6 | #include <linux/cpufreq.h> |
@@ -31,35 +26,57 @@ | |||
31 | #define REG_CLR 0x8 | 26 | #define REG_CLR 0x8 |
32 | #define REG_TOG 0xc | 27 | #define REG_TOG 0xc |
33 | 28 | ||
34 | #define MISC0 0x0150 | 29 | /* i.MX6 specific */ |
35 | #define MISC0_REFTOP_SELBIASOFF (1 << 3) | 30 | #define IMX6_MISC0 0x0150 |
36 | #define MISC1 0x0160 | 31 | #define IMX6_MISC0_REFTOP_SELBIASOFF (1 << 3) |
37 | #define MISC1_IRQ_TEMPHIGH (1 << 29) | 32 | #define IMX6_MISC1 0x0160 |
33 | #define IMX6_MISC1_IRQ_TEMPHIGH (1 << 29) | ||
38 | /* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */ | 34 | /* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */ |
39 | #define MISC1_IRQ_TEMPLOW (1 << 28) | 35 | #define IMX6_MISC1_IRQ_TEMPLOW (1 << 28) |
40 | #define MISC1_IRQ_TEMPPANIC (1 << 27) | 36 | #define IMX6_MISC1_IRQ_TEMPPANIC (1 << 27) |
41 | 37 | ||
42 | #define TEMPSENSE0 0x0180 | 38 | #define IMX6_TEMPSENSE0 0x0180 |
43 | #define TEMPSENSE0_ALARM_VALUE_SHIFT 20 | 39 | #define IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT 20 |
44 | #define TEMPSENSE0_ALARM_VALUE_MASK (0xfff << TEMPSENSE0_ALARM_VALUE_SHIFT) | 40 | #define IMX6_TEMPSENSE0_ALARM_VALUE_MASK (0xfff << 20) |
45 | #define TEMPSENSE0_TEMP_CNT_SHIFT 8 | 41 | #define IMX6_TEMPSENSE0_TEMP_CNT_SHIFT 8 |
46 | #define TEMPSENSE0_TEMP_CNT_MASK (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT) | 42 | #define IMX6_TEMPSENSE0_TEMP_CNT_MASK (0xfff << 8) |
47 | #define TEMPSENSE0_FINISHED (1 << 2) | 43 | #define IMX6_TEMPSENSE0_FINISHED (1 << 2) |
48 | #define TEMPSENSE0_MEASURE_TEMP (1 << 1) | 44 | #define IMX6_TEMPSENSE0_MEASURE_TEMP (1 << 1) |
49 | #define TEMPSENSE0_POWER_DOWN (1 << 0) | 45 | #define IMX6_TEMPSENSE0_POWER_DOWN (1 << 0) |
50 | 46 | ||
51 | #define TEMPSENSE1 0x0190 | 47 | #define IMX6_TEMPSENSE1 0x0190 |
52 | #define TEMPSENSE1_MEASURE_FREQ 0xffff | 48 | #define IMX6_TEMPSENSE1_MEASURE_FREQ 0xffff |
53 | /* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */ | 49 | #define IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT 0 |
54 | #define TEMPSENSE2 0x0290 | ||
55 | #define TEMPSENSE2_LOW_VALUE_SHIFT 0 | ||
56 | #define TEMPSENSE2_LOW_VALUE_MASK 0xfff | ||
57 | #define TEMPSENSE2_PANIC_VALUE_SHIFT 16 | ||
58 | #define TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000 | ||
59 | 50 | ||
60 | #define OCOTP_MEM0 0x0480 | 51 | #define OCOTP_MEM0 0x0480 |
61 | #define OCOTP_ANA1 0x04e0 | 52 | #define OCOTP_ANA1 0x04e0 |
62 | 53 | ||
54 | /* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */ | ||
55 | #define IMX6_TEMPSENSE2 0x0290 | ||
56 | #define IMX6_TEMPSENSE2_LOW_VALUE_SHIFT 0 | ||
57 | #define IMX6_TEMPSENSE2_LOW_VALUE_MASK 0xfff | ||
58 | #define IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT 16 | ||
59 | #define IMX6_TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000 | ||
60 | |||
61 | /* i.MX7 specific */ | ||
62 | #define IMX7_ANADIG_DIGPROG 0x800 | ||
63 | #define IMX7_TEMPSENSE0 0x300 | ||
64 | #define IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT 18 | ||
65 | #define IMX7_TEMPSENSE0_PANIC_ALARM_MASK (0x1ff << 18) | ||
66 | #define IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT 9 | ||
67 | #define IMX7_TEMPSENSE0_HIGH_ALARM_MASK (0x1ff << 9) | ||
68 | #define IMX7_TEMPSENSE0_LOW_ALARM_SHIFT 0 | ||
69 | #define IMX7_TEMPSENSE0_LOW_ALARM_MASK 0x1ff | ||
70 | |||
71 | #define IMX7_TEMPSENSE1 0x310 | ||
72 | #define IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT 16 | ||
73 | #define IMX7_TEMPSENSE1_MEASURE_FREQ_MASK (0xffff << 16) | ||
74 | #define IMX7_TEMPSENSE1_FINISHED (1 << 11) | ||
75 | #define IMX7_TEMPSENSE1_MEASURE_TEMP (1 << 10) | ||
76 | #define IMX7_TEMPSENSE1_POWER_DOWN (1 << 9) | ||
77 | #define IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT 0 | ||
78 | #define IMX7_TEMPSENSE1_TEMP_VALUE_MASK 0x1ff | ||
79 | |||
63 | /* The driver supports 1 passive trip point and 1 critical trip point */ | 80 | /* The driver supports 1 passive trip point and 1 critical trip point */ |
64 | enum imx_thermal_trip { | 81 | enum imx_thermal_trip { |
65 | IMX_TRIP_PASSIVE, | 82 | IMX_TRIP_PASSIVE, |
@@ -72,17 +89,114 @@ enum imx_thermal_trip { | |||
72 | 89 | ||
73 | #define TEMPMON_IMX6Q 1 | 90 | #define TEMPMON_IMX6Q 1 |
74 | #define TEMPMON_IMX6SX 2 | 91 | #define TEMPMON_IMX6SX 2 |
92 | #define TEMPMON_IMX7D 3 | ||
75 | 93 | ||
76 | struct thermal_soc_data { | 94 | struct thermal_soc_data { |
77 | u32 version; | 95 | u32 version; |
96 | |||
97 | u32 sensor_ctrl; | ||
98 | u32 power_down_mask; | ||
99 | u32 measure_temp_mask; | ||
100 | |||
101 | u32 measure_freq_ctrl; | ||
102 | u32 measure_freq_mask; | ||
103 | u32 measure_freq_shift; | ||
104 | |||
105 | u32 temp_data; | ||
106 | u32 temp_value_mask; | ||
107 | u32 temp_value_shift; | ||
108 | u32 temp_valid_mask; | ||
109 | |||
110 | u32 panic_alarm_ctrl; | ||
111 | u32 panic_alarm_mask; | ||
112 | u32 panic_alarm_shift; | ||
113 | |||
114 | u32 high_alarm_ctrl; | ||
115 | u32 high_alarm_mask; | ||
116 | u32 high_alarm_shift; | ||
117 | |||
118 | u32 low_alarm_ctrl; | ||
119 | u32 low_alarm_mask; | ||
120 | u32 low_alarm_shift; | ||
78 | }; | 121 | }; |
79 | 122 | ||
80 | static struct thermal_soc_data thermal_imx6q_data = { | 123 | static struct thermal_soc_data thermal_imx6q_data = { |
81 | .version = TEMPMON_IMX6Q, | 124 | .version = TEMPMON_IMX6Q, |
125 | |||
126 | .sensor_ctrl = IMX6_TEMPSENSE0, | ||
127 | .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN, | ||
128 | .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP, | ||
129 | |||
130 | .measure_freq_ctrl = IMX6_TEMPSENSE1, | ||
131 | .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT, | ||
132 | .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ, | ||
133 | |||
134 | .temp_data = IMX6_TEMPSENSE0, | ||
135 | .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK, | ||
136 | .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT, | ||
137 | .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED, | ||
138 | |||
139 | .high_alarm_ctrl = IMX6_TEMPSENSE0, | ||
140 | .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK, | ||
141 | .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT, | ||
82 | }; | 142 | }; |
83 | 143 | ||
84 | static struct thermal_soc_data thermal_imx6sx_data = { | 144 | static struct thermal_soc_data thermal_imx6sx_data = { |
85 | .version = TEMPMON_IMX6SX, | 145 | .version = TEMPMON_IMX6SX, |
146 | |||
147 | .sensor_ctrl = IMX6_TEMPSENSE0, | ||
148 | .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN, | ||
149 | .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP, | ||
150 | |||
151 | .measure_freq_ctrl = IMX6_TEMPSENSE1, | ||
152 | .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT, | ||
153 | .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ, | ||
154 | |||
155 | .temp_data = IMX6_TEMPSENSE0, | ||
156 | .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK, | ||
157 | .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT, | ||
158 | .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED, | ||
159 | |||
160 | .high_alarm_ctrl = IMX6_TEMPSENSE0, | ||
161 | .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK, | ||
162 | .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT, | ||
163 | |||
164 | .panic_alarm_ctrl = IMX6_TEMPSENSE2, | ||
165 | .panic_alarm_mask = IMX6_TEMPSENSE2_PANIC_VALUE_MASK, | ||
166 | .panic_alarm_shift = IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT, | ||
167 | |||
168 | .low_alarm_ctrl = IMX6_TEMPSENSE2, | ||
169 | .low_alarm_mask = IMX6_TEMPSENSE2_LOW_VALUE_MASK, | ||
170 | .low_alarm_shift = IMX6_TEMPSENSE2_LOW_VALUE_SHIFT, | ||
171 | }; | ||
172 | |||
173 | static struct thermal_soc_data thermal_imx7d_data = { | ||
174 | .version = TEMPMON_IMX7D, | ||
175 | |||
176 | .sensor_ctrl = IMX7_TEMPSENSE1, | ||
177 | .power_down_mask = IMX7_TEMPSENSE1_POWER_DOWN, | ||
178 | .measure_temp_mask = IMX7_TEMPSENSE1_MEASURE_TEMP, | ||
179 | |||
180 | .measure_freq_ctrl = IMX7_TEMPSENSE1, | ||
181 | .measure_freq_shift = IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT, | ||
182 | .measure_freq_mask = IMX7_TEMPSENSE1_MEASURE_FREQ_MASK, | ||
183 | |||
184 | .temp_data = IMX7_TEMPSENSE1, | ||
185 | .temp_value_mask = IMX7_TEMPSENSE1_TEMP_VALUE_MASK, | ||
186 | .temp_value_shift = IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT, | ||
187 | .temp_valid_mask = IMX7_TEMPSENSE1_FINISHED, | ||
188 | |||
189 | .panic_alarm_ctrl = IMX7_TEMPSENSE1, | ||
190 | .panic_alarm_mask = IMX7_TEMPSENSE0_PANIC_ALARM_MASK, | ||
191 | .panic_alarm_shift = IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT, | ||
192 | |||
193 | .high_alarm_ctrl = IMX7_TEMPSENSE0, | ||
194 | .high_alarm_mask = IMX7_TEMPSENSE0_HIGH_ALARM_MASK, | ||
195 | .high_alarm_shift = IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT, | ||
196 | |||
197 | .low_alarm_ctrl = IMX7_TEMPSENSE0, | ||
198 | .low_alarm_mask = IMX7_TEMPSENSE0_LOW_ALARM_MASK, | ||
199 | .low_alarm_shift = IMX7_TEMPSENSE0_LOW_ALARM_SHIFT, | ||
86 | }; | 200 | }; |
87 | 201 | ||
88 | struct imx_thermal_data { | 202 | struct imx_thermal_data { |
@@ -107,31 +221,42 @@ struct imx_thermal_data { | |||
107 | static void imx_set_panic_temp(struct imx_thermal_data *data, | 221 | static void imx_set_panic_temp(struct imx_thermal_data *data, |
108 | int panic_temp) | 222 | int panic_temp) |
109 | { | 223 | { |
224 | const struct thermal_soc_data *soc_data = data->socdata; | ||
110 | struct regmap *map = data->tempmon; | 225 | struct regmap *map = data->tempmon; |
111 | int critical_value; | 226 | int critical_value; |
112 | 227 | ||
113 | critical_value = (data->c2 - panic_temp) / data->c1; | 228 | critical_value = (data->c2 - panic_temp) / data->c1; |
114 | regmap_write(map, TEMPSENSE2 + REG_CLR, TEMPSENSE2_PANIC_VALUE_MASK); | 229 | |
115 | regmap_write(map, TEMPSENSE2 + REG_SET, critical_value << | 230 | regmap_write(map, soc_data->panic_alarm_ctrl + REG_CLR, |
116 | TEMPSENSE2_PANIC_VALUE_SHIFT); | 231 | soc_data->panic_alarm_mask); |
232 | regmap_write(map, soc_data->panic_alarm_ctrl + REG_SET, | ||
233 | critical_value << soc_data->panic_alarm_shift); | ||
117 | } | 234 | } |
118 | 235 | ||
119 | static void imx_set_alarm_temp(struct imx_thermal_data *data, | 236 | static void imx_set_alarm_temp(struct imx_thermal_data *data, |
120 | int alarm_temp) | 237 | int alarm_temp) |
121 | { | 238 | { |
122 | struct regmap *map = data->tempmon; | 239 | struct regmap *map = data->tempmon; |
240 | const struct thermal_soc_data *soc_data = data->socdata; | ||
123 | int alarm_value; | 241 | int alarm_value; |
124 | 242 | ||
125 | data->alarm_temp = alarm_temp; | 243 | data->alarm_temp = alarm_temp; |
126 | alarm_value = (data->c2 - alarm_temp) / data->c1; | 244 | |
127 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK); | 245 | if (data->socdata->version == TEMPMON_IMX7D) |
128 | regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value << | 246 | alarm_value = alarm_temp / 1000 + data->c1 - 25; |
129 | TEMPSENSE0_ALARM_VALUE_SHIFT); | 247 | else |
248 | alarm_value = (data->c2 - alarm_temp) / data->c1; | ||
249 | |||
250 | regmap_write(map, soc_data->high_alarm_ctrl + REG_CLR, | ||
251 | soc_data->high_alarm_mask); | ||
252 | regmap_write(map, soc_data->high_alarm_ctrl + REG_SET, | ||
253 | alarm_value << soc_data->high_alarm_shift); | ||
130 | } | 254 | } |
131 | 255 | ||
132 | static int imx_get_temp(struct thermal_zone_device *tz, int *temp) | 256 | static int imx_get_temp(struct thermal_zone_device *tz, int *temp) |
133 | { | 257 | { |
134 | struct imx_thermal_data *data = tz->devdata; | 258 | struct imx_thermal_data *data = tz->devdata; |
259 | const struct thermal_soc_data *soc_data = data->socdata; | ||
135 | struct regmap *map = data->tempmon; | 260 | struct regmap *map = data->tempmon; |
136 | unsigned int n_meas; | 261 | unsigned int n_meas; |
137 | bool wait; | 262 | bool wait; |
@@ -139,16 +264,18 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) | |||
139 | 264 | ||
140 | if (data->mode == THERMAL_DEVICE_ENABLED) { | 265 | if (data->mode == THERMAL_DEVICE_ENABLED) { |
141 | /* Check if a measurement is currently in progress */ | 266 | /* Check if a measurement is currently in progress */ |
142 | regmap_read(map, TEMPSENSE0, &val); | 267 | regmap_read(map, soc_data->temp_data, &val); |
143 | wait = !(val & TEMPSENSE0_FINISHED); | 268 | wait = !(val & soc_data->temp_valid_mask); |
144 | } else { | 269 | } else { |
145 | /* | 270 | /* |
146 | * Every time we measure the temperature, we will power on the | 271 | * Every time we measure the temperature, we will power on the |
147 | * temperature sensor, enable measurements, take a reading, | 272 | * temperature sensor, enable measurements, take a reading, |
148 | * disable measurements, power off the temperature sensor. | 273 | * disable measurements, power off the temperature sensor. |
149 | */ | 274 | */ |
150 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); | 275 | regmap_write(map, soc_data->sensor_ctrl + REG_CLR, |
151 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); | 276 | soc_data->power_down_mask); |
277 | regmap_write(map, soc_data->sensor_ctrl + REG_SET, | ||
278 | soc_data->measure_temp_mask); | ||
152 | 279 | ||
153 | wait = true; | 280 | wait = true; |
154 | } | 281 | } |
@@ -160,22 +287,28 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) | |||
160 | if (wait) | 287 | if (wait) |
161 | usleep_range(20, 50); | 288 | usleep_range(20, 50); |
162 | 289 | ||
163 | regmap_read(map, TEMPSENSE0, &val); | 290 | regmap_read(map, soc_data->temp_data, &val); |
164 | 291 | ||
165 | if (data->mode != THERMAL_DEVICE_ENABLED) { | 292 | if (data->mode != THERMAL_DEVICE_ENABLED) { |
166 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP); | 293 | regmap_write(map, soc_data->sensor_ctrl + REG_CLR, |
167 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); | 294 | soc_data->measure_temp_mask); |
295 | regmap_write(map, soc_data->sensor_ctrl + REG_SET, | ||
296 | soc_data->power_down_mask); | ||
168 | } | 297 | } |
169 | 298 | ||
170 | if ((val & TEMPSENSE0_FINISHED) == 0) { | 299 | if ((val & soc_data->temp_valid_mask) == 0) { |
171 | dev_dbg(&tz->device, "temp measurement never finished\n"); | 300 | dev_dbg(&tz->device, "temp measurement never finished\n"); |
172 | return -EAGAIN; | 301 | return -EAGAIN; |
173 | } | 302 | } |
174 | 303 | ||
175 | n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT; | 304 | n_meas = (val & soc_data->temp_value_mask) |
305 | >> soc_data->temp_value_shift; | ||
176 | 306 | ||
177 | /* See imx_init_calib() for formula derivation */ | 307 | /* See imx_init_calib() for formula derivation */ |
178 | *temp = data->c2 - n_meas * data->c1; | 308 | if (data->socdata->version == TEMPMON_IMX7D) |
309 | *temp = (n_meas - data->c1 + 25) * 1000; | ||
310 | else | ||
311 | *temp = data->c2 - n_meas * data->c1; | ||
179 | 312 | ||
180 | /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */ | 313 | /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */ |
181 | if (data->socdata->version == TEMPMON_IMX6Q) { | 314 | if (data->socdata->version == TEMPMON_IMX6Q) { |
@@ -219,21 +352,26 @@ static int imx_set_mode(struct thermal_zone_device *tz, | |||
219 | { | 352 | { |
220 | struct imx_thermal_data *data = tz->devdata; | 353 | struct imx_thermal_data *data = tz->devdata; |
221 | struct regmap *map = data->tempmon; | 354 | struct regmap *map = data->tempmon; |
355 | const struct thermal_soc_data *soc_data = data->socdata; | ||
222 | 356 | ||
223 | if (mode == THERMAL_DEVICE_ENABLED) { | 357 | if (mode == THERMAL_DEVICE_ENABLED) { |
224 | tz->polling_delay = IMX_POLLING_DELAY; | 358 | tz->polling_delay = IMX_POLLING_DELAY; |
225 | tz->passive_delay = IMX_PASSIVE_DELAY; | 359 | tz->passive_delay = IMX_PASSIVE_DELAY; |
226 | 360 | ||
227 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); | 361 | regmap_write(map, soc_data->sensor_ctrl + REG_CLR, |
228 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); | 362 | soc_data->power_down_mask); |
363 | regmap_write(map, soc_data->sensor_ctrl + REG_SET, | ||
364 | soc_data->measure_temp_mask); | ||
229 | 365 | ||
230 | if (!data->irq_enabled) { | 366 | if (!data->irq_enabled) { |
231 | data->irq_enabled = true; | 367 | data->irq_enabled = true; |
232 | enable_irq(data->irq); | 368 | enable_irq(data->irq); |
233 | } | 369 | } |
234 | } else { | 370 | } else { |
235 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP); | 371 | regmap_write(map, soc_data->sensor_ctrl + REG_CLR, |
236 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); | 372 | soc_data->measure_temp_mask); |
373 | regmap_write(map, soc_data->sensor_ctrl + REG_SET, | ||
374 | soc_data->power_down_mask); | ||
237 | 375 | ||
238 | tz->polling_delay = 0; | 376 | tz->polling_delay = 0; |
239 | tz->passive_delay = 0; | 377 | tz->passive_delay = 0; |
@@ -355,6 +493,15 @@ static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1) | |||
355 | } | 493 | } |
356 | 494 | ||
357 | /* | 495 | /* |
496 | * On i.MX7D, we only use the calibration data at 25C to get the temp, | ||
497 | * Tmeas = ( Nmeas - n1) + 25; n1 is the fuse value for 25C. | ||
498 | */ | ||
499 | if (data->socdata->version == TEMPMON_IMX7D) { | ||
500 | data->c1 = (ocotp_ana1 >> 9) & 0x1ff; | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | /* | ||
358 | * The sensor is calibrated at 25 °C (aka T1) and the value measured | 505 | * The sensor is calibrated at 25 °C (aka T1) and the value measured |
359 | * (aka N1) at this temperature is provided in bits [31:20] in the | 506 | * (aka N1) at this temperature is provided in bits [31:20] in the |
360 | * i.MX's OCOTP value ANA1. | 507 | * i.MX's OCOTP value ANA1. |
@@ -492,6 +639,7 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev) | |||
492 | static const struct of_device_id of_imx_thermal_match[] = { | 639 | static const struct of_device_id of_imx_thermal_match[] = { |
493 | { .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, }, | 640 | { .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, }, |
494 | { .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, }, | 641 | { .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, }, |
642 | { .compatible = "fsl,imx7d-tempmon", .data = &thermal_imx7d_data, }, | ||
495 | { /* end */ } | 643 | { /* end */ } |
496 | }; | 644 | }; |
497 | MODULE_DEVICE_TABLE(of, of_imx_thermal_match); | 645 | MODULE_DEVICE_TABLE(of, of_imx_thermal_match); |
@@ -523,14 +671,15 @@ static int imx_thermal_probe(struct platform_device *pdev) | |||
523 | 671 | ||
524 | /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */ | 672 | /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */ |
525 | if (data->socdata->version == TEMPMON_IMX6SX) { | 673 | if (data->socdata->version == TEMPMON_IMX6SX) { |
526 | regmap_write(map, MISC1 + REG_CLR, MISC1_IRQ_TEMPHIGH | | 674 | regmap_write(map, IMX6_MISC1 + REG_CLR, |
527 | MISC1_IRQ_TEMPLOW | MISC1_IRQ_TEMPPANIC); | 675 | IMX6_MISC1_IRQ_TEMPHIGH | IMX6_MISC1_IRQ_TEMPLOW |
676 | | IMX6_MISC1_IRQ_TEMPPANIC); | ||
528 | /* | 677 | /* |
529 | * reset value of LOW ALARM is incorrect, set it to lowest | 678 | * reset value of LOW ALARM is incorrect, set it to lowest |
530 | * value to avoid false trigger of low alarm. | 679 | * value to avoid false trigger of low alarm. |
531 | */ | 680 | */ |
532 | regmap_write(map, TEMPSENSE2 + REG_SET, | 681 | regmap_write(map, data->socdata->low_alarm_ctrl + REG_SET, |
533 | TEMPSENSE2_LOW_VALUE_MASK); | 682 | data->socdata->low_alarm_mask); |
534 | } | 683 | } |
535 | 684 | ||
536 | data->irq = platform_get_irq(pdev, 0); | 685 | data->irq = platform_get_irq(pdev, 0); |
@@ -557,11 +706,17 @@ static int imx_thermal_probe(struct platform_device *pdev) | |||
557 | } | 706 | } |
558 | 707 | ||
559 | /* Make sure sensor is in known good state for measurements */ | 708 | /* Make sure sensor is in known good state for measurements */ |
560 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); | 709 | regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, |
561 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP); | 710 | data->socdata->power_down_mask); |
562 | regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ); | 711 | regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, |
563 | regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF); | 712 | data->socdata->measure_temp_mask); |
564 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); | 713 | regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR, |
714 | data->socdata->measure_freq_mask); | ||
715 | if (data->socdata->version != TEMPMON_IMX7D) | ||
716 | regmap_write(map, IMX6_MISC0 + REG_SET, | ||
717 | IMX6_MISC0_REFTOP_SELBIASOFF); | ||
718 | regmap_write(map, data->socdata->sensor_ctrl + REG_SET, | ||
719 | data->socdata->power_down_mask); | ||
565 | 720 | ||
566 | data->policy = cpufreq_cpu_get(0); | 721 | data->policy = cpufreq_cpu_get(0); |
567 | if (!data->policy) { | 722 | if (!data->policy) { |
@@ -626,16 +781,20 @@ static int imx_thermal_probe(struct platform_device *pdev) | |||
626 | data->temp_passive / 1000); | 781 | data->temp_passive / 1000); |
627 | 782 | ||
628 | /* Enable measurements at ~ 10 Hz */ | 783 | /* Enable measurements at ~ 10 Hz */ |
629 | regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ); | 784 | regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR, |
785 | data->socdata->measure_freq_mask); | ||
630 | measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */ | 786 | measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */ |
631 | regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq); | 787 | regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET, |
788 | measure_freq << data->socdata->measure_freq_shift); | ||
632 | imx_set_alarm_temp(data, data->temp_passive); | 789 | imx_set_alarm_temp(data, data->temp_passive); |
633 | 790 | ||
634 | if (data->socdata->version == TEMPMON_IMX6SX) | 791 | if (data->socdata->version == TEMPMON_IMX6SX) |
635 | imx_set_panic_temp(data, data->temp_critical); | 792 | imx_set_panic_temp(data, data->temp_critical); |
636 | 793 | ||
637 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); | 794 | regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, |
638 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); | 795 | data->socdata->power_down_mask); |
796 | regmap_write(map, data->socdata->sensor_ctrl + REG_SET, | ||
797 | data->socdata->measure_temp_mask); | ||
639 | 798 | ||
640 | data->irq_enabled = true; | 799 | data->irq_enabled = true; |
641 | data->mode = THERMAL_DEVICE_ENABLED; | 800 | data->mode = THERMAL_DEVICE_ENABLED; |
@@ -661,7 +820,8 @@ static int imx_thermal_remove(struct platform_device *pdev) | |||
661 | struct regmap *map = data->tempmon; | 820 | struct regmap *map = data->tempmon; |
662 | 821 | ||
663 | /* Disable measurements */ | 822 | /* Disable measurements */ |
664 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); | 823 | regmap_write(map, data->socdata->sensor_ctrl + REG_SET, |
824 | data->socdata->power_down_mask); | ||
665 | if (!IS_ERR(data->thermal_clk)) | 825 | if (!IS_ERR(data->thermal_clk)) |
666 | clk_disable_unprepare(data->thermal_clk); | 826 | clk_disable_unprepare(data->thermal_clk); |
667 | 827 | ||
@@ -684,8 +844,10 @@ static int imx_thermal_suspend(struct device *dev) | |||
684 | * temperature will be read as the thermal sensor is powered | 844 | * temperature will be read as the thermal sensor is powered |
685 | * down. | 845 | * down. |
686 | */ | 846 | */ |
687 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP); | 847 | regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, |
688 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); | 848 | data->socdata->measure_temp_mask); |
849 | regmap_write(map, data->socdata->sensor_ctrl + REG_SET, | ||
850 | data->socdata->power_down_mask); | ||
689 | data->mode = THERMAL_DEVICE_DISABLED; | 851 | data->mode = THERMAL_DEVICE_DISABLED; |
690 | clk_disable_unprepare(data->thermal_clk); | 852 | clk_disable_unprepare(data->thermal_clk); |
691 | 853 | ||
@@ -702,8 +864,10 @@ static int imx_thermal_resume(struct device *dev) | |||
702 | if (ret) | 864 | if (ret) |
703 | return ret; | 865 | return ret; |
704 | /* Enabled thermal sensor after resume */ | 866 | /* Enabled thermal sensor after resume */ |
705 | regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); | 867 | regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, |
706 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); | 868 | data->socdata->power_down_mask); |
869 | regmap_write(map, data->socdata->sensor_ctrl + REG_SET, | ||
870 | data->socdata->measure_temp_mask); | ||
707 | data->mode = THERMAL_DEVICE_ENABLED; | 871 | data->mode = THERMAL_DEVICE_ENABLED; |
708 | 872 | ||
709 | return 0; | 873 | return 0; |
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index c75661a3801a..0691f260f6ea 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c | |||
@@ -153,6 +153,12 @@ | |||
153 | /* The number of sensing points per bank */ | 153 | /* The number of sensing points per bank */ |
154 | #define MT2712_NUM_SENSORS_PER_ZONE 4 | 154 | #define MT2712_NUM_SENSORS_PER_ZONE 4 |
155 | 155 | ||
156 | #define MT7622_TEMP_AUXADC_CHANNEL 11 | ||
157 | #define MT7622_NUM_SENSORS 1 | ||
158 | #define MT7622_NUM_ZONES 1 | ||
159 | #define MT7622_NUM_SENSORS_PER_ZONE 1 | ||
160 | #define MT7622_TS1 0 | ||
161 | |||
156 | struct mtk_thermal; | 162 | struct mtk_thermal; |
157 | 163 | ||
158 | struct thermal_bank_cfg { | 164 | struct thermal_bank_cfg { |
@@ -242,6 +248,12 @@ static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = { | |||
242 | 248 | ||
243 | static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 }; | 249 | static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 }; |
244 | 250 | ||
251 | /* MT7622 thermal sensor data */ | ||
252 | static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, }; | ||
253 | static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; | ||
254 | static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; | ||
255 | static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, }; | ||
256 | |||
245 | /** | 257 | /** |
246 | * The MT8173 thermal controller has four banks. Each bank can read up to | 258 | * The MT8173 thermal controller has four banks. Each bank can read up to |
247 | * four temperature sensors simultaneously. The MT8173 has a total of 5 | 259 | * four temperature sensors simultaneously. The MT8173 has a total of 5 |
@@ -329,6 +341,25 @@ static const struct mtk_thermal_data mt2712_thermal_data = { | |||
329 | .sensor_mux_values = mt2712_mux_values, | 341 | .sensor_mux_values = mt2712_mux_values, |
330 | }; | 342 | }; |
331 | 343 | ||
344 | /* | ||
345 | * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data | ||
346 | * access. | ||
347 | */ | ||
348 | static const struct mtk_thermal_data mt7622_thermal_data = { | ||
349 | .auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL, | ||
350 | .num_banks = MT7622_NUM_ZONES, | ||
351 | .num_sensors = MT7622_NUM_SENSORS, | ||
352 | .bank_data = { | ||
353 | { | ||
354 | .num_sensors = 1, | ||
355 | .sensors = mt7622_bank_data, | ||
356 | }, | ||
357 | }, | ||
358 | .msr = mt7622_msr, | ||
359 | .adcpnp = mt7622_adcpnp, | ||
360 | .sensor_mux_values = mt7622_mux_values, | ||
361 | }; | ||
362 | |||
332 | /** | 363 | /** |
333 | * raw_to_mcelsius - convert a raw ADC value to mcelsius | 364 | * raw_to_mcelsius - convert a raw ADC value to mcelsius |
334 | * @mt: The thermal controller | 365 | * @mt: The thermal controller |
@@ -631,6 +662,10 @@ static const struct of_device_id mtk_thermal_of_match[] = { | |||
631 | { | 662 | { |
632 | .compatible = "mediatek,mt2712-thermal", | 663 | .compatible = "mediatek,mt2712-thermal", |
633 | .data = (void *)&mt2712_thermal_data, | 664 | .data = (void *)&mt2712_thermal_data, |
665 | }, | ||
666 | { | ||
667 | .compatible = "mediatek,mt7622-thermal", | ||
668 | .data = (void *)&mt7622_thermal_data, | ||
634 | }, { | 669 | }, { |
635 | }, | 670 | }, |
636 | }; | 671 | }; |
@@ -642,7 +677,6 @@ static int mtk_thermal_probe(struct platform_device *pdev) | |||
642 | struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; | 677 | struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; |
643 | struct mtk_thermal *mt; | 678 | struct mtk_thermal *mt; |
644 | struct resource *res; | 679 | struct resource *res; |
645 | const struct of_device_id *of_id; | ||
646 | u64 auxadc_phys_base, apmixed_phys_base; | 680 | u64 auxadc_phys_base, apmixed_phys_base; |
647 | struct thermal_zone_device *tzdev; | 681 | struct thermal_zone_device *tzdev; |
648 | 682 | ||
@@ -650,9 +684,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) | |||
650 | if (!mt) | 684 | if (!mt) |
651 | return -ENOMEM; | 685 | return -ENOMEM; |
652 | 686 | ||
653 | of_id = of_match_device(mtk_thermal_of_match, &pdev->dev); | 687 | mt->conf = of_device_get_match_data(&pdev->dev); |
654 | if (of_id) | ||
655 | mt->conf = (const struct mtk_thermal_data *)of_id->data; | ||
656 | 688 | ||
657 | mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm"); | 689 | mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm"); |
658 | if (IS_ERR(mt->clk_peri_therm)) | 690 | if (IS_ERR(mt->clk_peri_therm)) |
diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c index 95f987d5aa71..ad4f3a8d6560 100644 --- a/drivers/thermal/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom-spmi-temp-alarm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. | 2 | * Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License version 2 and | 5 | * it under the terms of the GNU General Public License version 2 and |
@@ -11,6 +11,7 @@ | |||
11 | * GNU General Public License for more details. | 11 | * GNU General Public License for more details. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/bitops.h> | ||
14 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
15 | #include <linux/err.h> | 16 | #include <linux/err.h> |
16 | #include <linux/iio/consumer.h> | 17 | #include <linux/iio/consumer.h> |
@@ -29,13 +30,17 @@ | |||
29 | #define QPNP_TM_REG_ALARM_CTRL 0x46 | 30 | #define QPNP_TM_REG_ALARM_CTRL 0x46 |
30 | 31 | ||
31 | #define QPNP_TM_TYPE 0x09 | 32 | #define QPNP_TM_TYPE 0x09 |
32 | #define QPNP_TM_SUBTYPE 0x08 | 33 | #define QPNP_TM_SUBTYPE_GEN1 0x08 |
34 | #define QPNP_TM_SUBTYPE_GEN2 0x09 | ||
33 | 35 | ||
34 | #define STATUS_STAGE_MASK 0x03 | 36 | #define STATUS_GEN1_STAGE_MASK GENMASK(1, 0) |
37 | #define STATUS_GEN2_STATE_MASK GENMASK(6, 4) | ||
38 | #define STATUS_GEN2_STATE_SHIFT 4 | ||
35 | 39 | ||
36 | #define SHUTDOWN_CTRL1_THRESHOLD_MASK 0x03 | 40 | #define SHUTDOWN_CTRL1_OVERRIDE_MASK GENMASK(7, 6) |
41 | #define SHUTDOWN_CTRL1_THRESHOLD_MASK GENMASK(1, 0) | ||
37 | 42 | ||
38 | #define ALARM_CTRL_FORCE_ENABLE 0x80 | 43 | #define ALARM_CTRL_FORCE_ENABLE BIT(7) |
39 | 44 | ||
40 | /* | 45 | /* |
41 | * Trip point values based on threshold control | 46 | * Trip point values based on threshold control |
@@ -58,6 +63,7 @@ | |||
58 | struct qpnp_tm_chip { | 63 | struct qpnp_tm_chip { |
59 | struct regmap *map; | 64 | struct regmap *map; |
60 | struct thermal_zone_device *tz_dev; | 65 | struct thermal_zone_device *tz_dev; |
66 | unsigned int subtype; | ||
61 | long temp; | 67 | long temp; |
62 | unsigned int thresh; | 68 | unsigned int thresh; |
63 | unsigned int stage; | 69 | unsigned int stage; |
@@ -66,6 +72,9 @@ struct qpnp_tm_chip { | |||
66 | struct iio_channel *adc; | 72 | struct iio_channel *adc; |
67 | }; | 73 | }; |
68 | 74 | ||
75 | /* This array maps from GEN2 alarm state to GEN1 alarm stage */ | ||
76 | static const unsigned int alarm_state_map[8] = {0, 1, 1, 2, 2, 3, 3, 3}; | ||
77 | |||
69 | static int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *data) | 78 | static int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *data) |
70 | { | 79 | { |
71 | unsigned int val; | 80 | unsigned int val; |
@@ -84,30 +93,59 @@ static int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 data) | |||
84 | return regmap_write(chip->map, chip->base + addr, data); | 93 | return regmap_write(chip->map, chip->base + addr, data); |
85 | } | 94 | } |
86 | 95 | ||
96 | /** | ||
97 | * qpnp_tm_get_temp_stage() - return over-temperature stage | ||
98 | * @chip: Pointer to the qpnp_tm chip | ||
99 | * | ||
100 | * Return: stage (GEN1) or state (GEN2) on success, or errno on failure. | ||
101 | */ | ||
102 | static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip) | ||
103 | { | ||
104 | int ret; | ||
105 | u8 reg = 0; | ||
106 | |||
107 | ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, ®); | ||
108 | if (ret < 0) | ||
109 | return ret; | ||
110 | |||
111 | if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) | ||
112 | ret = reg & STATUS_GEN1_STAGE_MASK; | ||
113 | else | ||
114 | ret = (reg & STATUS_GEN2_STATE_MASK) >> STATUS_GEN2_STATE_SHIFT; | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | |||
87 | /* | 119 | /* |
88 | * This function updates the internal temp value based on the | 120 | * This function updates the internal temp value based on the |
89 | * current thermal stage and threshold as well as the previous stage | 121 | * current thermal stage and threshold as well as the previous stage |
90 | */ | 122 | */ |
91 | static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip) | 123 | static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip) |
92 | { | 124 | { |
93 | unsigned int stage; | 125 | unsigned int stage, stage_new, stage_old; |
94 | int ret; | 126 | int ret; |
95 | u8 reg = 0; | ||
96 | 127 | ||
97 | ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, ®); | 128 | ret = qpnp_tm_get_temp_stage(chip); |
98 | if (ret < 0) | 129 | if (ret < 0) |
99 | return ret; | 130 | return ret; |
131 | stage = ret; | ||
100 | 132 | ||
101 | stage = reg & STATUS_STAGE_MASK; | 133 | if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) { |
134 | stage_new = stage; | ||
135 | stage_old = chip->stage; | ||
136 | } else { | ||
137 | stage_new = alarm_state_map[stage]; | ||
138 | stage_old = alarm_state_map[chip->stage]; | ||
139 | } | ||
102 | 140 | ||
103 | if (stage > chip->stage) { | 141 | if (stage_new > stage_old) { |
104 | /* increasing stage, use lower bound */ | 142 | /* increasing stage, use lower bound */ |
105 | chip->temp = (stage - 1) * TEMP_STAGE_STEP + | 143 | chip->temp = (stage_new - 1) * TEMP_STAGE_STEP + |
106 | chip->thresh * TEMP_THRESH_STEP + | 144 | chip->thresh * TEMP_THRESH_STEP + |
107 | TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN; | 145 | TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN; |
108 | } else if (stage < chip->stage) { | 146 | } else if (stage_new < stage_old) { |
109 | /* decreasing stage, use upper bound */ | 147 | /* decreasing stage, use upper bound */ |
110 | chip->temp = stage * TEMP_STAGE_STEP + | 148 | chip->temp = stage_new * TEMP_STAGE_STEP + |
111 | chip->thresh * TEMP_THRESH_STEP - | 149 | chip->thresh * TEMP_THRESH_STEP - |
112 | TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN; | 150 | TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN; |
113 | } | 151 | } |
@@ -162,28 +200,37 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data) | |||
162 | */ | 200 | */ |
163 | static int qpnp_tm_init(struct qpnp_tm_chip *chip) | 201 | static int qpnp_tm_init(struct qpnp_tm_chip *chip) |
164 | { | 202 | { |
203 | unsigned int stage; | ||
165 | int ret; | 204 | int ret; |
166 | u8 reg; | 205 | u8 reg = 0; |
167 | 206 | ||
168 | chip->thresh = THRESH_MIN; | 207 | ret = qpnp_tm_read(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, ®); |
208 | if (ret < 0) | ||
209 | return ret; | ||
210 | |||
211 | chip->thresh = reg & SHUTDOWN_CTRL1_THRESHOLD_MASK; | ||
169 | chip->temp = DEFAULT_TEMP; | 212 | chip->temp = DEFAULT_TEMP; |
170 | 213 | ||
171 | ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, ®); | 214 | ret = qpnp_tm_get_temp_stage(chip); |
172 | if (ret < 0) | 215 | if (ret < 0) |
173 | return ret; | 216 | return ret; |
217 | chip->stage = ret; | ||
174 | 218 | ||
175 | chip->stage = reg & STATUS_STAGE_MASK; | 219 | stage = chip->subtype == QPNP_TM_SUBTYPE_GEN1 |
220 | ? chip->stage : alarm_state_map[chip->stage]; | ||
176 | 221 | ||
177 | if (chip->stage) | 222 | if (stage) |
178 | chip->temp = chip->thresh * TEMP_THRESH_STEP + | 223 | chip->temp = chip->thresh * TEMP_THRESH_STEP + |
179 | (chip->stage - 1) * TEMP_STAGE_STEP + | 224 | (stage - 1) * TEMP_STAGE_STEP + |
180 | TEMP_THRESH_MIN; | 225 | TEMP_THRESH_MIN; |
181 | 226 | ||
182 | /* | 227 | /* |
183 | * Set threshold and disable software override of stage 2 and 3 | 228 | * Set threshold and disable software override of stage 2 and 3 |
184 | * shutdowns. | 229 | * shutdowns. |
185 | */ | 230 | */ |
186 | reg = chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK; | 231 | chip->thresh = THRESH_MIN; |
232 | reg &= ~(SHUTDOWN_CTRL1_OVERRIDE_MASK | SHUTDOWN_CTRL1_THRESHOLD_MASK); | ||
233 | reg |= chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK; | ||
187 | ret = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg); | 234 | ret = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg); |
188 | if (ret < 0) | 235 | if (ret < 0) |
189 | return ret; | 236 | return ret; |
@@ -246,12 +293,15 @@ static int qpnp_tm_probe(struct platform_device *pdev) | |||
246 | return ret; | 293 | return ret; |
247 | } | 294 | } |
248 | 295 | ||
249 | if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) { | 296 | if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1 |
297 | && subtype != QPNP_TM_SUBTYPE_GEN2)) { | ||
250 | dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n", | 298 | dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n", |
251 | type, subtype); | 299 | type, subtype); |
252 | return -ENODEV; | 300 | return -ENODEV; |
253 | } | 301 | } |
254 | 302 | ||
303 | chip->subtype = subtype; | ||
304 | |||
255 | ret = qpnp_tm_init(chip); | 305 | ret = qpnp_tm_init(chip); |
256 | if (ret < 0) { | 306 | if (ret < 0) { |
257 | dev_err(&pdev->dev, "init failed\n"); | 307 | dev_err(&pdev->dev, "init failed\n"); |
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index c2c34425279d..3440166c2ae9 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c | |||
@@ -115,6 +115,7 @@ static int tsens_probe(struct platform_device *pdev) | |||
115 | struct tsens_device *tmdev; | 115 | struct tsens_device *tmdev; |
116 | const struct tsens_data *data; | 116 | const struct tsens_data *data; |
117 | const struct of_device_id *id; | 117 | const struct of_device_id *id; |
118 | u32 num_sensors; | ||
118 | 119 | ||
119 | if (pdev->dev.of_node) | 120 | if (pdev->dev.of_node) |
120 | dev = &pdev->dev; | 121 | dev = &pdev->dev; |
@@ -129,19 +130,24 @@ static int tsens_probe(struct platform_device *pdev) | |||
129 | else | 130 | else |
130 | data = &data_8960; | 131 | data = &data_8960; |
131 | 132 | ||
132 | if (data->num_sensors <= 0) { | 133 | num_sensors = data->num_sensors; |
134 | |||
135 | if (np) | ||
136 | of_property_read_u32(np, "#qcom,sensors", &num_sensors); | ||
137 | |||
138 | if (num_sensors <= 0) { | ||
133 | dev_err(dev, "invalid number of sensors\n"); | 139 | dev_err(dev, "invalid number of sensors\n"); |
134 | return -EINVAL; | 140 | return -EINVAL; |
135 | } | 141 | } |
136 | 142 | ||
137 | tmdev = devm_kzalloc(dev, | 143 | tmdev = devm_kzalloc(dev, |
138 | struct_size(tmdev, sensor, data->num_sensors), | 144 | struct_size(tmdev, sensor, num_sensors), |
139 | GFP_KERNEL); | 145 | GFP_KERNEL); |
140 | if (!tmdev) | 146 | if (!tmdev) |
141 | return -ENOMEM; | 147 | return -ENOMEM; |
142 | 148 | ||
143 | tmdev->dev = dev; | 149 | tmdev->dev = dev; |
144 | tmdev->num_sensors = data->num_sensors; | 150 | tmdev->num_sensors = num_sensors; |
145 | tmdev->ops = data->ops; | 151 | tmdev->ops = data->ops; |
146 | for (i = 0; i < tmdev->num_sensors; i++) { | 152 | for (i = 0; i < tmdev->num_sensors; i++) { |
147 | if (data->hw_ids) | 153 | if (data->hw_ids) |
diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 561a0a332208..766521eb7071 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c | |||
@@ -132,7 +132,7 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc, | |||
132 | #define RCAR3_THERMAL_GRAN 500 /* mili Celsius */ | 132 | #define RCAR3_THERMAL_GRAN 500 /* mili Celsius */ |
133 | 133 | ||
134 | /* no idea where these constants come from */ | 134 | /* no idea where these constants come from */ |
135 | #define TJ_1 96 | 135 | #define TJ_1 116 |
136 | #define TJ_3 -41 | 136 | #define TJ_3 -41 |
137 | 137 | ||
138 | static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef, | 138 | static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef, |
@@ -146,7 +146,7 @@ static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef, | |||
146 | * Division is not scaled in BSP and if scaled it might overflow | 146 | * Division is not scaled in BSP and if scaled it might overflow |
147 | * the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled | 147 | * the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled |
148 | */ | 148 | */ |
149 | tj_2 = (FIXPT_INT((ptat[1] - ptat[2]) * 137) | 149 | tj_2 = (FIXPT_INT((ptat[1] - ptat[2]) * 157) |
150 | / (ptat[0] - ptat[2])) - FIXPT_INT(41); | 150 | / (ptat[0] - ptat[2])) - FIXPT_INT(41); |
151 | 151 | ||
152 | coef->a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]), | 152 | coef->a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]), |
@@ -207,8 +207,8 @@ static int rcar_gen3_thermal_set_trips(void *devdata, int low, int high) | |||
207 | { | 207 | { |
208 | struct rcar_gen3_thermal_tsc *tsc = devdata; | 208 | struct rcar_gen3_thermal_tsc *tsc = devdata; |
209 | 209 | ||
210 | low = clamp_val(low, -40000, 125000); | 210 | low = clamp_val(low, -40000, 120000); |
211 | high = clamp_val(high, -40000, 125000); | 211 | high = clamp_val(high, -40000, 120000); |
212 | 212 | ||
213 | rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1, | 213 | rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1, |
214 | rcar_gen3_thermal_mcelsius_to_temp(tsc, low)); | 214 | rcar_gen3_thermal_mcelsius_to_temp(tsc, low)); |
@@ -329,6 +329,7 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc) | |||
329 | static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { | 329 | static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { |
330 | { .compatible = "renesas,r8a7795-thermal", }, | 330 | { .compatible = "renesas,r8a7795-thermal", }, |
331 | { .compatible = "renesas,r8a7796-thermal", }, | 331 | { .compatible = "renesas,r8a7796-thermal", }, |
332 | { .compatible = "renesas,r8a77965-thermal", }, | ||
332 | {}, | 333 | {}, |
333 | }; | 334 | }; |
334 | MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); | 335 | MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); |
@@ -354,11 +355,11 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) | |||
354 | 355 | ||
355 | /* default values if FUSEs are missing */ | 356 | /* default values if FUSEs are missing */ |
356 | /* TODO: Read values from hardware on supported platforms */ | 357 | /* TODO: Read values from hardware on supported platforms */ |
357 | int ptat[3] = { 2351, 1509, 435 }; | 358 | int ptat[3] = { 2631, 1509, 435 }; |
358 | int thcode[TSC_MAX_NUM][3] = { | 359 | int thcode[TSC_MAX_NUM][3] = { |
359 | { 3248, 2800, 2221 }, | 360 | { 3397, 2800, 2221 }, |
360 | { 3245, 2795, 2216 }, | 361 | { 3393, 2795, 2216 }, |
361 | { 3250, 2805, 2237 }, | 362 | { 3389, 2805, 2237 }, |
362 | }; | 363 | }; |
363 | 364 | ||
364 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 365 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 73e5fee6cf1d..45fb284d4c11 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c | |||
@@ -58,10 +58,47 @@ struct rcar_thermal_common { | |||
58 | spinlock_t lock; | 58 | spinlock_t lock; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | struct rcar_thermal_chip { | ||
62 | unsigned int use_of_thermal : 1; | ||
63 | unsigned int has_filonoff : 1; | ||
64 | unsigned int irq_per_ch : 1; | ||
65 | unsigned int needs_suspend_resume : 1; | ||
66 | unsigned int nirqs; | ||
67 | }; | ||
68 | |||
69 | static const struct rcar_thermal_chip rcar_thermal = { | ||
70 | .use_of_thermal = 0, | ||
71 | .has_filonoff = 1, | ||
72 | .irq_per_ch = 0, | ||
73 | .needs_suspend_resume = 0, | ||
74 | .nirqs = 1, | ||
75 | }; | ||
76 | |||
77 | static const struct rcar_thermal_chip rcar_gen2_thermal = { | ||
78 | .use_of_thermal = 1, | ||
79 | .has_filonoff = 1, | ||
80 | .irq_per_ch = 0, | ||
81 | .needs_suspend_resume = 0, | ||
82 | .nirqs = 1, | ||
83 | }; | ||
84 | |||
85 | static const struct rcar_thermal_chip rcar_gen3_thermal = { | ||
86 | .use_of_thermal = 1, | ||
87 | .has_filonoff = 0, | ||
88 | .irq_per_ch = 1, | ||
89 | .needs_suspend_resume = 1, | ||
90 | /* | ||
91 | * The Gen3 chip has 3 interrupts, but this driver uses only 2 | ||
92 | * interrupts to detect a temperature change, rise or fall. | ||
93 | */ | ||
94 | .nirqs = 2, | ||
95 | }; | ||
96 | |||
61 | struct rcar_thermal_priv { | 97 | struct rcar_thermal_priv { |
62 | void __iomem *base; | 98 | void __iomem *base; |
63 | struct rcar_thermal_common *common; | 99 | struct rcar_thermal_common *common; |
64 | struct thermal_zone_device *zone; | 100 | struct thermal_zone_device *zone; |
101 | const struct rcar_thermal_chip *chip; | ||
65 | struct delayed_work work; | 102 | struct delayed_work work; |
66 | struct mutex lock; | 103 | struct mutex lock; |
67 | struct list_head list; | 104 | struct list_head list; |
@@ -77,13 +114,20 @@ struct rcar_thermal_priv { | |||
77 | #define rcar_priv_to_dev(priv) ((priv)->common->dev) | 114 | #define rcar_priv_to_dev(priv) ((priv)->common->dev) |
78 | #define rcar_has_irq_support(priv) ((priv)->common->base) | 115 | #define rcar_has_irq_support(priv) ((priv)->common->base) |
79 | #define rcar_id_to_shift(priv) ((priv)->id * 8) | 116 | #define rcar_id_to_shift(priv) ((priv)->id * 8) |
80 | #define rcar_of_data(dev) ((unsigned long)of_device_get_match_data(dev)) | ||
81 | #define rcar_use_of_thermal(dev) (rcar_of_data(dev) == USE_OF_THERMAL) | ||
82 | 117 | ||
83 | #define USE_OF_THERMAL 1 | ||
84 | static const struct of_device_id rcar_thermal_dt_ids[] = { | 118 | static const struct of_device_id rcar_thermal_dt_ids[] = { |
85 | { .compatible = "renesas,rcar-thermal", }, | 119 | { |
86 | { .compatible = "renesas,rcar-gen2-thermal", .data = (void *)USE_OF_THERMAL }, | 120 | .compatible = "renesas,rcar-thermal", |
121 | .data = &rcar_thermal, | ||
122 | }, | ||
123 | { | ||
124 | .compatible = "renesas,rcar-gen2-thermal", | ||
125 | .data = &rcar_gen2_thermal, | ||
126 | }, | ||
127 | { | ||
128 | .compatible = "renesas,thermal-r8a77995", | ||
129 | .data = &rcar_gen3_thermal, | ||
130 | }, | ||
87 | {}, | 131 | {}, |
88 | }; | 132 | }; |
89 | MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); | 133 | MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); |
@@ -190,7 +234,8 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) | |||
190 | * enable IRQ | 234 | * enable IRQ |
191 | */ | 235 | */ |
192 | if (rcar_has_irq_support(priv)) { | 236 | if (rcar_has_irq_support(priv)) { |
193 | rcar_thermal_write(priv, FILONOFF, 0); | 237 | if (priv->chip->has_filonoff) |
238 | rcar_thermal_write(priv, FILONOFF, 0); | ||
194 | 239 | ||
195 | /* enable Rising/Falling edge interrupt */ | 240 | /* enable Rising/Falling edge interrupt */ |
196 | rcar_thermal_write(priv, POSNEG, 0x1); | 241 | rcar_thermal_write(priv, POSNEG, 0x1); |
@@ -420,7 +465,7 @@ static int rcar_thermal_remove(struct platform_device *pdev) | |||
420 | 465 | ||
421 | rcar_thermal_for_each_priv(priv, common) { | 466 | rcar_thermal_for_each_priv(priv, common) { |
422 | rcar_thermal_irq_disable(priv); | 467 | rcar_thermal_irq_disable(priv); |
423 | if (rcar_use_of_thermal(dev)) | 468 | if (priv->chip->use_of_thermal) |
424 | thermal_remove_hwmon_sysfs(priv->zone); | 469 | thermal_remove_hwmon_sysfs(priv->zone); |
425 | else | 470 | else |
426 | thermal_zone_device_unregister(priv->zone); | 471 | thermal_zone_device_unregister(priv->zone); |
@@ -438,6 +483,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
438 | struct rcar_thermal_priv *priv; | 483 | struct rcar_thermal_priv *priv; |
439 | struct device *dev = &pdev->dev; | 484 | struct device *dev = &pdev->dev; |
440 | struct resource *res, *irq; | 485 | struct resource *res, *irq; |
486 | const struct rcar_thermal_chip *chip = of_device_get_match_data(dev); | ||
441 | int mres = 0; | 487 | int mres = 0; |
442 | int i; | 488 | int i; |
443 | int ret = -ENODEV; | 489 | int ret = -ENODEV; |
@@ -457,19 +503,35 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
457 | pm_runtime_enable(dev); | 503 | pm_runtime_enable(dev); |
458 | pm_runtime_get_sync(dev); | 504 | pm_runtime_get_sync(dev); |
459 | 505 | ||
460 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 506 | for (i = 0; i < chip->nirqs; i++) { |
461 | if (irq) { | 507 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
462 | /* | 508 | if (!irq) |
463 | * platform has IRQ support. | 509 | continue; |
464 | * Then, driver uses common registers | 510 | if (!common->base) { |
465 | * rcar_has_irq_support() will be enabled | 511 | /* |
466 | */ | 512 | * platform has IRQ support. |
467 | res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); | 513 | * Then, driver uses common registers |
468 | common->base = devm_ioremap_resource(dev, res); | 514 | * rcar_has_irq_support() will be enabled |
469 | if (IS_ERR(common->base)) | 515 | */ |
470 | return PTR_ERR(common->base); | 516 | res = platform_get_resource(pdev, IORESOURCE_MEM, |
517 | mres++); | ||
518 | common->base = devm_ioremap_resource(dev, res); | ||
519 | if (IS_ERR(common->base)) | ||
520 | return PTR_ERR(common->base); | ||
521 | |||
522 | idle = 0; /* polling delay is not needed */ | ||
523 | } | ||
471 | 524 | ||
472 | idle = 0; /* polling delay is not needed */ | 525 | ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, |
526 | IRQF_SHARED, dev_name(dev), common); | ||
527 | if (ret) { | ||
528 | dev_err(dev, "irq request failed\n "); | ||
529 | goto error_unregister; | ||
530 | } | ||
531 | |||
532 | /* update ENR bits */ | ||
533 | if (chip->irq_per_ch) | ||
534 | enr_bits |= 1 << i; | ||
473 | } | 535 | } |
474 | 536 | ||
475 | for (i = 0;; i++) { | 537 | for (i = 0;; i++) { |
@@ -491,6 +553,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
491 | 553 | ||
492 | priv->common = common; | 554 | priv->common = common; |
493 | priv->id = i; | 555 | priv->id = i; |
556 | priv->chip = chip; | ||
494 | mutex_init(&priv->lock); | 557 | mutex_init(&priv->lock); |
495 | INIT_LIST_HEAD(&priv->list); | 558 | INIT_LIST_HEAD(&priv->list); |
496 | INIT_DELAYED_WORK(&priv->work, rcar_thermal_work); | 559 | INIT_DELAYED_WORK(&priv->work, rcar_thermal_work); |
@@ -498,7 +561,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
498 | if (ret < 0) | 561 | if (ret < 0) |
499 | goto error_unregister; | 562 | goto error_unregister; |
500 | 563 | ||
501 | if (rcar_use_of_thermal(dev)) | 564 | if (chip->use_of_thermal) |
502 | priv->zone = devm_thermal_zone_of_sensor_register( | 565 | priv->zone = devm_thermal_zone_of_sensor_register( |
503 | dev, i, priv, | 566 | dev, i, priv, |
504 | &rcar_thermal_zone_of_ops); | 567 | &rcar_thermal_zone_of_ops); |
@@ -515,7 +578,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
515 | goto error_unregister; | 578 | goto error_unregister; |
516 | } | 579 | } |
517 | 580 | ||
518 | if (rcar_use_of_thermal(dev)) { | 581 | if (chip->use_of_thermal) { |
519 | /* | 582 | /* |
520 | * thermal_zone doesn't enable hwmon as default, | 583 | * thermal_zone doesn't enable hwmon as default, |
521 | * but, enable it here to keep compatible | 584 | * but, enable it here to keep compatible |
@@ -531,20 +594,12 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
531 | list_move_tail(&priv->list, &common->head); | 594 | list_move_tail(&priv->list, &common->head); |
532 | 595 | ||
533 | /* update ENR bits */ | 596 | /* update ENR bits */ |
534 | enr_bits |= 3 << (i * 8); | 597 | if (!chip->irq_per_ch) |
598 | enr_bits |= 3 << (i * 8); | ||
535 | } | 599 | } |
536 | 600 | ||
537 | /* enable temperature comparation */ | 601 | if (enr_bits) |
538 | if (irq) { | ||
539 | ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0, | ||
540 | dev_name(dev), common); | ||
541 | if (ret) { | ||
542 | dev_err(dev, "irq request failed\n "); | ||
543 | goto error_unregister; | ||
544 | } | ||
545 | |||
546 | rcar_thermal_common_write(common, ENR, enr_bits); | 602 | rcar_thermal_common_write(common, ENR, enr_bits); |
547 | } | ||
548 | 603 | ||
549 | dev_info(dev, "%d sensor probed\n", i); | 604 | dev_info(dev, "%d sensor probed\n", i); |
550 | 605 | ||
@@ -556,9 +611,48 @@ error_unregister: | |||
556 | return ret; | 611 | return ret; |
557 | } | 612 | } |
558 | 613 | ||
614 | #ifdef CONFIG_PM_SLEEP | ||
615 | static int rcar_thermal_suspend(struct device *dev) | ||
616 | { | ||
617 | struct rcar_thermal_common *common = dev_get_drvdata(dev); | ||
618 | struct rcar_thermal_priv *priv = list_first_entry(&common->head, | ||
619 | typeof(*priv), list); | ||
620 | |||
621 | if (priv->chip->needs_suspend_resume) { | ||
622 | rcar_thermal_common_write(common, ENR, 0); | ||
623 | rcar_thermal_irq_disable(priv); | ||
624 | rcar_thermal_bset(priv, THSCR, CPCTL, 0); | ||
625 | } | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int rcar_thermal_resume(struct device *dev) | ||
631 | { | ||
632 | struct rcar_thermal_common *common = dev_get_drvdata(dev); | ||
633 | struct rcar_thermal_priv *priv = list_first_entry(&common->head, | ||
634 | typeof(*priv), list); | ||
635 | int ret; | ||
636 | |||
637 | if (priv->chip->needs_suspend_resume) { | ||
638 | ret = rcar_thermal_update_temp(priv); | ||
639 | if (ret < 0) | ||
640 | return ret; | ||
641 | rcar_thermal_irq_enable(priv); | ||
642 | rcar_thermal_common_write(common, ENR, 0x03); | ||
643 | } | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | #endif | ||
648 | |||
649 | static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend, | ||
650 | rcar_thermal_resume); | ||
651 | |||
559 | static struct platform_driver rcar_thermal_driver = { | 652 | static struct platform_driver rcar_thermal_driver = { |
560 | .driver = { | 653 | .driver = { |
561 | .name = "rcar_thermal", | 654 | .name = "rcar_thermal", |
655 | .pm = &rcar_thermal_pm_ops, | ||
562 | .of_match_table = rcar_thermal_dt_ids, | 656 | .of_match_table = rcar_thermal_dt_ids, |
563 | }, | 657 | }, |
564 | .probe = rcar_thermal_probe, | 658 | .probe = rcar_thermal_probe, |
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index ac83f721db24..a992e51ef065 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c | |||
@@ -29,13 +29,14 @@ | |||
29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/of.h> | 32 | #include <linux/of_device.h> |
33 | #include <linux/of_address.h> | 33 | #include <linux/of_address.h> |
34 | #include <linux/of_irq.h> | 34 | #include <linux/of_irq.h> |
35 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
36 | #include <linux/regulator/consumer.h> | 36 | #include <linux/regulator/consumer.h> |
37 | 37 | ||
38 | #include "exynos_tmu.h" | 38 | #include <dt-bindings/thermal/thermal_exynos.h> |
39 | |||
39 | #include "../thermal_core.h" | 40 | #include "../thermal_core.h" |
40 | 41 | ||
41 | /* Exynos generic registers */ | 42 | /* Exynos generic registers */ |
@@ -75,9 +76,6 @@ | |||
75 | #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12 | 76 | #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12 |
76 | 77 | ||
77 | #define EXYNOS_TMU_INTEN_RISE0_SHIFT 0 | 78 | #define EXYNOS_TMU_INTEN_RISE0_SHIFT 0 |
78 | #define EXYNOS_TMU_INTEN_RISE1_SHIFT 4 | ||
79 | #define EXYNOS_TMU_INTEN_RISE2_SHIFT 8 | ||
80 | #define EXYNOS_TMU_INTEN_RISE3_SHIFT 12 | ||
81 | #define EXYNOS_TMU_INTEN_FALL0_SHIFT 16 | 79 | #define EXYNOS_TMU_INTEN_FALL0_SHIFT 16 |
82 | 80 | ||
83 | #define EXYNOS_EMUL_TIME 0x57F0 | 81 | #define EXYNOS_EMUL_TIME 0x57F0 |
@@ -98,11 +96,6 @@ | |||
98 | #define EXYNOS4412_MUX_ADDR_SHIFT 20 | 96 | #define EXYNOS4412_MUX_ADDR_SHIFT 20 |
99 | 97 | ||
100 | /* Exynos5433 specific registers */ | 98 | /* Exynos5433 specific registers */ |
101 | #define EXYNOS5433_TMU_REG_CONTROL1 0x024 | ||
102 | #define EXYNOS5433_TMU_SAMPLING_INTERVAL 0x02c | ||
103 | #define EXYNOS5433_TMU_COUNTER_VALUE0 0x030 | ||
104 | #define EXYNOS5433_TMU_COUNTER_VALUE1 0x034 | ||
105 | #define EXYNOS5433_TMU_REG_CURRENT_TEMP1 0x044 | ||
106 | #define EXYNOS5433_THD_TEMP_RISE3_0 0x050 | 99 | #define EXYNOS5433_THD_TEMP_RISE3_0 0x050 |
107 | #define EXYNOS5433_THD_TEMP_RISE7_4 0x054 | 100 | #define EXYNOS5433_THD_TEMP_RISE7_4 0x054 |
108 | #define EXYNOS5433_THD_TEMP_FALL3_0 0x060 | 101 | #define EXYNOS5433_THD_TEMP_FALL3_0 0x060 |
@@ -123,27 +116,7 @@ | |||
123 | 116 | ||
124 | #define EXYNOS5433_PD_DET_EN 1 | 117 | #define EXYNOS5433_PD_DET_EN 1 |
125 | 118 | ||
126 | /*exynos5440 specific registers*/ | 119 | #define EXYNOS5433_G3D_BASE 0x10070000 |
127 | #define EXYNOS5440_TMU_S0_7_TRIM 0x000 | ||
128 | #define EXYNOS5440_TMU_S0_7_CTRL 0x020 | ||
129 | #define EXYNOS5440_TMU_S0_7_DEBUG 0x040 | ||
130 | #define EXYNOS5440_TMU_S0_7_TEMP 0x0f0 | ||
131 | #define EXYNOS5440_TMU_S0_7_TH0 0x110 | ||
132 | #define EXYNOS5440_TMU_S0_7_TH1 0x130 | ||
133 | #define EXYNOS5440_TMU_S0_7_TH2 0x150 | ||
134 | #define EXYNOS5440_TMU_S0_7_IRQEN 0x210 | ||
135 | #define EXYNOS5440_TMU_S0_7_IRQ 0x230 | ||
136 | /* exynos5440 common registers */ | ||
137 | #define EXYNOS5440_TMU_IRQ_STATUS 0x000 | ||
138 | #define EXYNOS5440_TMU_PMIN 0x004 | ||
139 | |||
140 | #define EXYNOS5440_TMU_INTEN_RISE0_SHIFT 0 | ||
141 | #define EXYNOS5440_TMU_INTEN_RISE1_SHIFT 1 | ||
142 | #define EXYNOS5440_TMU_INTEN_RISE2_SHIFT 2 | ||
143 | #define EXYNOS5440_TMU_INTEN_RISE3_SHIFT 3 | ||
144 | #define EXYNOS5440_TMU_INTEN_FALL0_SHIFT 4 | ||
145 | #define EXYNOS5440_TMU_TH_RISE4_SHIFT 24 | ||
146 | #define EXYNOS5440_EFUSE_SWAP_OFFSET 8 | ||
147 | 120 | ||
148 | /* Exynos7 specific registers */ | 121 | /* Exynos7 specific registers */ |
149 | #define EXYNOS7_THD_TEMP_RISE7_6 0x50 | 122 | #define EXYNOS7_THD_TEMP_RISE7_6 0x50 |
@@ -155,22 +128,32 @@ | |||
155 | #define EXYNOS7_TMU_TEMP_MASK 0x1ff | 128 | #define EXYNOS7_TMU_TEMP_MASK 0x1ff |
156 | #define EXYNOS7_PD_DET_EN_SHIFT 23 | 129 | #define EXYNOS7_PD_DET_EN_SHIFT 23 |
157 | #define EXYNOS7_TMU_INTEN_RISE0_SHIFT 0 | 130 | #define EXYNOS7_TMU_INTEN_RISE0_SHIFT 0 |
158 | #define EXYNOS7_TMU_INTEN_RISE1_SHIFT 1 | ||
159 | #define EXYNOS7_TMU_INTEN_RISE2_SHIFT 2 | ||
160 | #define EXYNOS7_TMU_INTEN_RISE3_SHIFT 3 | ||
161 | #define EXYNOS7_TMU_INTEN_RISE4_SHIFT 4 | ||
162 | #define EXYNOS7_TMU_INTEN_RISE5_SHIFT 5 | ||
163 | #define EXYNOS7_TMU_INTEN_RISE6_SHIFT 6 | ||
164 | #define EXYNOS7_TMU_INTEN_RISE7_SHIFT 7 | ||
165 | #define EXYNOS7_EMUL_DATA_SHIFT 7 | 131 | #define EXYNOS7_EMUL_DATA_SHIFT 7 |
166 | #define EXYNOS7_EMUL_DATA_MASK 0x1ff | 132 | #define EXYNOS7_EMUL_DATA_MASK 0x1ff |
167 | 133 | ||
134 | #define EXYNOS_FIRST_POINT_TRIM 25 | ||
135 | #define EXYNOS_SECOND_POINT_TRIM 85 | ||
136 | |||
137 | #define EXYNOS_NOISE_CANCEL_MODE 4 | ||
138 | |||
168 | #define MCELSIUS 1000 | 139 | #define MCELSIUS 1000 |
140 | |||
141 | enum soc_type { | ||
142 | SOC_ARCH_EXYNOS3250 = 1, | ||
143 | SOC_ARCH_EXYNOS4210, | ||
144 | SOC_ARCH_EXYNOS4412, | ||
145 | SOC_ARCH_EXYNOS5250, | ||
146 | SOC_ARCH_EXYNOS5260, | ||
147 | SOC_ARCH_EXYNOS5420, | ||
148 | SOC_ARCH_EXYNOS5420_TRIMINFO, | ||
149 | SOC_ARCH_EXYNOS5433, | ||
150 | SOC_ARCH_EXYNOS7, | ||
151 | }; | ||
152 | |||
169 | /** | 153 | /** |
170 | * struct exynos_tmu_data : A structure to hold the private data of the TMU | 154 | * struct exynos_tmu_data : A structure to hold the private data of the TMU |
171 | driver | 155 | driver |
172 | * @id: identifier of the one instance of the TMU controller. | 156 | * @id: identifier of the one instance of the TMU controller. |
173 | * @pdata: pointer to the tmu platform/configuration data | ||
174 | * @base: base address of the single instance of the TMU controller. | 157 | * @base: base address of the single instance of the TMU controller. |
175 | * @base_second: base address of the common registers of the TMU controller. | 158 | * @base_second: base address of the common registers of the TMU controller. |
176 | * @irq: irq number of the TMU controller. | 159 | * @irq: irq number of the TMU controller. |
@@ -180,8 +163,17 @@ | |||
180 | * @clk: pointer to the clock structure. | 163 | * @clk: pointer to the clock structure. |
181 | * @clk_sec: pointer to the clock structure for accessing the base_second. | 164 | * @clk_sec: pointer to the clock structure for accessing the base_second. |
182 | * @sclk: pointer to the clock structure for accessing the tmu special clk. | 165 | * @sclk: pointer to the clock structure for accessing the tmu special clk. |
166 | * @cal_type: calibration type for temperature | ||
167 | * @efuse_value: SoC defined fuse value | ||
168 | * @min_efuse_value: minimum valid trimming data | ||
169 | * @max_efuse_value: maximum valid trimming data | ||
183 | * @temp_error1: fused value of the first point trim. | 170 | * @temp_error1: fused value of the first point trim. |
184 | * @temp_error2: fused value of the second point trim. | 171 | * @temp_error2: fused value of the second point trim. |
172 | * @gain: gain of amplifier in the positive-TC generator block | ||
173 | * 0 < gain <= 15 | ||
174 | * @reference_voltage: reference voltage of amplifier | ||
175 | * in the positive-TC generator block | ||
176 | * 0 < reference_voltage <= 31 | ||
185 | * @regulator: pointer to the TMU regulator structure. | 177 | * @regulator: pointer to the TMU regulator structure. |
186 | * @reg_conf: pointer to structure to register with core thermal. | 178 | * @reg_conf: pointer to structure to register with core thermal. |
187 | * @ntrip: number of supported trip points. | 179 | * @ntrip: number of supported trip points. |
@@ -194,7 +186,6 @@ | |||
194 | */ | 186 | */ |
195 | struct exynos_tmu_data { | 187 | struct exynos_tmu_data { |
196 | int id; | 188 | int id; |
197 | struct exynos_tmu_platform_data *pdata; | ||
198 | void __iomem *base; | 189 | void __iomem *base; |
199 | void __iomem *base_second; | 190 | void __iomem *base_second; |
200 | int irq; | 191 | int irq; |
@@ -202,71 +193,42 @@ struct exynos_tmu_data { | |||
202 | struct work_struct irq_work; | 193 | struct work_struct irq_work; |
203 | struct mutex lock; | 194 | struct mutex lock; |
204 | struct clk *clk, *clk_sec, *sclk; | 195 | struct clk *clk, *clk_sec, *sclk; |
196 | u32 cal_type; | ||
197 | u32 efuse_value; | ||
198 | u32 min_efuse_value; | ||
199 | u32 max_efuse_value; | ||
205 | u16 temp_error1, temp_error2; | 200 | u16 temp_error1, temp_error2; |
201 | u8 gain; | ||
202 | u8 reference_voltage; | ||
206 | struct regulator *regulator; | 203 | struct regulator *regulator; |
207 | struct thermal_zone_device *tzd; | 204 | struct thermal_zone_device *tzd; |
208 | unsigned int ntrip; | 205 | unsigned int ntrip; |
209 | bool enabled; | 206 | bool enabled; |
210 | 207 | ||
211 | int (*tmu_initialize)(struct platform_device *pdev); | 208 | void (*tmu_set_trip_temp)(struct exynos_tmu_data *data, int trip, |
209 | u8 temp); | ||
210 | void (*tmu_set_trip_hyst)(struct exynos_tmu_data *data, int trip, | ||
211 | u8 temp, u8 hyst); | ||
212 | void (*tmu_initialize)(struct platform_device *pdev); | ||
212 | void (*tmu_control)(struct platform_device *pdev, bool on); | 213 | void (*tmu_control)(struct platform_device *pdev, bool on); |
213 | int (*tmu_read)(struct exynos_tmu_data *data); | 214 | int (*tmu_read)(struct exynos_tmu_data *data); |
214 | void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp); | 215 | void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp); |
215 | void (*tmu_clear_irqs)(struct exynos_tmu_data *data); | 216 | void (*tmu_clear_irqs)(struct exynos_tmu_data *data); |
216 | }; | 217 | }; |
217 | 218 | ||
218 | static void exynos_report_trigger(struct exynos_tmu_data *p) | ||
219 | { | ||
220 | char data[10], *envp[] = { data, NULL }; | ||
221 | struct thermal_zone_device *tz = p->tzd; | ||
222 | int temp; | ||
223 | unsigned int i; | ||
224 | |||
225 | if (!tz) { | ||
226 | pr_err("No thermal zone device defined\n"); | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); | ||
231 | |||
232 | mutex_lock(&tz->lock); | ||
233 | /* Find the level for which trip happened */ | ||
234 | for (i = 0; i < of_thermal_get_ntrips(tz); i++) { | ||
235 | tz->ops->get_trip_temp(tz, i, &temp); | ||
236 | if (tz->last_temperature < temp) | ||
237 | break; | ||
238 | } | ||
239 | |||
240 | snprintf(data, sizeof(data), "%u", i); | ||
241 | kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, envp); | ||
242 | mutex_unlock(&tz->lock); | ||
243 | } | ||
244 | |||
245 | /* | 219 | /* |
246 | * TMU treats temperature as a mapped temperature code. | 220 | * TMU treats temperature as a mapped temperature code. |
247 | * The temperature is converted differently depending on the calibration type. | 221 | * The temperature is converted differently depending on the calibration type. |
248 | */ | 222 | */ |
249 | static int temp_to_code(struct exynos_tmu_data *data, u8 temp) | 223 | static int temp_to_code(struct exynos_tmu_data *data, u8 temp) |
250 | { | 224 | { |
251 | struct exynos_tmu_platform_data *pdata = data->pdata; | 225 | if (data->cal_type == TYPE_ONE_POINT_TRIMMING) |
252 | int temp_code; | 226 | return temp + data->temp_error1 - EXYNOS_FIRST_POINT_TRIM; |
253 | |||
254 | switch (pdata->cal_type) { | ||
255 | case TYPE_TWO_POINT_TRIMMING: | ||
256 | temp_code = (temp - pdata->first_point_trim) * | ||
257 | (data->temp_error2 - data->temp_error1) / | ||
258 | (pdata->second_point_trim - pdata->first_point_trim) + | ||
259 | data->temp_error1; | ||
260 | break; | ||
261 | case TYPE_ONE_POINT_TRIMMING: | ||
262 | temp_code = temp + data->temp_error1 - pdata->first_point_trim; | ||
263 | break; | ||
264 | default: | ||
265 | temp_code = temp + pdata->default_temp_offset; | ||
266 | break; | ||
267 | } | ||
268 | 227 | ||
269 | return temp_code; | 228 | return (temp - EXYNOS_FIRST_POINT_TRIM) * |
229 | (data->temp_error2 - data->temp_error1) / | ||
230 | (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) + | ||
231 | data->temp_error1; | ||
270 | } | 232 | } |
271 | 233 | ||
272 | /* | 234 | /* |
@@ -275,120 +237,123 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp) | |||
275 | */ | 237 | */ |
276 | static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code) | 238 | static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code) |
277 | { | 239 | { |
278 | struct exynos_tmu_platform_data *pdata = data->pdata; | 240 | if (data->cal_type == TYPE_ONE_POINT_TRIMMING) |
279 | int temp; | 241 | return temp_code - data->temp_error1 + EXYNOS_FIRST_POINT_TRIM; |
280 | |||
281 | switch (pdata->cal_type) { | ||
282 | case TYPE_TWO_POINT_TRIMMING: | ||
283 | temp = (temp_code - data->temp_error1) * | ||
284 | (pdata->second_point_trim - pdata->first_point_trim) / | ||
285 | (data->temp_error2 - data->temp_error1) + | ||
286 | pdata->first_point_trim; | ||
287 | break; | ||
288 | case TYPE_ONE_POINT_TRIMMING: | ||
289 | temp = temp_code - data->temp_error1 + pdata->first_point_trim; | ||
290 | break; | ||
291 | default: | ||
292 | temp = temp_code - pdata->default_temp_offset; | ||
293 | break; | ||
294 | } | ||
295 | 242 | ||
296 | return temp; | 243 | return (temp_code - data->temp_error1) * |
244 | (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) / | ||
245 | (data->temp_error2 - data->temp_error1) + | ||
246 | EXYNOS_FIRST_POINT_TRIM; | ||
297 | } | 247 | } |
298 | 248 | ||
299 | static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) | 249 | static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) |
300 | { | 250 | { |
301 | struct exynos_tmu_platform_data *pdata = data->pdata; | 251 | u16 tmu_temp_mask = |
252 | (data->soc == SOC_ARCH_EXYNOS7) ? EXYNOS7_TMU_TEMP_MASK | ||
253 | : EXYNOS_TMU_TEMP_MASK; | ||
302 | 254 | ||
303 | data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK; | 255 | data->temp_error1 = trim_info & tmu_temp_mask; |
304 | data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) & | 256 | data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) & |
305 | EXYNOS_TMU_TEMP_MASK); | 257 | EXYNOS_TMU_TEMP_MASK); |
306 | 258 | ||
307 | if (!data->temp_error1 || | 259 | if (!data->temp_error1 || |
308 | (pdata->min_efuse_value > data->temp_error1) || | 260 | (data->min_efuse_value > data->temp_error1) || |
309 | (data->temp_error1 > pdata->max_efuse_value)) | 261 | (data->temp_error1 > data->max_efuse_value)) |
310 | data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK; | 262 | data->temp_error1 = data->efuse_value & EXYNOS_TMU_TEMP_MASK; |
311 | 263 | ||
312 | if (!data->temp_error2) | 264 | if (!data->temp_error2) |
313 | data->temp_error2 = | 265 | data->temp_error2 = |
314 | (pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) & | 266 | (data->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) & |
315 | EXYNOS_TMU_TEMP_MASK; | 267 | EXYNOS_TMU_TEMP_MASK; |
316 | } | 268 | } |
317 | 269 | ||
318 | static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling) | 270 | static int exynos_tmu_initialize(struct platform_device *pdev) |
319 | { | 271 | { |
320 | struct thermal_zone_device *tz = data->tzd; | 272 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
273 | struct thermal_zone_device *tzd = data->tzd; | ||
321 | const struct thermal_trip * const trips = | 274 | const struct thermal_trip * const trips = |
322 | of_thermal_get_trip_points(tz); | 275 | of_thermal_get_trip_points(tzd); |
323 | unsigned long temp; | 276 | unsigned int status; |
324 | int i; | 277 | int ret = 0, temp, hyst; |
325 | 278 | ||
326 | if (!trips) { | 279 | if (!trips) { |
327 | pr_err("%s: Cannot get trip points from of-thermal.c!\n", | 280 | dev_err(&pdev->dev, |
328 | __func__); | 281 | "Cannot get trip points from device tree!\n"); |
329 | return 0; | 282 | return -ENODEV; |
330 | } | 283 | } |
331 | 284 | ||
332 | for (i = 0; i < of_thermal_get_ntrips(tz); i++) { | 285 | if (data->soc != SOC_ARCH_EXYNOS5433) /* FIXME */ |
333 | if (trips[i].type == THERMAL_TRIP_CRITICAL) | 286 | ret = tzd->ops->get_crit_temp(tzd, &temp); |
334 | continue; | 287 | if (ret) { |
335 | 288 | dev_err(&pdev->dev, | |
336 | temp = trips[i].temperature / MCELSIUS; | 289 | "No CRITICAL trip point defined in device tree!\n"); |
337 | if (falling) | 290 | goto out; |
338 | temp -= (trips[i].hysteresis / MCELSIUS); | ||
339 | else | ||
340 | threshold &= ~(0xff << 8 * i); | ||
341 | |||
342 | threshold |= temp_to_code(data, temp) << 8 * i; | ||
343 | } | 291 | } |
344 | 292 | ||
345 | return threshold; | 293 | if (of_thermal_get_ntrips(tzd) > data->ntrip) { |
346 | } | ||
347 | |||
348 | static int exynos_tmu_initialize(struct platform_device *pdev) | ||
349 | { | ||
350 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | ||
351 | int ret; | ||
352 | |||
353 | if (of_thermal_get_ntrips(data->tzd) > data->ntrip) { | ||
354 | dev_info(&pdev->dev, | 294 | dev_info(&pdev->dev, |
355 | "More trip points than supported by this TMU.\n"); | 295 | "More trip points than supported by this TMU.\n"); |
356 | dev_info(&pdev->dev, | 296 | dev_info(&pdev->dev, |
357 | "%d trip points should be configured in polling mode.\n", | 297 | "%d trip points should be configured in polling mode.\n", |
358 | (of_thermal_get_ntrips(data->tzd) - data->ntrip)); | 298 | (of_thermal_get_ntrips(tzd) - data->ntrip)); |
359 | } | 299 | } |
360 | 300 | ||
361 | mutex_lock(&data->lock); | 301 | mutex_lock(&data->lock); |
362 | clk_enable(data->clk); | 302 | clk_enable(data->clk); |
363 | if (!IS_ERR(data->clk_sec)) | 303 | if (!IS_ERR(data->clk_sec)) |
364 | clk_enable(data->clk_sec); | 304 | clk_enable(data->clk_sec); |
365 | ret = data->tmu_initialize(pdev); | 305 | |
306 | status = readb(data->base + EXYNOS_TMU_REG_STATUS); | ||
307 | if (!status) { | ||
308 | ret = -EBUSY; | ||
309 | } else { | ||
310 | int i, ntrips = | ||
311 | min_t(int, of_thermal_get_ntrips(tzd), data->ntrip); | ||
312 | |||
313 | data->tmu_initialize(pdev); | ||
314 | |||
315 | /* Write temperature code for rising and falling threshold */ | ||
316 | for (i = 0; i < ntrips; i++) { | ||
317 | /* Write temperature code for rising threshold */ | ||
318 | ret = tzd->ops->get_trip_temp(tzd, i, &temp); | ||
319 | if (ret) | ||
320 | goto err; | ||
321 | temp /= MCELSIUS; | ||
322 | data->tmu_set_trip_temp(data, i, temp); | ||
323 | |||
324 | /* Write temperature code for falling threshold */ | ||
325 | ret = tzd->ops->get_trip_hyst(tzd, i, &hyst); | ||
326 | if (ret) | ||
327 | goto err; | ||
328 | hyst /= MCELSIUS; | ||
329 | data->tmu_set_trip_hyst(data, i, temp, hyst); | ||
330 | } | ||
331 | |||
332 | data->tmu_clear_irqs(data); | ||
333 | } | ||
334 | err: | ||
366 | clk_disable(data->clk); | 335 | clk_disable(data->clk); |
367 | mutex_unlock(&data->lock); | 336 | mutex_unlock(&data->lock); |
368 | if (!IS_ERR(data->clk_sec)) | 337 | if (!IS_ERR(data->clk_sec)) |
369 | clk_disable(data->clk_sec); | 338 | clk_disable(data->clk_sec); |
370 | 339 | out: | |
371 | return ret; | 340 | return ret; |
372 | } | 341 | } |
373 | 342 | ||
374 | static u32 get_con_reg(struct exynos_tmu_data *data, u32 con) | 343 | static u32 get_con_reg(struct exynos_tmu_data *data, u32 con) |
375 | { | 344 | { |
376 | struct exynos_tmu_platform_data *pdata = data->pdata; | ||
377 | |||
378 | if (data->soc == SOC_ARCH_EXYNOS4412 || | 345 | if (data->soc == SOC_ARCH_EXYNOS4412 || |
379 | data->soc == SOC_ARCH_EXYNOS3250) | 346 | data->soc == SOC_ARCH_EXYNOS3250) |
380 | con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT); | 347 | con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT); |
381 | 348 | ||
382 | con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT); | 349 | con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT); |
383 | con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT; | 350 | con |= data->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT; |
384 | 351 | ||
385 | con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); | 352 | con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); |
386 | con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); | 353 | con |= (data->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); |
387 | 354 | ||
388 | if (pdata->noise_cancel_mode) { | 355 | con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT); |
389 | con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT); | 356 | con |= (EXYNOS_NOISE_CANCEL_MODE << EXYNOS_TMU_TRIP_MODE_SHIFT); |
390 | con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT); | ||
391 | } | ||
392 | 357 | ||
393 | return con; | 358 | return con; |
394 | } | 359 | } |
@@ -405,65 +370,70 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on) | |||
405 | mutex_unlock(&data->lock); | 370 | mutex_unlock(&data->lock); |
406 | } | 371 | } |
407 | 372 | ||
408 | static int exynos4210_tmu_initialize(struct platform_device *pdev) | 373 | static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data, |
374 | int trip, u8 temp) | ||
409 | { | 375 | { |
410 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | ||
411 | struct thermal_zone_device *tz = data->tzd; | ||
412 | const struct thermal_trip * const trips = | 376 | const struct thermal_trip * const trips = |
413 | of_thermal_get_trip_points(tz); | 377 | of_thermal_get_trip_points(data->tzd); |
414 | int ret = 0, threshold_code, i; | 378 | u8 ref, th_code; |
415 | unsigned long reference, temp; | ||
416 | unsigned int status; | ||
417 | 379 | ||
418 | if (!trips) { | 380 | ref = trips[0].temperature / MCELSIUS; |
419 | pr_err("%s: Cannot get trip points from of-thermal.c!\n", | ||
420 | __func__); | ||
421 | ret = -ENODEV; | ||
422 | goto out; | ||
423 | } | ||
424 | 381 | ||
425 | status = readb(data->base + EXYNOS_TMU_REG_STATUS); | 382 | if (trip == 0) { |
426 | if (!status) { | 383 | th_code = temp_to_code(data, ref); |
427 | ret = -EBUSY; | 384 | writeb(th_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); |
428 | goto out; | ||
429 | } | 385 | } |
430 | 386 | ||
387 | temp -= ref; | ||
388 | writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip * 4); | ||
389 | } | ||
390 | |||
391 | /* failing thresholds are not supported on Exynos4210 */ | ||
392 | static void exynos4210_tmu_set_trip_hyst(struct exynos_tmu_data *data, | ||
393 | int trip, u8 temp, u8 hyst) | ||
394 | { | ||
395 | } | ||
396 | |||
397 | static void exynos4210_tmu_initialize(struct platform_device *pdev) | ||
398 | { | ||
399 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | ||
400 | |||
431 | sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO)); | 401 | sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO)); |
402 | } | ||
432 | 403 | ||
433 | /* Write temperature code for threshold */ | 404 | static void exynos4412_tmu_set_trip_temp(struct exynos_tmu_data *data, |
434 | reference = trips[0].temperature / MCELSIUS; | 405 | int trip, u8 temp) |
435 | threshold_code = temp_to_code(data, reference); | 406 | { |
436 | if (threshold_code < 0) { | 407 | u32 th, con; |
437 | ret = threshold_code; | ||
438 | goto out; | ||
439 | } | ||
440 | writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); | ||
441 | 408 | ||
442 | for (i = 0; i < of_thermal_get_ntrips(tz); i++) { | 409 | th = readl(data->base + EXYNOS_THD_TEMP_RISE); |
443 | temp = trips[i].temperature / MCELSIUS; | 410 | th &= ~(0xff << 8 * trip); |
444 | writeb(temp - reference, data->base + | 411 | th |= temp_to_code(data, temp) << 8 * trip; |
445 | EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4); | 412 | writel(th, data->base + EXYNOS_THD_TEMP_RISE); |
413 | |||
414 | if (trip == 3) { | ||
415 | con = readl(data->base + EXYNOS_TMU_REG_CONTROL); | ||
416 | con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); | ||
417 | writel(con, data->base + EXYNOS_TMU_REG_CONTROL); | ||
446 | } | 418 | } |
419 | } | ||
447 | 420 | ||
448 | data->tmu_clear_irqs(data); | 421 | static void exynos4412_tmu_set_trip_hyst(struct exynos_tmu_data *data, |
449 | out: | 422 | int trip, u8 temp, u8 hyst) |
450 | return ret; | 423 | { |
424 | u32 th; | ||
425 | |||
426 | th = readl(data->base + EXYNOS_THD_TEMP_FALL); | ||
427 | th &= ~(0xff << 8 * trip); | ||
428 | if (hyst) | ||
429 | th |= temp_to_code(data, temp - hyst) << 8 * trip; | ||
430 | writel(th, data->base + EXYNOS_THD_TEMP_FALL); | ||
451 | } | 431 | } |
452 | 432 | ||
453 | static int exynos4412_tmu_initialize(struct platform_device *pdev) | 433 | static void exynos4412_tmu_initialize(struct platform_device *pdev) |
454 | { | 434 | { |
455 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 435 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
456 | const struct thermal_trip * const trips = | 436 | unsigned int trim_info, ctrl; |
457 | of_thermal_get_trip_points(data->tzd); | ||
458 | unsigned int status, trim_info, con, ctrl, rising_threshold; | ||
459 | int ret = 0, threshold_code, i; | ||
460 | unsigned long crit_temp = 0; | ||
461 | |||
462 | status = readb(data->base + EXYNOS_TMU_REG_STATUS); | ||
463 | if (!status) { | ||
464 | ret = -EBUSY; | ||
465 | goto out; | ||
466 | } | ||
467 | 437 | ||
468 | if (data->soc == SOC_ARCH_EXYNOS3250 || | 438 | if (data->soc == SOC_ARCH_EXYNOS3250 || |
469 | data->soc == SOC_ARCH_EXYNOS4412 || | 439 | data->soc == SOC_ARCH_EXYNOS4412 || |
@@ -485,58 +455,53 @@ static int exynos4412_tmu_initialize(struct platform_device *pdev) | |||
485 | trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); | 455 | trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); |
486 | 456 | ||
487 | sanitize_temp_error(data, trim_info); | 457 | sanitize_temp_error(data, trim_info); |
458 | } | ||
488 | 459 | ||
489 | /* Write temperature code for rising and falling threshold */ | 460 | static void exynos5433_tmu_set_trip_temp(struct exynos_tmu_data *data, |
490 | rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE); | 461 | int trip, u8 temp) |
491 | rising_threshold = get_th_reg(data, rising_threshold, false); | 462 | { |
492 | writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE); | 463 | unsigned int reg_off, j; |
493 | writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL); | 464 | u32 th; |
494 | |||
495 | data->tmu_clear_irqs(data); | ||
496 | 465 | ||
497 | /* if last threshold limit is also present */ | 466 | if (trip > 3) { |
498 | for (i = 0; i < of_thermal_get_ntrips(data->tzd); i++) { | 467 | reg_off = EXYNOS5433_THD_TEMP_RISE7_4; |
499 | if (trips[i].type == THERMAL_TRIP_CRITICAL) { | 468 | j = trip - 4; |
500 | crit_temp = trips[i].temperature; | 469 | } else { |
501 | break; | 470 | reg_off = EXYNOS5433_THD_TEMP_RISE3_0; |
502 | } | 471 | j = trip; |
503 | } | 472 | } |
504 | 473 | ||
505 | if (i == of_thermal_get_ntrips(data->tzd)) { | 474 | th = readl(data->base + reg_off); |
506 | pr_err("%s: No CRITICAL trip point defined at of-thermal.c!\n", | 475 | th &= ~(0xff << j * 8); |
507 | __func__); | 476 | th |= (temp_to_code(data, temp) << j * 8); |
508 | ret = -EINVAL; | 477 | writel(th, data->base + reg_off); |
509 | goto out; | 478 | } |
510 | } | ||
511 | 479 | ||
512 | threshold_code = temp_to_code(data, crit_temp / MCELSIUS); | 480 | static void exynos5433_tmu_set_trip_hyst(struct exynos_tmu_data *data, |
513 | /* 1-4 level to be assigned in th0 reg */ | 481 | int trip, u8 temp, u8 hyst) |
514 | rising_threshold &= ~(0xff << 8 * i); | 482 | { |
515 | rising_threshold |= threshold_code << 8 * i; | 483 | unsigned int reg_off, j; |
516 | writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE); | 484 | u32 th; |
517 | con = readl(data->base + EXYNOS_TMU_REG_CONTROL); | ||
518 | con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); | ||
519 | writel(con, data->base + EXYNOS_TMU_REG_CONTROL); | ||
520 | 485 | ||
521 | out: | 486 | if (trip > 3) { |
522 | return ret; | 487 | reg_off = EXYNOS5433_THD_TEMP_FALL7_4; |
488 | j = trip - 4; | ||
489 | } else { | ||
490 | reg_off = EXYNOS5433_THD_TEMP_FALL3_0; | ||
491 | j = trip; | ||
492 | } | ||
493 | |||
494 | th = readl(data->base + reg_off); | ||
495 | th &= ~(0xff << j * 8); | ||
496 | th |= (temp_to_code(data, temp - hyst) << j * 8); | ||
497 | writel(th, data->base + reg_off); | ||
523 | } | 498 | } |
524 | 499 | ||
525 | static int exynos5433_tmu_initialize(struct platform_device *pdev) | 500 | static void exynos5433_tmu_initialize(struct platform_device *pdev) |
526 | { | 501 | { |
527 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 502 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
528 | struct exynos_tmu_platform_data *pdata = data->pdata; | 503 | unsigned int trim_info; |
529 | struct thermal_zone_device *tz = data->tzd; | 504 | int sensor_id, cal_type; |
530 | unsigned int status, trim_info; | ||
531 | unsigned int rising_threshold = 0, falling_threshold = 0; | ||
532 | int temp, temp_hist; | ||
533 | int ret = 0, threshold_code, i, sensor_id, cal_type; | ||
534 | |||
535 | status = readb(data->base + EXYNOS_TMU_REG_STATUS); | ||
536 | if (!status) { | ||
537 | ret = -EBUSY; | ||
538 | goto out; | ||
539 | } | ||
540 | 505 | ||
541 | trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); | 506 | trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); |
542 | sanitize_temp_error(data, trim_info); | 507 | sanitize_temp_error(data, trim_info); |
@@ -552,227 +517,84 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev) | |||
552 | >> EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT; | 517 | >> EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT; |
553 | 518 | ||
554 | switch (cal_type) { | 519 | switch (cal_type) { |
555 | case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING: | ||
556 | pdata->cal_type = TYPE_ONE_POINT_TRIMMING; | ||
557 | break; | ||
558 | case EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING: | 520 | case EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING: |
559 | pdata->cal_type = TYPE_TWO_POINT_TRIMMING; | 521 | data->cal_type = TYPE_TWO_POINT_TRIMMING; |
560 | break; | 522 | break; |
523 | case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING: | ||
561 | default: | 524 | default: |
562 | pdata->cal_type = TYPE_ONE_POINT_TRIMMING; | 525 | data->cal_type = TYPE_ONE_POINT_TRIMMING; |
563 | break; | 526 | break; |
564 | } | 527 | } |
565 | 528 | ||
566 | dev_info(&pdev->dev, "Calibration type is %d-point calibration\n", | 529 | dev_info(&pdev->dev, "Calibration type is %d-point calibration\n", |
567 | cal_type ? 2 : 1); | 530 | cal_type ? 2 : 1); |
568 | |||
569 | /* Write temperature code for rising and falling threshold */ | ||
570 | for (i = 0; i < of_thermal_get_ntrips(tz); i++) { | ||
571 | int rising_reg_offset, falling_reg_offset; | ||
572 | int j = 0; | ||
573 | |||
574 | switch (i) { | ||
575 | case 0: | ||
576 | case 1: | ||
577 | case 2: | ||
578 | case 3: | ||
579 | rising_reg_offset = EXYNOS5433_THD_TEMP_RISE3_0; | ||
580 | falling_reg_offset = EXYNOS5433_THD_TEMP_FALL3_0; | ||
581 | j = i; | ||
582 | break; | ||
583 | case 4: | ||
584 | case 5: | ||
585 | case 6: | ||
586 | case 7: | ||
587 | rising_reg_offset = EXYNOS5433_THD_TEMP_RISE7_4; | ||
588 | falling_reg_offset = EXYNOS5433_THD_TEMP_FALL7_4; | ||
589 | j = i - 4; | ||
590 | break; | ||
591 | default: | ||
592 | continue; | ||
593 | } | ||
594 | |||
595 | /* Write temperature code for rising threshold */ | ||
596 | tz->ops->get_trip_temp(tz, i, &temp); | ||
597 | temp /= MCELSIUS; | ||
598 | threshold_code = temp_to_code(data, temp); | ||
599 | |||
600 | rising_threshold = readl(data->base + rising_reg_offset); | ||
601 | rising_threshold |= (threshold_code << j * 8); | ||
602 | writel(rising_threshold, data->base + rising_reg_offset); | ||
603 | |||
604 | /* Write temperature code for falling threshold */ | ||
605 | tz->ops->get_trip_hyst(tz, i, &temp_hist); | ||
606 | temp_hist = temp - (temp_hist / MCELSIUS); | ||
607 | threshold_code = temp_to_code(data, temp_hist); | ||
608 | |||
609 | falling_threshold = readl(data->base + falling_reg_offset); | ||
610 | falling_threshold &= ~(0xff << j * 8); | ||
611 | falling_threshold |= (threshold_code << j * 8); | ||
612 | writel(falling_threshold, data->base + falling_reg_offset); | ||
613 | } | ||
614 | |||
615 | data->tmu_clear_irqs(data); | ||
616 | out: | ||
617 | return ret; | ||
618 | } | 531 | } |
619 | 532 | ||
620 | static int exynos5440_tmu_initialize(struct platform_device *pdev) | 533 | static void exynos7_tmu_set_trip_temp(struct exynos_tmu_data *data, |
534 | int trip, u8 temp) | ||
621 | { | 535 | { |
622 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 536 | unsigned int reg_off, bit_off; |
623 | unsigned int trim_info = 0, con, rising_threshold; | 537 | u32 th; |
624 | int threshold_code; | ||
625 | int crit_temp = 0; | ||
626 | 538 | ||
627 | /* | 539 | reg_off = ((7 - trip) / 2) * 4; |
628 | * For exynos5440 soc triminfo value is swapped between TMU0 and | 540 | bit_off = ((8 - trip) % 2); |
629 | * TMU2, so the below logic is needed. | ||
630 | */ | ||
631 | switch (data->id) { | ||
632 | case 0: | ||
633 | trim_info = readl(data->base + EXYNOS5440_EFUSE_SWAP_OFFSET + | ||
634 | EXYNOS5440_TMU_S0_7_TRIM); | ||
635 | break; | ||
636 | case 1: | ||
637 | trim_info = readl(data->base + EXYNOS5440_TMU_S0_7_TRIM); | ||
638 | break; | ||
639 | case 2: | ||
640 | trim_info = readl(data->base - EXYNOS5440_EFUSE_SWAP_OFFSET + | ||
641 | EXYNOS5440_TMU_S0_7_TRIM); | ||
642 | } | ||
643 | sanitize_temp_error(data, trim_info); | ||
644 | 541 | ||
645 | /* Write temperature code for rising and falling threshold */ | 542 | th = readl(data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off); |
646 | rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0); | 543 | th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); |
647 | rising_threshold = get_th_reg(data, rising_threshold, false); | 544 | th |= temp_to_code(data, temp) << (16 * bit_off); |
648 | writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0); | 545 | writel(th, data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off); |
649 | writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1); | 546 | } |
650 | 547 | ||
651 | data->tmu_clear_irqs(data); | 548 | static void exynos7_tmu_set_trip_hyst(struct exynos_tmu_data *data, |
549 | int trip, u8 temp, u8 hyst) | ||
550 | { | ||
551 | unsigned int reg_off, bit_off; | ||
552 | u32 th; | ||
652 | 553 | ||
653 | /* if last threshold limit is also present */ | 554 | reg_off = ((7 - trip) / 2) * 4; |
654 | if (!data->tzd->ops->get_crit_temp(data->tzd, &crit_temp)) { | 555 | bit_off = ((8 - trip) % 2); |
655 | threshold_code = temp_to_code(data, crit_temp / MCELSIUS); | ||
656 | /* 5th level to be assigned in th2 reg */ | ||
657 | rising_threshold = | ||
658 | threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT; | ||
659 | writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH2); | ||
660 | con = readl(data->base + EXYNOS5440_TMU_S0_7_CTRL); | ||
661 | con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); | ||
662 | writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL); | ||
663 | } | ||
664 | /* Clear the PMIN in the common TMU register */ | ||
665 | if (!data->id) | ||
666 | writel(0, data->base_second + EXYNOS5440_TMU_PMIN); | ||
667 | 556 | ||
668 | return 0; | 557 | th = readl(data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off); |
558 | th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); | ||
559 | th |= temp_to_code(data, temp - hyst) << (16 * bit_off); | ||
560 | writel(th, data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off); | ||
669 | } | 561 | } |
670 | 562 | ||
671 | static int exynos7_tmu_initialize(struct platform_device *pdev) | 563 | static void exynos7_tmu_initialize(struct platform_device *pdev) |
672 | { | 564 | { |
673 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 565 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
674 | struct thermal_zone_device *tz = data->tzd; | 566 | unsigned int trim_info; |
675 | struct exynos_tmu_platform_data *pdata = data->pdata; | ||
676 | unsigned int status, trim_info; | ||
677 | unsigned int rising_threshold = 0, falling_threshold = 0; | ||
678 | int ret = 0, threshold_code, i; | ||
679 | int temp, temp_hist; | ||
680 | unsigned int reg_off, bit_off; | ||
681 | |||
682 | status = readb(data->base + EXYNOS_TMU_REG_STATUS); | ||
683 | if (!status) { | ||
684 | ret = -EBUSY; | ||
685 | goto out; | ||
686 | } | ||
687 | 567 | ||
688 | trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); | 568 | trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); |
689 | 569 | sanitize_temp_error(data, trim_info); | |
690 | data->temp_error1 = trim_info & EXYNOS7_TMU_TEMP_MASK; | ||
691 | if (!data->temp_error1 || | ||
692 | (pdata->min_efuse_value > data->temp_error1) || | ||
693 | (data->temp_error1 > pdata->max_efuse_value)) | ||
694 | data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK; | ||
695 | |||
696 | /* Write temperature code for rising and falling threshold */ | ||
697 | for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) { | ||
698 | /* | ||
699 | * On exynos7 there are 4 rising and 4 falling threshold | ||
700 | * registers (0x50-0x5c and 0x60-0x6c respectively). Each | ||
701 | * register holds the value of two threshold levels (at bit | ||
702 | * offsets 0 and 16). Based on the fact that there are atmost | ||
703 | * eight possible trigger levels, calculate the register and | ||
704 | * bit offsets where the threshold levels are to be written. | ||
705 | * | ||
706 | * e.g. EXYNOS7_THD_TEMP_RISE7_6 (0x50) | ||
707 | * [24:16] - Threshold level 7 | ||
708 | * [8:0] - Threshold level 6 | ||
709 | * e.g. EXYNOS7_THD_TEMP_RISE5_4 (0x54) | ||
710 | * [24:16] - Threshold level 5 | ||
711 | * [8:0] - Threshold level 4 | ||
712 | * | ||
713 | * and similarly for falling thresholds. | ||
714 | * | ||
715 | * Based on the above, calculate the register and bit offsets | ||
716 | * for rising/falling threshold levels and populate them. | ||
717 | */ | ||
718 | reg_off = ((7 - i) / 2) * 4; | ||
719 | bit_off = ((8 - i) % 2); | ||
720 | |||
721 | tz->ops->get_trip_temp(tz, i, &temp); | ||
722 | temp /= MCELSIUS; | ||
723 | |||
724 | tz->ops->get_trip_hyst(tz, i, &temp_hist); | ||
725 | temp_hist = temp - (temp_hist / MCELSIUS); | ||
726 | |||
727 | /* Set 9-bit temperature code for rising threshold levels */ | ||
728 | threshold_code = temp_to_code(data, temp); | ||
729 | rising_threshold = readl(data->base + | ||
730 | EXYNOS7_THD_TEMP_RISE7_6 + reg_off); | ||
731 | rising_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); | ||
732 | rising_threshold |= threshold_code << (16 * bit_off); | ||
733 | writel(rising_threshold, | ||
734 | data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off); | ||
735 | |||
736 | /* Set 9-bit temperature code for falling threshold levels */ | ||
737 | threshold_code = temp_to_code(data, temp_hist); | ||
738 | falling_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); | ||
739 | falling_threshold |= threshold_code << (16 * bit_off); | ||
740 | writel(falling_threshold, | ||
741 | data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off); | ||
742 | } | ||
743 | |||
744 | data->tmu_clear_irqs(data); | ||
745 | out: | ||
746 | return ret; | ||
747 | } | 570 | } |
748 | 571 | ||
749 | static void exynos4210_tmu_control(struct platform_device *pdev, bool on) | 572 | static void exynos4210_tmu_control(struct platform_device *pdev, bool on) |
750 | { | 573 | { |
751 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 574 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
752 | struct thermal_zone_device *tz = data->tzd; | 575 | struct thermal_zone_device *tz = data->tzd; |
753 | unsigned int con, interrupt_en; | 576 | unsigned int con, interrupt_en = 0, i; |
754 | 577 | ||
755 | con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); | 578 | con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); |
756 | 579 | ||
757 | if (on) { | 580 | if (on) { |
758 | con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); | 581 | for (i = 0; i < data->ntrip; i++) { |
759 | interrupt_en = | 582 | if (!of_thermal_is_trip_valid(tz, i)) |
760 | (of_thermal_is_trip_valid(tz, 3) | 583 | continue; |
761 | << EXYNOS_TMU_INTEN_RISE3_SHIFT) | | 584 | |
762 | (of_thermal_is_trip_valid(tz, 2) | 585 | interrupt_en |= |
763 | << EXYNOS_TMU_INTEN_RISE2_SHIFT) | | 586 | (1 << (EXYNOS_TMU_INTEN_RISE0_SHIFT + i * 4)); |
764 | (of_thermal_is_trip_valid(tz, 1) | 587 | } |
765 | << EXYNOS_TMU_INTEN_RISE1_SHIFT) | | ||
766 | (of_thermal_is_trip_valid(tz, 0) | ||
767 | << EXYNOS_TMU_INTEN_RISE0_SHIFT); | ||
768 | 588 | ||
769 | if (data->soc != SOC_ARCH_EXYNOS4210) | 589 | if (data->soc != SOC_ARCH_EXYNOS4210) |
770 | interrupt_en |= | 590 | interrupt_en |= |
771 | interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; | 591 | interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; |
592 | |||
593 | con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); | ||
772 | } else { | 594 | } else { |
773 | con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); | 595 | con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); |
774 | interrupt_en = 0; /* Disable all interrupts */ | ||
775 | } | 596 | } |
597 | |||
776 | writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN); | 598 | writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN); |
777 | writel(con, data->base + EXYNOS_TMU_REG_CONTROL); | 599 | writel(con, data->base + EXYNOS_TMU_REG_CONTROL); |
778 | } | 600 | } |
@@ -781,36 +603,25 @@ static void exynos5433_tmu_control(struct platform_device *pdev, bool on) | |||
781 | { | 603 | { |
782 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 604 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
783 | struct thermal_zone_device *tz = data->tzd; | 605 | struct thermal_zone_device *tz = data->tzd; |
784 | unsigned int con, interrupt_en, pd_det_en; | 606 | unsigned int con, interrupt_en = 0, pd_det_en, i; |
785 | 607 | ||
786 | con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); | 608 | con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); |
787 | 609 | ||
788 | if (on) { | 610 | if (on) { |
789 | con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); | 611 | for (i = 0; i < data->ntrip; i++) { |
790 | interrupt_en = | 612 | if (!of_thermal_is_trip_valid(tz, i)) |
791 | (of_thermal_is_trip_valid(tz, 7) | 613 | continue; |
792 | << EXYNOS7_TMU_INTEN_RISE7_SHIFT) | | 614 | |
793 | (of_thermal_is_trip_valid(tz, 6) | 615 | interrupt_en |= |
794 | << EXYNOS7_TMU_INTEN_RISE6_SHIFT) | | 616 | (1 << (EXYNOS7_TMU_INTEN_RISE0_SHIFT + i)); |
795 | (of_thermal_is_trip_valid(tz, 5) | 617 | } |
796 | << EXYNOS7_TMU_INTEN_RISE5_SHIFT) | | ||
797 | (of_thermal_is_trip_valid(tz, 4) | ||
798 | << EXYNOS7_TMU_INTEN_RISE4_SHIFT) | | ||
799 | (of_thermal_is_trip_valid(tz, 3) | ||
800 | << EXYNOS7_TMU_INTEN_RISE3_SHIFT) | | ||
801 | (of_thermal_is_trip_valid(tz, 2) | ||
802 | << EXYNOS7_TMU_INTEN_RISE2_SHIFT) | | ||
803 | (of_thermal_is_trip_valid(tz, 1) | ||
804 | << EXYNOS7_TMU_INTEN_RISE1_SHIFT) | | ||
805 | (of_thermal_is_trip_valid(tz, 0) | ||
806 | << EXYNOS7_TMU_INTEN_RISE0_SHIFT); | ||
807 | 618 | ||
808 | interrupt_en |= | 619 | interrupt_en |= |
809 | interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; | 620 | interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; |
810 | } else { | 621 | |
622 | con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); | ||
623 | } else | ||
811 | con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); | 624 | con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); |
812 | interrupt_en = 0; /* Disable all interrupts */ | ||
813 | } | ||
814 | 625 | ||
815 | pd_det_en = on ? EXYNOS5433_PD_DET_EN : 0; | 626 | pd_det_en = on ? EXYNOS5433_PD_DET_EN : 0; |
816 | 627 | ||
@@ -819,70 +630,31 @@ static void exynos5433_tmu_control(struct platform_device *pdev, bool on) | |||
819 | writel(con, data->base + EXYNOS_TMU_REG_CONTROL); | 630 | writel(con, data->base + EXYNOS_TMU_REG_CONTROL); |
820 | } | 631 | } |
821 | 632 | ||
822 | static void exynos5440_tmu_control(struct platform_device *pdev, bool on) | ||
823 | { | ||
824 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | ||
825 | struct thermal_zone_device *tz = data->tzd; | ||
826 | unsigned int con, interrupt_en; | ||
827 | |||
828 | con = get_con_reg(data, readl(data->base + EXYNOS5440_TMU_S0_7_CTRL)); | ||
829 | |||
830 | if (on) { | ||
831 | con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); | ||
832 | interrupt_en = | ||
833 | (of_thermal_is_trip_valid(tz, 3) | ||
834 | << EXYNOS5440_TMU_INTEN_RISE3_SHIFT) | | ||
835 | (of_thermal_is_trip_valid(tz, 2) | ||
836 | << EXYNOS5440_TMU_INTEN_RISE2_SHIFT) | | ||
837 | (of_thermal_is_trip_valid(tz, 1) | ||
838 | << EXYNOS5440_TMU_INTEN_RISE1_SHIFT) | | ||
839 | (of_thermal_is_trip_valid(tz, 0) | ||
840 | << EXYNOS5440_TMU_INTEN_RISE0_SHIFT); | ||
841 | interrupt_en |= | ||
842 | interrupt_en << EXYNOS5440_TMU_INTEN_FALL0_SHIFT; | ||
843 | } else { | ||
844 | con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); | ||
845 | interrupt_en = 0; /* Disable all interrupts */ | ||
846 | } | ||
847 | writel(interrupt_en, data->base + EXYNOS5440_TMU_S0_7_IRQEN); | ||
848 | writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL); | ||
849 | } | ||
850 | |||
851 | static void exynos7_tmu_control(struct platform_device *pdev, bool on) | 633 | static void exynos7_tmu_control(struct platform_device *pdev, bool on) |
852 | { | 634 | { |
853 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 635 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
854 | struct thermal_zone_device *tz = data->tzd; | 636 | struct thermal_zone_device *tz = data->tzd; |
855 | unsigned int con, interrupt_en; | 637 | unsigned int con, interrupt_en = 0, i; |
856 | 638 | ||
857 | con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); | 639 | con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); |
858 | 640 | ||
859 | if (on) { | 641 | if (on) { |
860 | con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); | 642 | for (i = 0; i < data->ntrip; i++) { |
861 | con |= (1 << EXYNOS7_PD_DET_EN_SHIFT); | 643 | if (!of_thermal_is_trip_valid(tz, i)) |
862 | interrupt_en = | 644 | continue; |
863 | (of_thermal_is_trip_valid(tz, 7) | 645 | |
864 | << EXYNOS7_TMU_INTEN_RISE7_SHIFT) | | 646 | interrupt_en |= |
865 | (of_thermal_is_trip_valid(tz, 6) | 647 | (1 << (EXYNOS7_TMU_INTEN_RISE0_SHIFT + i)); |
866 | << EXYNOS7_TMU_INTEN_RISE6_SHIFT) | | 648 | } |
867 | (of_thermal_is_trip_valid(tz, 5) | ||
868 | << EXYNOS7_TMU_INTEN_RISE5_SHIFT) | | ||
869 | (of_thermal_is_trip_valid(tz, 4) | ||
870 | << EXYNOS7_TMU_INTEN_RISE4_SHIFT) | | ||
871 | (of_thermal_is_trip_valid(tz, 3) | ||
872 | << EXYNOS7_TMU_INTEN_RISE3_SHIFT) | | ||
873 | (of_thermal_is_trip_valid(tz, 2) | ||
874 | << EXYNOS7_TMU_INTEN_RISE2_SHIFT) | | ||
875 | (of_thermal_is_trip_valid(tz, 1) | ||
876 | << EXYNOS7_TMU_INTEN_RISE1_SHIFT) | | ||
877 | (of_thermal_is_trip_valid(tz, 0) | ||
878 | << EXYNOS7_TMU_INTEN_RISE0_SHIFT); | ||
879 | 649 | ||
880 | interrupt_en |= | 650 | interrupt_en |= |
881 | interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; | 651 | interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; |
652 | |||
653 | con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); | ||
654 | con |= (1 << EXYNOS7_PD_DET_EN_SHIFT); | ||
882 | } else { | 655 | } else { |
883 | con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); | 656 | con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); |
884 | con &= ~(1 << EXYNOS7_PD_DET_EN_SHIFT); | 657 | con &= ~(1 << EXYNOS7_PD_DET_EN_SHIFT); |
885 | interrupt_en = 0; /* Disable all interrupts */ | ||
886 | } | 658 | } |
887 | 659 | ||
888 | writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN); | 660 | writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN); |
@@ -896,6 +668,12 @@ static int exynos_get_temp(void *p, int *temp) | |||
896 | 668 | ||
897 | if (!data || !data->tmu_read || !data->enabled) | 669 | if (!data || !data->tmu_read || !data->enabled) |
898 | return -EINVAL; | 670 | return -EINVAL; |
671 | else if (!data->enabled) | ||
672 | /* | ||
673 | * Called too early, probably | ||
674 | * from thermal_zone_of_sensor_register(). | ||
675 | */ | ||
676 | return -EAGAIN; | ||
899 | 677 | ||
900 | mutex_lock(&data->lock); | 678 | mutex_lock(&data->lock); |
901 | clk_enable(data->clk); | 679 | clk_enable(data->clk); |
@@ -919,10 +697,8 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val, | |||
919 | if (temp) { | 697 | if (temp) { |
920 | temp /= MCELSIUS; | 698 | temp /= MCELSIUS; |
921 | 699 | ||
922 | if (data->soc != SOC_ARCH_EXYNOS5440) { | 700 | val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT); |
923 | val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT); | 701 | val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT); |
924 | val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT); | ||
925 | } | ||
926 | if (data->soc == SOC_ARCH_EXYNOS7) { | 702 | if (data->soc == SOC_ARCH_EXYNOS7) { |
927 | val &= ~(EXYNOS7_EMUL_DATA_MASK << | 703 | val &= ~(EXYNOS7_EMUL_DATA_MASK << |
928 | EXYNOS7_EMUL_DATA_SHIFT); | 704 | EXYNOS7_EMUL_DATA_SHIFT); |
@@ -963,16 +739,6 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data, | |||
963 | writel(val, data->base + emul_con); | 739 | writel(val, data->base + emul_con); |
964 | } | 740 | } |
965 | 741 | ||
966 | static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data, | ||
967 | int temp) | ||
968 | { | ||
969 | unsigned int val; | ||
970 | |||
971 | val = readl(data->base + EXYNOS5440_TMU_S0_7_DEBUG); | ||
972 | val = get_emul_con_reg(data, val, temp); | ||
973 | writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG); | ||
974 | } | ||
975 | |||
976 | static int exynos_tmu_set_emulation(void *drv_data, int temp) | 742 | static int exynos_tmu_set_emulation(void *drv_data, int temp) |
977 | { | 743 | { |
978 | struct exynos_tmu_data *data = drv_data; | 744 | struct exynos_tmu_data *data = drv_data; |
@@ -995,7 +761,6 @@ out: | |||
995 | } | 761 | } |
996 | #else | 762 | #else |
997 | #define exynos4412_tmu_set_emulation NULL | 763 | #define exynos4412_tmu_set_emulation NULL |
998 | #define exynos5440_tmu_set_emulation NULL | ||
999 | static int exynos_tmu_set_emulation(void *drv_data, int temp) | 764 | static int exynos_tmu_set_emulation(void *drv_data, int temp) |
1000 | { return -EINVAL; } | 765 | { return -EINVAL; } |
1001 | #endif /* CONFIG_THERMAL_EMULATION */ | 766 | #endif /* CONFIG_THERMAL_EMULATION */ |
@@ -1013,11 +778,6 @@ static int exynos4412_tmu_read(struct exynos_tmu_data *data) | |||
1013 | return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP); | 778 | return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP); |
1014 | } | 779 | } |
1015 | 780 | ||
1016 | static int exynos5440_tmu_read(struct exynos_tmu_data *data) | ||
1017 | { | ||
1018 | return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP); | ||
1019 | } | ||
1020 | |||
1021 | static int exynos7_tmu_read(struct exynos_tmu_data *data) | 781 | static int exynos7_tmu_read(struct exynos_tmu_data *data) |
1022 | { | 782 | { |
1023 | return readw(data->base + EXYNOS_TMU_REG_CURRENT_TEMP) & | 783 | return readw(data->base + EXYNOS_TMU_REG_CURRENT_TEMP) & |
@@ -1028,20 +788,14 @@ static void exynos_tmu_work(struct work_struct *work) | |||
1028 | { | 788 | { |
1029 | struct exynos_tmu_data *data = container_of(work, | 789 | struct exynos_tmu_data *data = container_of(work, |
1030 | struct exynos_tmu_data, irq_work); | 790 | struct exynos_tmu_data, irq_work); |
1031 | unsigned int val_type; | ||
1032 | 791 | ||
1033 | if (!IS_ERR(data->clk_sec)) | 792 | if (!IS_ERR(data->clk_sec)) |
1034 | clk_enable(data->clk_sec); | 793 | clk_enable(data->clk_sec); |
1035 | /* Find which sensor generated this interrupt */ | ||
1036 | if (data->soc == SOC_ARCH_EXYNOS5440) { | ||
1037 | val_type = readl(data->base_second + EXYNOS5440_TMU_IRQ_STATUS); | ||
1038 | if (!((val_type >> data->id) & 0x1)) | ||
1039 | goto out; | ||
1040 | } | ||
1041 | if (!IS_ERR(data->clk_sec)) | 794 | if (!IS_ERR(data->clk_sec)) |
1042 | clk_disable(data->clk_sec); | 795 | clk_disable(data->clk_sec); |
1043 | 796 | ||
1044 | exynos_report_trigger(data); | 797 | thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED); |
798 | |||
1045 | mutex_lock(&data->lock); | 799 | mutex_lock(&data->lock); |
1046 | clk_enable(data->clk); | 800 | clk_enable(data->clk); |
1047 | 801 | ||
@@ -1050,7 +804,6 @@ static void exynos_tmu_work(struct work_struct *work) | |||
1050 | 804 | ||
1051 | clk_disable(data->clk); | 805 | clk_disable(data->clk); |
1052 | mutex_unlock(&data->lock); | 806 | mutex_unlock(&data->lock); |
1053 | out: | ||
1054 | enable_irq(data->irq); | 807 | enable_irq(data->irq); |
1055 | } | 808 | } |
1056 | 809 | ||
@@ -1085,15 +838,6 @@ static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data) | |||
1085 | writel(val_irq, data->base + tmu_intclear); | 838 | writel(val_irq, data->base + tmu_intclear); |
1086 | } | 839 | } |
1087 | 840 | ||
1088 | static void exynos5440_tmu_clear_irqs(struct exynos_tmu_data *data) | ||
1089 | { | ||
1090 | unsigned int val_irq; | ||
1091 | |||
1092 | val_irq = readl(data->base + EXYNOS5440_TMU_S0_7_IRQ); | ||
1093 | /* clear the interrupts */ | ||
1094 | writel(val_irq, data->base + EXYNOS5440_TMU_S0_7_IRQ); | ||
1095 | } | ||
1096 | |||
1097 | static irqreturn_t exynos_tmu_irq(int irq, void *id) | 841 | static irqreturn_t exynos_tmu_irq(int irq, void *id) |
1098 | { | 842 | { |
1099 | struct exynos_tmu_data *data = id; | 843 | struct exynos_tmu_data *data = id; |
@@ -1105,86 +849,41 @@ static irqreturn_t exynos_tmu_irq(int irq, void *id) | |||
1105 | } | 849 | } |
1106 | 850 | ||
1107 | static const struct of_device_id exynos_tmu_match[] = { | 851 | static const struct of_device_id exynos_tmu_match[] = { |
1108 | { .compatible = "samsung,exynos3250-tmu", }, | 852 | { |
1109 | { .compatible = "samsung,exynos4210-tmu", }, | 853 | .compatible = "samsung,exynos3250-tmu", |
1110 | { .compatible = "samsung,exynos4412-tmu", }, | 854 | .data = (const void *)SOC_ARCH_EXYNOS3250, |
1111 | { .compatible = "samsung,exynos5250-tmu", }, | 855 | }, { |
1112 | { .compatible = "samsung,exynos5260-tmu", }, | 856 | .compatible = "samsung,exynos4210-tmu", |
1113 | { .compatible = "samsung,exynos5420-tmu", }, | 857 | .data = (const void *)SOC_ARCH_EXYNOS4210, |
1114 | { .compatible = "samsung,exynos5420-tmu-ext-triminfo", }, | 858 | }, { |
1115 | { .compatible = "samsung,exynos5433-tmu", }, | 859 | .compatible = "samsung,exynos4412-tmu", |
1116 | { .compatible = "samsung,exynos5440-tmu", }, | 860 | .data = (const void *)SOC_ARCH_EXYNOS4412, |
1117 | { .compatible = "samsung,exynos7-tmu", }, | 861 | }, { |
1118 | { /* sentinel */ }, | 862 | .compatible = "samsung,exynos5250-tmu", |
863 | .data = (const void *)SOC_ARCH_EXYNOS5250, | ||
864 | }, { | ||
865 | .compatible = "samsung,exynos5260-tmu", | ||
866 | .data = (const void *)SOC_ARCH_EXYNOS5260, | ||
867 | }, { | ||
868 | .compatible = "samsung,exynos5420-tmu", | ||
869 | .data = (const void *)SOC_ARCH_EXYNOS5420, | ||
870 | }, { | ||
871 | .compatible = "samsung,exynos5420-tmu-ext-triminfo", | ||
872 | .data = (const void *)SOC_ARCH_EXYNOS5420_TRIMINFO, | ||
873 | }, { | ||
874 | .compatible = "samsung,exynos5433-tmu", | ||
875 | .data = (const void *)SOC_ARCH_EXYNOS5433, | ||
876 | }, { | ||
877 | .compatible = "samsung,exynos7-tmu", | ||
878 | .data = (const void *)SOC_ARCH_EXYNOS7, | ||
879 | }, | ||
880 | { }, | ||
1119 | }; | 881 | }; |
1120 | MODULE_DEVICE_TABLE(of, exynos_tmu_match); | 882 | MODULE_DEVICE_TABLE(of, exynos_tmu_match); |
1121 | 883 | ||
1122 | static int exynos_of_get_soc_type(struct device_node *np) | ||
1123 | { | ||
1124 | if (of_device_is_compatible(np, "samsung,exynos3250-tmu")) | ||
1125 | return SOC_ARCH_EXYNOS3250; | ||
1126 | else if (of_device_is_compatible(np, "samsung,exynos4210-tmu")) | ||
1127 | return SOC_ARCH_EXYNOS4210; | ||
1128 | else if (of_device_is_compatible(np, "samsung,exynos4412-tmu")) | ||
1129 | return SOC_ARCH_EXYNOS4412; | ||
1130 | else if (of_device_is_compatible(np, "samsung,exynos5250-tmu")) | ||
1131 | return SOC_ARCH_EXYNOS5250; | ||
1132 | else if (of_device_is_compatible(np, "samsung,exynos5260-tmu")) | ||
1133 | return SOC_ARCH_EXYNOS5260; | ||
1134 | else if (of_device_is_compatible(np, "samsung,exynos5420-tmu")) | ||
1135 | return SOC_ARCH_EXYNOS5420; | ||
1136 | else if (of_device_is_compatible(np, | ||
1137 | "samsung,exynos5420-tmu-ext-triminfo")) | ||
1138 | return SOC_ARCH_EXYNOS5420_TRIMINFO; | ||
1139 | else if (of_device_is_compatible(np, "samsung,exynos5433-tmu")) | ||
1140 | return SOC_ARCH_EXYNOS5433; | ||
1141 | else if (of_device_is_compatible(np, "samsung,exynos5440-tmu")) | ||
1142 | return SOC_ARCH_EXYNOS5440; | ||
1143 | else if (of_device_is_compatible(np, "samsung,exynos7-tmu")) | ||
1144 | return SOC_ARCH_EXYNOS7; | ||
1145 | |||
1146 | return -EINVAL; | ||
1147 | } | ||
1148 | |||
1149 | static int exynos_of_sensor_conf(struct device_node *np, | ||
1150 | struct exynos_tmu_platform_data *pdata) | ||
1151 | { | ||
1152 | u32 value; | ||
1153 | int ret; | ||
1154 | |||
1155 | of_node_get(np); | ||
1156 | |||
1157 | ret = of_property_read_u32(np, "samsung,tmu_gain", &value); | ||
1158 | pdata->gain = (u8)value; | ||
1159 | of_property_read_u32(np, "samsung,tmu_reference_voltage", &value); | ||
1160 | pdata->reference_voltage = (u8)value; | ||
1161 | of_property_read_u32(np, "samsung,tmu_noise_cancel_mode", &value); | ||
1162 | pdata->noise_cancel_mode = (u8)value; | ||
1163 | |||
1164 | of_property_read_u32(np, "samsung,tmu_efuse_value", | ||
1165 | &pdata->efuse_value); | ||
1166 | of_property_read_u32(np, "samsung,tmu_min_efuse_value", | ||
1167 | &pdata->min_efuse_value); | ||
1168 | of_property_read_u32(np, "samsung,tmu_max_efuse_value", | ||
1169 | &pdata->max_efuse_value); | ||
1170 | |||
1171 | of_property_read_u32(np, "samsung,tmu_first_point_trim", &value); | ||
1172 | pdata->first_point_trim = (u8)value; | ||
1173 | of_property_read_u32(np, "samsung,tmu_second_point_trim", &value); | ||
1174 | pdata->second_point_trim = (u8)value; | ||
1175 | of_property_read_u32(np, "samsung,tmu_default_temp_offset", &value); | ||
1176 | pdata->default_temp_offset = (u8)value; | ||
1177 | |||
1178 | of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type); | ||
1179 | |||
1180 | of_node_put(np); | ||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | static int exynos_map_dt_data(struct platform_device *pdev) | 884 | static int exynos_map_dt_data(struct platform_device *pdev) |
1185 | { | 885 | { |
1186 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); | 886 | struct exynos_tmu_data *data = platform_get_drvdata(pdev); |
1187 | struct exynos_tmu_platform_data *pdata; | ||
1188 | struct resource res; | 887 | struct resource res; |
1189 | 888 | ||
1190 | if (!data || !pdev->dev.of_node) | 889 | if (!data || !pdev->dev.of_node) |
@@ -1211,23 +910,22 @@ static int exynos_map_dt_data(struct platform_device *pdev) | |||
1211 | return -EADDRNOTAVAIL; | 910 | return -EADDRNOTAVAIL; |
1212 | } | 911 | } |
1213 | 912 | ||
1214 | pdata = devm_kzalloc(&pdev->dev, | 913 | data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev); |
1215 | sizeof(struct exynos_tmu_platform_data), | ||
1216 | GFP_KERNEL); | ||
1217 | if (!pdata) | ||
1218 | return -ENOMEM; | ||
1219 | |||
1220 | exynos_of_sensor_conf(pdev->dev.of_node, pdata); | ||
1221 | data->pdata = pdata; | ||
1222 | data->soc = exynos_of_get_soc_type(pdev->dev.of_node); | ||
1223 | 914 | ||
1224 | switch (data->soc) { | 915 | switch (data->soc) { |
1225 | case SOC_ARCH_EXYNOS4210: | 916 | case SOC_ARCH_EXYNOS4210: |
917 | data->tmu_set_trip_temp = exynos4210_tmu_set_trip_temp; | ||
918 | data->tmu_set_trip_hyst = exynos4210_tmu_set_trip_hyst; | ||
1226 | data->tmu_initialize = exynos4210_tmu_initialize; | 919 | data->tmu_initialize = exynos4210_tmu_initialize; |
1227 | data->tmu_control = exynos4210_tmu_control; | 920 | data->tmu_control = exynos4210_tmu_control; |
1228 | data->tmu_read = exynos4210_tmu_read; | 921 | data->tmu_read = exynos4210_tmu_read; |
1229 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; | 922 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; |
1230 | data->ntrip = 4; | 923 | data->ntrip = 4; |
924 | data->gain = 15; | ||
925 | data->reference_voltage = 7; | ||
926 | data->efuse_value = 55; | ||
927 | data->min_efuse_value = 40; | ||
928 | data->max_efuse_value = 100; | ||
1231 | break; | 929 | break; |
1232 | case SOC_ARCH_EXYNOS3250: | 930 | case SOC_ARCH_EXYNOS3250: |
1233 | case SOC_ARCH_EXYNOS4412: | 931 | case SOC_ARCH_EXYNOS4412: |
@@ -1235,48 +933,69 @@ static int exynos_map_dt_data(struct platform_device *pdev) | |||
1235 | case SOC_ARCH_EXYNOS5260: | 933 | case SOC_ARCH_EXYNOS5260: |
1236 | case SOC_ARCH_EXYNOS5420: | 934 | case SOC_ARCH_EXYNOS5420: |
1237 | case SOC_ARCH_EXYNOS5420_TRIMINFO: | 935 | case SOC_ARCH_EXYNOS5420_TRIMINFO: |
936 | data->tmu_set_trip_temp = exynos4412_tmu_set_trip_temp; | ||
937 | data->tmu_set_trip_hyst = exynos4412_tmu_set_trip_hyst; | ||
1238 | data->tmu_initialize = exynos4412_tmu_initialize; | 938 | data->tmu_initialize = exynos4412_tmu_initialize; |
1239 | data->tmu_control = exynos4210_tmu_control; | 939 | data->tmu_control = exynos4210_tmu_control; |
1240 | data->tmu_read = exynos4412_tmu_read; | 940 | data->tmu_read = exynos4412_tmu_read; |
1241 | data->tmu_set_emulation = exynos4412_tmu_set_emulation; | 941 | data->tmu_set_emulation = exynos4412_tmu_set_emulation; |
1242 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; | 942 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; |
1243 | data->ntrip = 4; | 943 | data->ntrip = 4; |
944 | data->gain = 8; | ||
945 | data->reference_voltage = 16; | ||
946 | data->efuse_value = 55; | ||
947 | if (data->soc != SOC_ARCH_EXYNOS5420 && | ||
948 | data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO) | ||
949 | data->min_efuse_value = 40; | ||
950 | else | ||
951 | data->min_efuse_value = 0; | ||
952 | data->max_efuse_value = 100; | ||
1244 | break; | 953 | break; |
1245 | case SOC_ARCH_EXYNOS5433: | 954 | case SOC_ARCH_EXYNOS5433: |
955 | data->tmu_set_trip_temp = exynos5433_tmu_set_trip_temp; | ||
956 | data->tmu_set_trip_hyst = exynos5433_tmu_set_trip_hyst; | ||
1246 | data->tmu_initialize = exynos5433_tmu_initialize; | 957 | data->tmu_initialize = exynos5433_tmu_initialize; |
1247 | data->tmu_control = exynos5433_tmu_control; | 958 | data->tmu_control = exynos5433_tmu_control; |
1248 | data->tmu_read = exynos4412_tmu_read; | 959 | data->tmu_read = exynos4412_tmu_read; |
1249 | data->tmu_set_emulation = exynos4412_tmu_set_emulation; | 960 | data->tmu_set_emulation = exynos4412_tmu_set_emulation; |
1250 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; | 961 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; |
1251 | data->ntrip = 8; | 962 | data->ntrip = 8; |
1252 | break; | 963 | data->gain = 8; |
1253 | case SOC_ARCH_EXYNOS5440: | 964 | if (res.start == EXYNOS5433_G3D_BASE) |
1254 | data->tmu_initialize = exynos5440_tmu_initialize; | 965 | data->reference_voltage = 23; |
1255 | data->tmu_control = exynos5440_tmu_control; | 966 | else |
1256 | data->tmu_read = exynos5440_tmu_read; | 967 | data->reference_voltage = 16; |
1257 | data->tmu_set_emulation = exynos5440_tmu_set_emulation; | 968 | data->efuse_value = 75; |
1258 | data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; | 969 | data->min_efuse_value = 40; |
1259 | data->ntrip = 4; | 970 | data->max_efuse_value = 150; |
1260 | break; | 971 | break; |
1261 | case SOC_ARCH_EXYNOS7: | 972 | case SOC_ARCH_EXYNOS7: |
973 | data->tmu_set_trip_temp = exynos7_tmu_set_trip_temp; | ||
974 | data->tmu_set_trip_hyst = exynos7_tmu_set_trip_hyst; | ||
1262 | data->tmu_initialize = exynos7_tmu_initialize; | 975 | data->tmu_initialize = exynos7_tmu_initialize; |
1263 | data->tmu_control = exynos7_tmu_control; | 976 | data->tmu_control = exynos7_tmu_control; |
1264 | data->tmu_read = exynos7_tmu_read; | 977 | data->tmu_read = exynos7_tmu_read; |
1265 | data->tmu_set_emulation = exynos4412_tmu_set_emulation; | 978 | data->tmu_set_emulation = exynos4412_tmu_set_emulation; |
1266 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; | 979 | data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; |
1267 | data->ntrip = 8; | 980 | data->ntrip = 8; |
981 | data->gain = 9; | ||
982 | data->reference_voltage = 17; | ||
983 | data->efuse_value = 75; | ||
984 | data->min_efuse_value = 15; | ||
985 | data->max_efuse_value = 100; | ||
1268 | break; | 986 | break; |
1269 | default: | 987 | default: |
1270 | dev_err(&pdev->dev, "Platform not supported\n"); | 988 | dev_err(&pdev->dev, "Platform not supported\n"); |
1271 | return -EINVAL; | 989 | return -EINVAL; |
1272 | } | 990 | } |
1273 | 991 | ||
992 | data->cal_type = TYPE_ONE_POINT_TRIMMING; | ||
993 | |||
1274 | /* | 994 | /* |
1275 | * Check if the TMU shares some registers and then try to map the | 995 | * Check if the TMU shares some registers and then try to map the |
1276 | * memory of common registers. | 996 | * memory of common registers. |
1277 | */ | 997 | */ |
1278 | if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO && | 998 | if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO) |
1279 | data->soc != SOC_ARCH_EXYNOS5440) | ||
1280 | return 0; | 999 | return 0; |
1281 | 1000 | ||
1282 | if (of_address_to_resource(pdev->dev.of_node, 1, &res)) { | 1001 | if (of_address_to_resource(pdev->dev.of_node, 1, &res)) { |
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h deleted file mode 100644 index 5149c2a3030c..000000000000 --- a/drivers/thermal/samsung/exynos_tmu.h +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /* | ||
2 | * exynos_tmu.h - 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.daniel@samsung.com> | ||
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 | #ifndef _EXYNOS_TMU_H | ||
24 | #define _EXYNOS_TMU_H | ||
25 | #include <linux/cpu_cooling.h> | ||
26 | #include <dt-bindings/thermal/thermal_exynos.h> | ||
27 | |||
28 | enum soc_type { | ||
29 | SOC_ARCH_EXYNOS3250 = 1, | ||
30 | SOC_ARCH_EXYNOS4210, | ||
31 | SOC_ARCH_EXYNOS4412, | ||
32 | SOC_ARCH_EXYNOS5250, | ||
33 | SOC_ARCH_EXYNOS5260, | ||
34 | SOC_ARCH_EXYNOS5420, | ||
35 | SOC_ARCH_EXYNOS5420_TRIMINFO, | ||
36 | SOC_ARCH_EXYNOS5433, | ||
37 | SOC_ARCH_EXYNOS5440, | ||
38 | SOC_ARCH_EXYNOS7, | ||
39 | }; | ||
40 | |||
41 | /** | ||
42 | * struct exynos_tmu_platform_data | ||
43 | * @gain: gain of amplifier in the positive-TC generator block | ||
44 | * 0 < gain <= 15 | ||
45 | * @reference_voltage: reference voltage of amplifier | ||
46 | * in the positive-TC generator block | ||
47 | * 0 < reference_voltage <= 31 | ||
48 | * @noise_cancel_mode: noise cancellation mode | ||
49 | * 000, 100, 101, 110 and 111 can be different modes | ||
50 | * @type: determines the type of SOC | ||
51 | * @efuse_value: platform defined fuse value | ||
52 | * @min_efuse_value: minimum valid trimming data | ||
53 | * @max_efuse_value: maximum valid trimming data | ||
54 | * @default_temp_offset: default temperature offset in case of no trimming | ||
55 | * @cal_type: calibration type for temperature | ||
56 | * | ||
57 | * This structure is required for configuration of exynos_tmu driver. | ||
58 | */ | ||
59 | struct exynos_tmu_platform_data { | ||
60 | u8 gain; | ||
61 | u8 reference_voltage; | ||
62 | u8 noise_cancel_mode; | ||
63 | |||
64 | u32 efuse_value; | ||
65 | u32 min_efuse_value; | ||
66 | u32 max_efuse_value; | ||
67 | u8 first_point_trim; | ||
68 | u8 second_point_trim; | ||
69 | u8 default_temp_offset; | ||
70 | |||
71 | enum soc_type type; | ||
72 | u32 cal_type; | ||
73 | }; | ||
74 | |||
75 | #endif /* _EXYNOS_TMU_H */ | ||
diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 455b58ce2652..207a79838643 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c | |||
@@ -241,31 +241,6 @@ struct tegra_soctherm { | |||
241 | }; | 241 | }; |
242 | 242 | ||
243 | /** | 243 | /** |
244 | * clk_writel() - writes a value to a CAR register | ||
245 | * @ts: pointer to a struct tegra_soctherm | ||
246 | * @v: the value to write | ||
247 | * @reg: the register offset | ||
248 | * | ||
249 | * Writes @v to @reg. No return value. | ||
250 | */ | ||
251 | static inline void clk_writel(struct tegra_soctherm *ts, u32 value, u32 reg) | ||
252 | { | ||
253 | writel(value, (ts->clk_regs + reg)); | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * clk_readl() - reads specified register from CAR IP block | ||
258 | * @ts: pointer to a struct tegra_soctherm | ||
259 | * @reg: register address to be read | ||
260 | * | ||
261 | * Return: the value of the register | ||
262 | */ | ||
263 | static inline u32 clk_readl(struct tegra_soctherm *ts, u32 reg) | ||
264 | { | ||
265 | return readl(ts->clk_regs + reg); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * ccroc_writel() - writes a value to a CCROC register | 244 | * ccroc_writel() - writes a value to a CCROC register |
270 | * @ts: pointer to a struct tegra_soctherm | 245 | * @ts: pointer to a struct tegra_soctherm |
271 | * @v: the value to write | 246 | * @v: the value to write |
@@ -926,7 +901,7 @@ static int throt_set_cdev_state(struct thermal_cooling_device *cdev, | |||
926 | return 0; | 901 | return 0; |
927 | } | 902 | } |
928 | 903 | ||
929 | static struct thermal_cooling_device_ops throt_cooling_ops = { | 904 | static const struct thermal_cooling_device_ops throt_cooling_ops = { |
930 | .get_max_state = throt_get_cdev_max_state, | 905 | .get_max_state = throt_get_cdev_max_state, |
931 | .get_cur_state = throt_get_cdev_cur_state, | 906 | .get_cur_state = throt_get_cdev_cur_state, |
932 | .set_cur_state = throt_set_cdev_state, | 907 | .set_cur_state = throt_set_cdev_state, |
@@ -1207,9 +1182,9 @@ static void tegra_soctherm_throttle(struct device *dev) | |||
1207 | } else { | 1182 | } else { |
1208 | writel(v, ts->regs + THROT_GLOBAL_CFG); | 1183 | writel(v, ts->regs + THROT_GLOBAL_CFG); |
1209 | 1184 | ||
1210 | v = clk_readl(ts, CAR_SUPER_CCLKG_DIVIDER); | 1185 | v = readl(ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER); |
1211 | v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1); | 1186 | v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1); |
1212 | clk_writel(ts, v, CAR_SUPER_CCLKG_DIVIDER); | 1187 | writel(v, ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER); |
1213 | } | 1188 | } |
1214 | 1189 | ||
1215 | /* initialize stats collection */ | 1190 | /* initialize stats collection */ |
diff --git a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c index cd9a304fb571..6ac037098b52 100644 --- a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c | |||
@@ -310,7 +310,7 @@ omap5430_adc_to_temp[ | |||
310 | 119800, 120200, 120600, 121000, 121400, 121800, 122400, 122600, 123000, | 310 | 119800, 120200, 120600, 121000, 121400, 121800, 122400, 122600, 123000, |
311 | 123400, | 311 | 123400, |
312 | /* Index 940 - 945 */ | 312 | /* Index 940 - 945 */ |
313 | 123800, 1242000, 124600, 124900, 125000, 125000, | 313 | 123800, 124200, 124600, 124900, 125000, 125000, |
314 | }; | 314 | }; |
315 | 315 | ||
316 | /* OMAP54xx ES2.0 data */ | 316 | /* OMAP54xx ES2.0 data */ |
diff --git a/drivers/thermal/uniphier_thermal.c b/drivers/thermal/uniphier_thermal.c index 95704732f760..55477d74d591 100644 --- a/drivers/thermal/uniphier_thermal.c +++ b/drivers/thermal/uniphier_thermal.c | |||
@@ -365,6 +365,10 @@ static const struct of_device_id uniphier_tm_dt_ids[] = { | |||
365 | .compatible = "socionext,uniphier-ld20-thermal", | 365 | .compatible = "socionext,uniphier-ld20-thermal", |
366 | .data = &uniphier_ld20_tm_data, | 366 | .data = &uniphier_ld20_tm_data, |
367 | }, | 367 | }, |
368 | { | ||
369 | .compatible = "socionext,uniphier-pxs3-thermal", | ||
370 | .data = &uniphier_ld20_tm_data, | ||
371 | }, | ||
368 | { /* sentinel */ } | 372 | { /* sentinel */ } |
369 | }; | 373 | }; |
370 | MODULE_DEVICE_TABLE(of, uniphier_tm_dt_ids); | 374 | MODULE_DEVICE_TABLE(of, uniphier_tm_dt_ids); |