^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright 2013 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/cpu_cooling.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/thermal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/nvmem-consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define REG_SET 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define REG_CLR 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define REG_TOG 0xc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* i.MX6 specific */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define IMX6_MISC0 0x0150
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define IMX6_MISC0_REFTOP_SELBIASOFF (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define IMX6_MISC1 0x0160
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define IMX6_MISC1_IRQ_TEMPHIGH (1 << 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define IMX6_MISC1_IRQ_TEMPLOW (1 << 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define IMX6_MISC1_IRQ_TEMPPANIC (1 << 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define IMX6_TEMPSENSE0 0x0180
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define IMX6_TEMPSENSE0_ALARM_VALUE_MASK (0xfff << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define IMX6_TEMPSENSE0_TEMP_CNT_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define IMX6_TEMPSENSE0_TEMP_CNT_MASK (0xfff << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define IMX6_TEMPSENSE0_FINISHED (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define IMX6_TEMPSENSE0_MEASURE_TEMP (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define IMX6_TEMPSENSE0_POWER_DOWN (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define IMX6_TEMPSENSE1 0x0190
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define IMX6_TEMPSENSE1_MEASURE_FREQ 0xffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define OCOTP_MEM0 0x0480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define OCOTP_ANA1 0x04e0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define IMX6_TEMPSENSE2 0x0290
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define IMX6_TEMPSENSE2_LOW_VALUE_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define IMX6_TEMPSENSE2_LOW_VALUE_MASK 0xfff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define IMX6_TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* i.MX7 specific */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define IMX7_ANADIG_DIGPROG 0x800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define IMX7_TEMPSENSE0 0x300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define IMX7_TEMPSENSE0_PANIC_ALARM_MASK (0x1ff << 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define IMX7_TEMPSENSE0_HIGH_ALARM_MASK (0x1ff << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define IMX7_TEMPSENSE0_LOW_ALARM_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define IMX7_TEMPSENSE0_LOW_ALARM_MASK 0x1ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define IMX7_TEMPSENSE1 0x310
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define IMX7_TEMPSENSE1_MEASURE_FREQ_MASK (0xffff << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define IMX7_TEMPSENSE1_FINISHED (1 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define IMX7_TEMPSENSE1_MEASURE_TEMP (1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define IMX7_TEMPSENSE1_POWER_DOWN (1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define IMX7_TEMPSENSE1_TEMP_VALUE_MASK 0x1ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* The driver supports 1 passive trip point and 1 critical trip point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) enum imx_thermal_trip {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) IMX_TRIP_PASSIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) IMX_TRIP_CRITICAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) IMX_TRIP_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define IMX_POLLING_DELAY 2000 /* millisecond */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define IMX_PASSIVE_DELAY 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define TEMPMON_IMX6Q 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define TEMPMON_IMX6SX 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define TEMPMON_IMX7D 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct thermal_soc_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 sensor_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u32 power_down_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u32 measure_temp_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u32 measure_freq_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u32 measure_freq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u32 measure_freq_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u32 temp_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u32 temp_value_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u32 temp_value_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u32 temp_valid_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 panic_alarm_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 panic_alarm_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 panic_alarm_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u32 high_alarm_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u32 high_alarm_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u32 high_alarm_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u32 low_alarm_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u32 low_alarm_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u32 low_alarm_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static struct thermal_soc_data thermal_imx6q_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .version = TEMPMON_IMX6Q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .sensor_ctrl = IMX6_TEMPSENSE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .measure_freq_ctrl = IMX6_TEMPSENSE1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .temp_data = IMX6_TEMPSENSE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .high_alarm_ctrl = IMX6_TEMPSENSE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static struct thermal_soc_data thermal_imx6sx_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .version = TEMPMON_IMX6SX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .sensor_ctrl = IMX6_TEMPSENSE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .measure_freq_ctrl = IMX6_TEMPSENSE1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .temp_data = IMX6_TEMPSENSE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .high_alarm_ctrl = IMX6_TEMPSENSE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .panic_alarm_ctrl = IMX6_TEMPSENSE2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .panic_alarm_mask = IMX6_TEMPSENSE2_PANIC_VALUE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .panic_alarm_shift = IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .low_alarm_ctrl = IMX6_TEMPSENSE2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .low_alarm_mask = IMX6_TEMPSENSE2_LOW_VALUE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .low_alarm_shift = IMX6_TEMPSENSE2_LOW_VALUE_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static struct thermal_soc_data thermal_imx7d_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .version = TEMPMON_IMX7D,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .sensor_ctrl = IMX7_TEMPSENSE1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .power_down_mask = IMX7_TEMPSENSE1_POWER_DOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .measure_temp_mask = IMX7_TEMPSENSE1_MEASURE_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .measure_freq_ctrl = IMX7_TEMPSENSE1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .measure_freq_shift = IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .measure_freq_mask = IMX7_TEMPSENSE1_MEASURE_FREQ_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .temp_data = IMX7_TEMPSENSE1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .temp_value_mask = IMX7_TEMPSENSE1_TEMP_VALUE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .temp_value_shift = IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .temp_valid_mask = IMX7_TEMPSENSE1_FINISHED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .panic_alarm_ctrl = IMX7_TEMPSENSE1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .panic_alarm_mask = IMX7_TEMPSENSE0_PANIC_ALARM_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .panic_alarm_shift = IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .high_alarm_ctrl = IMX7_TEMPSENSE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .high_alarm_mask = IMX7_TEMPSENSE0_HIGH_ALARM_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .high_alarm_shift = IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .low_alarm_ctrl = IMX7_TEMPSENSE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .low_alarm_mask = IMX7_TEMPSENSE0_LOW_ALARM_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .low_alarm_shift = IMX7_TEMPSENSE0_LOW_ALARM_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct imx_thermal_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct cpufreq_policy *policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct thermal_zone_device *tz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct thermal_cooling_device *cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct regmap *tempmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u32 c1, c2; /* See formula in imx_init_calib() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int temp_passive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int temp_critical;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int temp_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int alarm_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int last_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) bool irq_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct clk *thermal_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) const struct thermal_soc_data *socdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) const char *temp_grade;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static void imx_set_panic_temp(struct imx_thermal_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int panic_temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) const struct thermal_soc_data *soc_data = data->socdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct regmap *map = data->tempmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int critical_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) critical_value = (data->c2 - panic_temp) / data->c1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) regmap_write(map, soc_data->panic_alarm_ctrl + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) soc_data->panic_alarm_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) regmap_write(map, soc_data->panic_alarm_ctrl + REG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) critical_value << soc_data->panic_alarm_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static void imx_set_alarm_temp(struct imx_thermal_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int alarm_temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct regmap *map = data->tempmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) const struct thermal_soc_data *soc_data = data->socdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int alarm_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) data->alarm_temp = alarm_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (data->socdata->version == TEMPMON_IMX7D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) alarm_value = alarm_temp / 1000 + data->c1 - 25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) alarm_value = (data->c2 - alarm_temp) / data->c1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) regmap_write(map, soc_data->high_alarm_ctrl + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) soc_data->high_alarm_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) regmap_write(map, soc_data->high_alarm_ctrl + REG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) alarm_value << soc_data->high_alarm_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct imx_thermal_data *data = tz->devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) const struct thermal_soc_data *soc_data = data->socdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct regmap *map = data->tempmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) unsigned int n_meas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ret = pm_runtime_resume_and_get(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) regmap_read(map, soc_data->temp_data, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if ((val & soc_data->temp_valid_mask) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) dev_dbg(&tz->device, "temp measurement never finished\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) n_meas = (val & soc_data->temp_value_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) >> soc_data->temp_value_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* See imx_init_calib() for formula derivation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (data->socdata->version == TEMPMON_IMX7D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *temp = (n_meas - data->c1 + 25) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) *temp = data->c2 - n_meas * data->c1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (data->socdata->version == TEMPMON_IMX6Q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (data->alarm_temp == data->temp_passive &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *temp >= data->temp_passive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) imx_set_alarm_temp(data, data->temp_critical);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (data->alarm_temp == data->temp_critical &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) *temp < data->temp_passive) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) imx_set_alarm_temp(data, data->temp_passive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) dev_dbg(&tz->device, "thermal alarm off: T < %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) data->alarm_temp / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (*temp != data->last_temp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) dev_dbg(&tz->device, "millicelsius: %d\n", *temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) data->last_temp = *temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* Reenable alarm IRQ if temperature below alarm temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!data->irq_enabled && *temp < data->alarm_temp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) data->irq_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) enable_irq(data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) pm_runtime_put(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int imx_change_mode(struct thermal_zone_device *tz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) enum thermal_device_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct imx_thermal_data *data = tz->devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (mode == THERMAL_DEVICE_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) pm_runtime_get(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (!data->irq_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) data->irq_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) enable_irq(data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) pm_runtime_put(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (data->irq_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) disable_irq(data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) data->irq_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) enum thermal_trip_type *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) *type = (trip == IMX_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) THERMAL_TRIP_CRITICAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct imx_thermal_data *data = tz->devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) *temp = data->temp_critical;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int *temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct imx_thermal_data *data = tz->devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) *temp = (trip == IMX_TRIP_PASSIVE) ? data->temp_passive :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) data->temp_critical;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) int temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct imx_thermal_data *data = tz->devdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) ret = pm_runtime_resume_and_get(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /* do not allow changing critical threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (trip == IMX_TRIP_CRITICAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* do not allow passive to be set higher than critical */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (temp < 0 || temp > data->temp_critical)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) data->temp_passive = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) imx_set_alarm_temp(data, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) pm_runtime_put(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static int imx_bind(struct thermal_zone_device *tz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct thermal_cooling_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) ret = thermal_zone_bind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) THERMAL_NO_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) THERMAL_NO_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) THERMAL_WEIGHT_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) dev_err(&tz->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) "binding zone %s with cdev %s failed:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) tz->type, cdev->type, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static int imx_unbind(struct thermal_zone_device *tz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct thermal_cooling_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) ret = thermal_zone_unbind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) dev_err(&tz->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) "unbinding zone %s with cdev %s failed:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) tz->type, cdev->type, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static struct thermal_zone_device_ops imx_tz_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .bind = imx_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .unbind = imx_unbind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .get_temp = imx_get_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) .change_mode = imx_change_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .get_trip_type = imx_get_trip_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .get_trip_temp = imx_get_trip_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) .get_crit_temp = imx_get_crit_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .set_trip_temp = imx_set_trip_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) struct imx_thermal_data *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) int n1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) u64 temp64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (ocotp_ana1 == 0 || ocotp_ana1 == ~0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) dev_err(&pdev->dev, "invalid sensor calibration data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * On i.MX7D, we only use the calibration data at 25C to get the temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * Tmeas = ( Nmeas - n1) + 25; n1 is the fuse value for 25C.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (data->socdata->version == TEMPMON_IMX7D) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) data->c1 = (ocotp_ana1 >> 9) & 0x1ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * The sensor is calibrated at 25 °C (aka T1) and the value measured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * (aka N1) at this temperature is provided in bits [31:20] in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * i.MX's OCOTP value ANA1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * To find the actual temperature T, the following formula has to be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * when reading value n from the sensor:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * T = T1 + (N - N1) / (0.4148468 - 0.0015423 * N1) °C + 3.580661 °C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * = [T1' - N1 / (0.4148468 - 0.0015423 * N1) °C] + N / (0.4148468 - 0.0015423 * N1) °C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * = [T1' + N1 / (0.0015423 * N1 - 0.4148468) °C] - N / (0.0015423 * N1 - 0.4148468) °C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * = c2 - c1 * N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * T1' = 28.580661 °C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * c1 = 1 / (0.0015423 * N1 - 0.4297157) °C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * c2 = T1' + N1 / (0.0015423 * N1 - 0.4148468) °C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * = T1' + N1 * c1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) n1 = ocotp_ana1 >> 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) temp64 = 10000000; /* use 10^7 as fixed point constant for values in formula */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) temp64 *= 1000; /* to get result in °mC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) do_div(temp64, 15423 * n1 - 4148468);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) data->c1 = temp64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) data->c2 = n1 * data->c1 + 28581;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct imx_thermal_data *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* The maximum die temp is specified by the Temperature Grade */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) switch ((ocotp_mem0 >> 6) & 0x3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) case 0: /* Commercial (0 to 95 °C) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) data->temp_grade = "Commercial";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) data->temp_max = 95000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) case 1: /* Extended Commercial (-20 °C to 105 °C) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) data->temp_grade = "Extended Commercial";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) data->temp_max = 105000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) case 2: /* Industrial (-40 °C to 105 °C) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) data->temp_grade = "Industrial";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) data->temp_max = 105000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) case 3: /* Automotive (-40 °C to 125 °C) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) data->temp_grade = "Automotive";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) data->temp_max = 125000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * Set the critical trip point at 5 °C under max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * Set the passive trip point at 10 °C under max (changeable via sysfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) data->temp_critical = data->temp_max - (1000 * 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) data->temp_passive = data->temp_max - (1000 * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static int imx_init_from_tempmon_data(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) "fsl,tempmon-data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (IS_ERR(map)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ret = PTR_ERR(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) ret = regmap_read(map, OCOTP_ANA1, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = imx_init_calib(pdev, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ret = regmap_read(map, OCOTP_MEM0, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) imx_init_temp_grade(pdev, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static int imx_init_from_nvmem_cells(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ret = nvmem_cell_read_u32(&pdev->dev, "calib", &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) ret = imx_init_calib(pdev, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) ret = nvmem_cell_read_u32(&pdev->dev, "temp_grade", &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) imx_init_temp_grade(pdev, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static irqreturn_t imx_thermal_alarm_irq(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct imx_thermal_data *data = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) disable_irq_nosync(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) data->irq_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return IRQ_WAKE_THREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct imx_thermal_data *data = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) data->alarm_temp / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) thermal_zone_device_update(data->tz, THERMAL_EVENT_UNSPECIFIED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static const struct of_device_id of_imx_thermal_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) { .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) { .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) { .compatible = "fsl,imx7d-tempmon", .data = &thermal_imx7d_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) { /* end */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) #ifdef CONFIG_CPU_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * Create cooling device in case no #cooling-cells property is available in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * CPU node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) data->policy = cpufreq_cpu_get(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (!data->policy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) pr_debug("%s: CPUFreq policy not found\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) np = of_get_cpu_node(data->policy->cpu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!np || !of_find_property(np, "#cooling-cells", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) data->cdev = cpufreq_cooling_register(data->policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (IS_ERR(data->cdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) ret = PTR_ERR(data->cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) cpufreq_cpu_put(data->policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) cpufreq_cooling_unregister(data->cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) cpufreq_cpu_put(data->policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static inline int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) static inline void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static int imx_thermal_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct imx_thermal_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int measure_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) data->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (IS_ERR(map)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ret = PTR_ERR(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) dev_err(&pdev->dev, "failed to get tempmon regmap: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) data->tempmon = map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) data->socdata = of_device_get_match_data(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (!data->socdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dev_err(&pdev->dev, "no device match found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (data->socdata->version == TEMPMON_IMX6SX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) regmap_write(map, IMX6_MISC1 + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) IMX6_MISC1_IRQ_TEMPHIGH | IMX6_MISC1_IRQ_TEMPLOW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) | IMX6_MISC1_IRQ_TEMPPANIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * reset value of LOW ALARM is incorrect, set it to lowest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * value to avoid false trigger of low alarm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) regmap_write(map, data->socdata->low_alarm_ctrl + REG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) data->socdata->low_alarm_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) data->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (data->irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) ret = imx_init_from_nvmem_cells(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return dev_err_probe(&pdev->dev, ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) "failed to init from nvmem\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) ret = imx_init_from_tempmon_data(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) dev_err(&pdev->dev, "failed to init from fsl,tempmon-data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) /* Make sure sensor is in known good state for measurements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) data->socdata->power_down_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) data->socdata->measure_temp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) data->socdata->measure_freq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (data->socdata->version != TEMPMON_IMX7D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) regmap_write(map, IMX6_MISC0 + REG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) IMX6_MISC0_REFTOP_SELBIASOFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) data->socdata->power_down_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) ret = imx_thermal_register_legacy_cooling(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return dev_err_probe(&pdev->dev, ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) "failed to register cpufreq cooling device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (IS_ERR(data->thermal_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) ret = PTR_ERR(data->thermal_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) "failed to get thermal clk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) goto legacy_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * Thermal sensor needs clk on to get correct value, normally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * we should enable its clk before taking measurement and disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) * clk after measurement is done, but if alarm function is enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * hardware will auto measure the temperature periodically, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * need to keep the clk always on for alarm function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) ret = clk_prepare_enable(data->thermal_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) goto legacy_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) data->tz = thermal_zone_device_register("imx_thermal_zone",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) IMX_TRIP_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) BIT(IMX_TRIP_PASSIVE), data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) &imx_tz_ops, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) IMX_PASSIVE_DELAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) IMX_POLLING_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (IS_ERR(data->tz)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) ret = PTR_ERR(data->tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) "failed to register thermal zone device %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) goto clk_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) " critical:%dC passive:%dC\n", data->temp_grade,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) data->temp_max / 1000, data->temp_critical / 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) data->temp_passive / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* Enable measurements at ~ 10 Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) data->socdata->measure_freq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) measure_freq << data->socdata->measure_freq_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) imx_set_alarm_temp(data, data->temp_passive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (data->socdata->version == TEMPMON_IMX6SX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) imx_set_panic_temp(data, data->temp_critical);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) data->socdata->power_down_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) data->socdata->measure_temp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* After power up, we need a delay before first access can be done. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) usleep_range(20, 50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /* the core was configured and enabled just before */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) pm_runtime_set_active(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) pm_runtime_enable(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) ret = pm_runtime_resume_and_get(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) goto disable_runtime_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) data->irq_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) ret = thermal_zone_device_enable(data->tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) goto thermal_zone_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) ret = devm_request_threaded_irq(&pdev->dev, data->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 0, "imx_thermal", data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) goto thermal_zone_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) pm_runtime_put(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) thermal_zone_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) thermal_zone_device_unregister(data->tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) disable_runtime_pm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) pm_runtime_put_noidle(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) pm_runtime_disable(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) clk_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) clk_disable_unprepare(data->thermal_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) legacy_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) imx_thermal_unregister_legacy_cooling(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int imx_thermal_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct imx_thermal_data *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) pm_runtime_put_noidle(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) pm_runtime_disable(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) thermal_zone_device_unregister(data->tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) imx_thermal_unregister_legacy_cooling(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static int __maybe_unused imx_thermal_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct imx_thermal_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) * Need to disable thermal sensor, otherwise, when thermal core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * try to get temperature before thermal sensor resume, a wrong
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * temperature will be read as the thermal sensor is powered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * down. This is done in change_mode() operation called from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) * thermal_zone_device_disable()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) ret = thermal_zone_device_disable(data->tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return pm_runtime_force_suspend(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) static int __maybe_unused imx_thermal_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct imx_thermal_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) ret = pm_runtime_force_resume(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /* Enabled thermal sensor after resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return thermal_zone_device_enable(data->tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static int __maybe_unused imx_thermal_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct imx_thermal_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) const struct thermal_soc_data *socdata = data->socdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct regmap *map = data->tempmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) socdata->measure_temp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) socdata->power_down_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) clk_disable_unprepare(data->thermal_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static int __maybe_unused imx_thermal_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct imx_thermal_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) const struct thermal_soc_data *socdata = data->socdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) struct regmap *map = data->tempmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) ret = clk_prepare_enable(data->thermal_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) socdata->power_down_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) socdata->measure_temp_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * According to the temp sensor designers, it may require up to ~17us
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * to complete a measurement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) usleep_range(20, 50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) static const struct dev_pm_ops imx_thermal_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) SET_SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) SET_RUNTIME_PM_OPS(imx_thermal_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) imx_thermal_runtime_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) static struct platform_driver imx_thermal = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) .name = "imx_thermal",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .pm = &imx_thermal_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) .of_match_table = of_imx_thermal_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .probe = imx_thermal_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) .remove = imx_thermal_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) module_platform_driver(imx_thermal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) MODULE_AUTHOR("Freescale Semiconductor, Inc.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) MODULE_DESCRIPTION("Thermal driver for Freescale i.MX SoCs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) MODULE_ALIAS("platform:imx-thermal");