diff options
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); |
