Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'thermal-v6.16-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux

Merge updates of multiple thermal drivers for 6.16 from Daniel Lezcano:

"- Make the Hisilicon driver to compile by default when ARCH_HISI is
set (Krzysztof Kozlowski)

- Cleanup printk format with use of %pC instead of %pCn in the bcm2835
driver (Luca Ceresoli)

- Fix variable naming coding style in the AmLogic driver (Enrique
Isidoro Vazquez Ramos)

- Fix missing debugfs entry removal on failure by using the devm_
variant in the LVTS driver (AngeloGioacchino Del Regno)

- Remove the unused lvts_debugfs_exit() function as the devm variant
introduced before takes care of removing the debugfs entry in the
LVTS driver (Arnd Bergmann)

- Add the Airoha EN7581 thermal sensor support along with its DT
bindings (Christian Marangi)

- Add ipq5018 compatible string DT binding, cleanup and add its suppot
in the QCom Tsens driver driver (Sricharan Ramabadhran and George
Moussalem)

- Fix comments typos in the Airoha driver (Christian Marangi)"

* tag 'thermal-v6.16-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux:
thermal/drivers/airoha: Fix spelling mistake
thermal/drivers/qcom/tsens: Add support for IPQ5018 tsens
thermal/drivers/qcom/tsens: Add support for tsens v1 without RPM
thermal/drivers/qcom/tsens: Update conditions to strictly evaluate for IP v2+
dt-bindings: thermal: qcom-tsens: Add ipq5018 compatible
thermal/drivers: Add support for Airoha EN7581 thermal sensor
dt-bindings: thermal: Add support for Airoha EN7581 thermal sensor
thermal/drivers/mediatek/lvts: Remove unused lvts_debugfs_exit
thermal/drivers/mediatek/lvts: Fix debugfs unregister on failure
thermal/drivers/amlogic: Rename Uptat to uptat to follow kernel coding style
vsprintf: remove redundant and unused %pCn format specifier
thermal/drivers/bcm2835: Use %pC instead of %pCn
thermal/drivers/hisi: Do not enable by default during compile testing

+655 -41
+1 -2
Documentation/core-api/printk-formats.rst
··· 571 571 :: 572 572 573 573 %pC pll1 574 - %pCn pll1 575 574 576 - For printing struct clk structures. %pC and %pCn print the name of the clock 575 + For printing struct clk structures. %pC prints the name of the clock 577 576 (Common Clock Framework) or a unique 32-bit ID (legacy clock framework). 578 577 579 578 Passed by reference.
+48
Documentation/devicetree/bindings/thermal/airoha,en7581-thermal.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/thermal/airoha,en7581-thermal.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Airoha EN7581 Thermal Sensor and Monitor 8 + 9 + maintainers: 10 + - Christian Marangi <ansuelsmth@gmail.com> 11 + 12 + properties: 13 + compatible: 14 + const: airoha,en7581-thermal 15 + 16 + reg: 17 + maxItems: 1 18 + 19 + interrupts: 20 + maxItems: 1 21 + 22 + airoha,chip-scu: 23 + description: phandle to the chip SCU syscon 24 + $ref: /schemas/types.yaml#/definitions/phandle 25 + 26 + '#thermal-sensor-cells': 27 + const: 0 28 + 29 + required: 30 + - compatible 31 + - reg 32 + - interrupts 33 + - airoha,chip-scu 34 + 35 + additionalProperties: false 36 + 37 + examples: 38 + - | 39 + #include <dt-bindings/interrupt-controller/arm-gic.h> 40 + 41 + thermal-sensor@1efbd800 { 42 + compatible = "airoha,en7581-thermal"; 43 + reg = <0x1efbd000 0xd5c>; 44 + interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; 45 + airoha,chip-scu = <&chip_scu>; 46 + 47 + #thermal-sensor-cells = <0>; 48 + };
+2
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
··· 39 39 - description: v1 of TSENS 40 40 items: 41 41 - enum: 42 + - qcom,ipq5018-tsens 42 43 - qcom,msm8937-tsens 43 44 - qcom,msm8956-tsens 44 45 - qcom,msm8976-tsens ··· 252 251 compatible: 253 252 contains: 254 253 enum: 254 + - qcom,ipq5018-tsens 255 255 - qcom,ipq8064-tsens 256 256 - qcom,msm8960-tsens 257 257 - qcom,tsens-v0_1
+1 -2
Documentation/translations/zh_CN/core-api/printk-formats.rst
··· 523 523 :: 524 524 525 525 %pC pll1 526 - %pCn pll1 527 526 528 - 用于打印clk结构。%pC 和 %pCn 打印时钟的名称(通用时钟框架)或唯一的32位 527 + 用于打印clk结构。%pC 打印时钟的名称(通用时钟框架)或唯一的32位 529 528 ID(传统时钟框架)。 530 529 531 530 通过引用传递。
+10 -1
drivers/thermal/Kconfig
··· 257 257 depends on ARCH_HISI || COMPILE_TEST 258 258 depends on HAS_IOMEM 259 259 depends on OF 260 - default y 260 + default ARCH_HISI 261 261 help 262 262 Enable this to plug hisilicon's thermal sensor driver into the Linux 263 263 thermal framework. cpufreq is used as the cooling device to throttle ··· 326 326 It supports one critical trip point and one passive trip point. The 327 327 cpufreq is used as the cooling device to throttle CPUs when the 328 328 passive trip is crossed. 329 + 330 + config AIROHA_THERMAL 331 + tristate "Airoha thermal sensor driver" 332 + depends on ARCH_AIROHA || COMPILE_TEST 333 + depends on MFD_SYSCON 334 + depends on OF 335 + help 336 + Enable this to plug the Airoha thermal sensor driver into the Linux 337 + thermal framework. 329 338 330 339 config SPEAR_THERMAL 331 340 tristate "SPEAr thermal sensor driver"
+1
drivers/thermal/Makefile
··· 38 38 # platform thermal drivers 39 39 obj-y += broadcom/ 40 40 obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o 41 + obj-$(CONFIG_AIROHA_THERMAL) += airoha_thermal.o 41 42 obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 42 43 obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o 43 44 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
+489
drivers/thermal/airoha_thermal.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + #include <linux/module.h> 4 + #include <linux/bitfield.h> 5 + #include <linux/delay.h> 6 + #include <linux/interrupt.h> 7 + #include <linux/mfd/syscon.h> 8 + #include <linux/of.h> 9 + #include <linux/of_address.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/regmap.h> 12 + #include <linux/thermal.h> 13 + 14 + /* SCU regs */ 15 + #define EN7581_PLLRG_PROTECT 0x268 16 + #define EN7581_PWD_TADC 0x2ec 17 + #define EN7581_MUX_TADC GENMASK(3, 1) 18 + #define EN7581_DOUT_TADC 0x2f8 19 + #define EN7581_DOUT_TADC_MASK GENMASK(15, 0) 20 + 21 + /* PTP_THERMAL regs */ 22 + #define EN7581_TEMPMONCTL0 0x800 23 + #define EN7581_SENSE3_EN BIT(3) 24 + #define EN7581_SENSE2_EN BIT(2) 25 + #define EN7581_SENSE1_EN BIT(1) 26 + #define EN7581_SENSE0_EN BIT(0) 27 + #define EN7581_TEMPMONCTL1 0x804 28 + /* period unit calculated in BUS clock * 256 scaling-up */ 29 + #define EN7581_PERIOD_UNIT GENMASK(9, 0) 30 + #define EN7581_TEMPMONCTL2 0x808 31 + #define EN7581_FILT_INTERVAL GENMASK(25, 16) 32 + #define EN7581_SEN_INTERVAL GENMASK(9, 0) 33 + #define EN7581_TEMPMONINT 0x80C 34 + #define EN7581_STAGE3_INT_EN BIT(31) 35 + #define EN7581_STAGE2_INT_EN BIT(30) 36 + #define EN7581_STAGE1_INT_EN BIT(29) 37 + #define EN7581_FILTER_INT_EN_3 BIT(28) 38 + #define EN7581_IMMD_INT_EN3 BIT(27) 39 + #define EN7581_NOHOTINTEN3 BIT(26) 40 + #define EN7581_HOFSINTEN3 BIT(25) 41 + #define EN7581_LOFSINTEN3 BIT(24) 42 + #define EN7581_HINTEN3 BIT(23) 43 + #define EN7581_CINTEN3 BIT(22) 44 + #define EN7581_FILTER_INT_EN_2 BIT(21) 45 + #define EN7581_FILTER_INT_EN_1 BIT(20) 46 + #define EN7581_FILTER_INT_EN_0 BIT(19) 47 + #define EN7581_IMMD_INT_EN2 BIT(18) 48 + #define EN7581_IMMD_INT_EN1 BIT(17) 49 + #define EN7581_IMMD_INT_EN0 BIT(16) 50 + #define EN7581_TIME_OUT_INT_EN BIT(15) 51 + #define EN7581_NOHOTINTEN2 BIT(14) 52 + #define EN7581_HOFSINTEN2 BIT(13) 53 + #define EN7581_LOFSINTEN2 BIT(12) 54 + #define EN7581_HINTEN2 BIT(11) 55 + #define EN7581_CINTEN2 BIT(10) 56 + #define EN7581_NOHOTINTEN1 BIT(9) 57 + #define EN7581_HOFSINTEN1 BIT(8) 58 + #define EN7581_LOFSINTEN1 BIT(7) 59 + #define EN7581_HINTEN1 BIT(6) 60 + #define EN7581_CINTEN1 BIT(5) 61 + #define EN7581_NOHOTINTEN0 BIT(4) 62 + /* Similar to COLD and HOT also these seems to be swapped in documentation */ 63 + #define EN7581_LOFSINTEN0 BIT(3) /* In documentation: BIT(2) */ 64 + #define EN7581_HOFSINTEN0 BIT(2) /* In documentation: BIT(3) */ 65 + /* It seems documentation have these swapped as the HW 66 + * - Fire BIT(1) when lower than EN7581_COLD_THRE 67 + * - Fire BIT(0) and BIT(5) when higher than EN7581_HOT2NORMAL_THRE or 68 + * EN7581_HOT_THRE 69 + */ 70 + #define EN7581_CINTEN0 BIT(1) /* In documentation: BIT(0) */ 71 + #define EN7581_HINTEN0 BIT(0) /* In documentation: BIT(1) */ 72 + #define EN7581_TEMPMONINTSTS 0x810 73 + #define EN7581_STAGE3_INT_STAT BIT(31) 74 + #define EN7581_STAGE2_INT_STAT BIT(30) 75 + #define EN7581_STAGE1_INT_STAT BIT(29) 76 + #define EN7581_FILTER_INT_STAT_3 BIT(28) 77 + #define EN7581_IMMD_INT_STS3 BIT(27) 78 + #define EN7581_NOHOTINTSTS3 BIT(26) 79 + #define EN7581_HOFSINTSTS3 BIT(25) 80 + #define EN7581_LOFSINTSTS3 BIT(24) 81 + #define EN7581_HINTSTS3 BIT(23) 82 + #define EN7581_CINTSTS3 BIT(22) 83 + #define EN7581_FILTER_INT_STAT_2 BIT(21) 84 + #define EN7581_FILTER_INT_STAT_1 BIT(20) 85 + #define EN7581_FILTER_INT_STAT_0 BIT(19) 86 + #define EN7581_IMMD_INT_STS2 BIT(18) 87 + #define EN7581_IMMD_INT_STS1 BIT(17) 88 + #define EN7581_IMMD_INT_STS0 BIT(16) 89 + #define EN7581_TIME_OUT_INT_STAT BIT(15) 90 + #define EN7581_NOHOTINTSTS2 BIT(14) 91 + #define EN7581_HOFSINTSTS2 BIT(13) 92 + #define EN7581_LOFSINTSTS2 BIT(12) 93 + #define EN7581_HINTSTS2 BIT(11) 94 + #define EN7581_CINTSTS2 BIT(10) 95 + #define EN7581_NOHOTINTSTS1 BIT(9) 96 + #define EN7581_HOFSINTSTS1 BIT(8) 97 + #define EN7581_LOFSINTSTS1 BIT(7) 98 + #define EN7581_HINTSTS1 BIT(6) 99 + #define EN7581_CINTSTS1 BIT(5) 100 + #define EN7581_NOHOTINTSTS0 BIT(4) 101 + /* Similar to COLD and HOT also these seems to be swapped in documentation */ 102 + #define EN7581_LOFSINTSTS0 BIT(3) /* In documentation: BIT(2) */ 103 + #define EN7581_HOFSINTSTS0 BIT(2) /* In documentation: BIT(3) */ 104 + /* It seems documentation have these swapped as the HW 105 + * - Fire BIT(1) when lower than EN7581_COLD_THRE 106 + * - Fire BIT(0) and BIT(5) when higher than EN7581_HOT2NORMAL_THRE or 107 + * EN7581_HOT_THRE 108 + * 109 + * To clear things, we swap the define but we keep them documented here. 110 + */ 111 + #define EN7581_CINTSTS0 BIT(1) /* In documentation: BIT(0) */ 112 + #define EN7581_HINTSTS0 BIT(0) /* In documentation: BIT(1)*/ 113 + /* Monitor will take the bigger threshold between HOT2NORMAL and HOT 114 + * and will fire both HOT2NORMAL and HOT interrupt when higher than the 2 115 + * 116 + * It has also been observed that not setting HOT2NORMAL makes the monitor 117 + * treat COLD threshold as HOT2NORMAL. 118 + */ 119 + #define EN7581_TEMPH2NTHRE 0x824 120 + /* It seems HOT2NORMAL is actually NORMAL2HOT */ 121 + #define EN7581_HOT2NORMAL_THRE GENMASK(11, 0) 122 + #define EN7581_TEMPHTHRE 0x828 123 + #define EN7581_HOT_THRE GENMASK(11, 0) 124 + /* Monitor will use this as HOT2NORMAL (fire interrupt when lower than...)*/ 125 + #define EN7581_TEMPCTHRE 0x82c 126 + #define EN7581_COLD_THRE GENMASK(11, 0) 127 + /* Also LOW and HIGH offset register are swapped */ 128 + #define EN7581_TEMPOFFSETL 0x830 /* In documentation: 0x834 */ 129 + #define EN7581_LOW_OFFSET GENMASK(11, 0) 130 + #define EN7581_TEMPOFFSETH 0x834 /* In documentation: 0x830 */ 131 + #define EN7581_HIGH_OFFSET GENMASK(11, 0) 132 + #define EN7581_TEMPMSRCTL0 0x838 133 + #define EN7581_MSRCTL3 GENMASK(11, 9) 134 + #define EN7581_MSRCTL2 GENMASK(8, 6) 135 + #define EN7581_MSRCTL1 GENMASK(5, 3) 136 + #define EN7581_MSRCTL0 GENMASK(2, 0) 137 + #define EN7581_TEMPADCVALIDADDR 0x878 138 + #define EN7581_ADC_VALID_ADDR GENMASK(31, 0) 139 + #define EN7581_TEMPADCVOLTADDR 0x87c 140 + #define EN7581_ADC_VOLT_ADDR GENMASK(31, 0) 141 + #define EN7581_TEMPRDCTRL 0x880 142 + /* 143 + * NOTICE: AHB have this set to 0 by default. Means that 144 + * the same addr is used for ADC volt and valid reading. 145 + * In such case, VALID ADDR is used and volt addr is ignored. 146 + */ 147 + #define EN7581_RD_CTRL_DIFF BIT(0) 148 + #define EN7581_TEMPADCVALIDMASK 0x884 149 + #define EN7581_ADV_RD_VALID_POLARITY BIT(5) 150 + #define EN7581_ADV_RD_VALID_POS GENMASK(4, 0) 151 + #define EN7581_TEMPADCVOLTAGESHIFT 0x888 152 + #define EN7581_ADC_VOLTAGE_SHIFT GENMASK(4, 0) 153 + /* 154 + * Same values for each CTL. 155 + * Can operate in: 156 + * - 1 sample 157 + * - 2 sample and make average of them 158 + * - 4,6,10,16 sample, drop max and min and make average of them 159 + */ 160 + #define EN7581_MSRCTL_1SAMPLE 0x0 161 + #define EN7581_MSRCTL_AVG2SAMPLE 0x1 162 + #define EN7581_MSRCTL_4SAMPLE_MAX_MIX_AVG2 0x2 163 + #define EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4 0x3 164 + #define EN7581_MSRCTL_10SAMPLE_MAX_MIX_AVG8 0x4 165 + #define EN7581_MSRCTL_18SAMPLE_MAX_MIX_AVG16 0x5 166 + #define EN7581_TEMPAHBPOLL 0x840 167 + #define EN7581_ADC_POLL_INTVL GENMASK(31, 0) 168 + /* PTPSPARE0,2 reg are used to store efuse info for calibrated temp offset */ 169 + #define EN7581_EFUSE_TEMP_OFFSET_REG 0xf20 /* PTPSPARE0 */ 170 + #define EN7581_EFUSE_TEMP_OFFSET GENMASK(31, 16) 171 + #define EN7581_PTPSPARE1 0xf24 /* PTPSPARE1 */ 172 + #define EN7581_EFUSE_TEMP_CPU_SENSOR_REG 0xf28 /* PTPSPARE2 */ 173 + 174 + #define EN7581_SLOPE_X100_DIO_DEFAULT 5645 175 + #define EN7581_SLOPE_X100_DIO_AVS 5645 176 + 177 + #define EN7581_INIT_TEMP_CPK_X10 300 178 + #define EN7581_INIT_TEMP_FTK_X10 620 179 + #define EN7581_INIT_TEMP_NONK_X10 550 180 + 181 + #define EN7581_SCU_THERMAL_PROTECT_KEY 0x12 182 + #define EN7581_SCU_THERMAL_MUX_DIODE1 0x7 183 + 184 + /* Convert temp to raw value as read from ADC ((((temp / 100) - init) * slope) / 1000) + offset */ 185 + #define TEMP_TO_RAW(priv, temp) ((((((temp) / 100) - (priv)->init_temp) * \ 186 + (priv)->default_slope) / 1000) + \ 187 + (priv)->default_offset) 188 + 189 + /* Convert raw to temp ((((temp - offset) * 1000) / slope + init) * 100) */ 190 + #define RAW_TO_TEMP(priv, raw) (((((raw) - (priv)->default_offset) * 1000) / \ 191 + (priv)->default_slope + \ 192 + (priv)->init_temp) * 100) 193 + 194 + #define AIROHA_MAX_SAMPLES 6 195 + 196 + struct airoha_thermal_priv { 197 + void __iomem *base; 198 + struct regmap *chip_scu; 199 + struct resource scu_adc_res; 200 + 201 + struct thermal_zone_device *tz; 202 + int init_temp; 203 + int default_slope; 204 + int default_offset; 205 + }; 206 + 207 + static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv) 208 + { 209 + u32 val; 210 + 211 + regmap_read(priv->chip_scu, EN7581_DOUT_TADC, &val); 212 + return FIELD_GET(EN7581_DOUT_TADC_MASK, val); 213 + } 214 + 215 + static void airoha_init_thermal_ADC_mode(struct airoha_thermal_priv *priv) 216 + { 217 + u32 adc_mux, pllrg; 218 + 219 + /* Save PLLRG current value */ 220 + regmap_read(priv->chip_scu, EN7581_PLLRG_PROTECT, &pllrg); 221 + 222 + /* Give access to thermal regs */ 223 + regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, EN7581_SCU_THERMAL_PROTECT_KEY); 224 + adc_mux = FIELD_PREP(EN7581_MUX_TADC, EN7581_SCU_THERMAL_MUX_DIODE1); 225 + regmap_write(priv->chip_scu, EN7581_PWD_TADC, adc_mux); 226 + 227 + /* Restore PLLRG value on exit */ 228 + regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, pllrg); 229 + } 230 + 231 + static int airoha_thermal_get_temp(struct thermal_zone_device *tz, int *temp) 232 + { 233 + struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz); 234 + int min_value, max_value, avg_value, value; 235 + int i; 236 + 237 + avg_value = 0; 238 + min_value = INT_MAX; 239 + max_value = INT_MIN; 240 + 241 + for (i = 0; i < AIROHA_MAX_SAMPLES; i++) { 242 + value = airoha_get_thermal_ADC(priv); 243 + min_value = min(value, min_value); 244 + max_value = max(value, max_value); 245 + avg_value += value; 246 + } 247 + 248 + /* Drop min and max and average for the remaining sample */ 249 + avg_value -= (min_value + max_value); 250 + avg_value /= AIROHA_MAX_SAMPLES - 2; 251 + 252 + *temp = RAW_TO_TEMP(priv, avg_value); 253 + return 0; 254 + } 255 + 256 + static int airoha_thermal_set_trips(struct thermal_zone_device *tz, int low, 257 + int high) 258 + { 259 + struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz); 260 + bool enable_monitor = false; 261 + 262 + if (high != INT_MAX) { 263 + /* Validate high and clamp it a supported value */ 264 + high = clamp_t(int, high, RAW_TO_TEMP(priv, 0), 265 + RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK))); 266 + 267 + /* We offset the high temp of 1°C to trigger correct event */ 268 + writel(TEMP_TO_RAW(priv, high) >> 4, 269 + priv->base + EN7581_TEMPOFFSETH); 270 + 271 + enable_monitor = true; 272 + } 273 + 274 + if (low != -INT_MAX) { 275 + /* Validate low and clamp it to a supported value */ 276 + low = clamp_t(int, high, RAW_TO_TEMP(priv, 0), 277 + RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK))); 278 + 279 + /* We offset the low temp of 1°C to trigger correct event */ 280 + writel(TEMP_TO_RAW(priv, low) >> 4, 281 + priv->base + EN7581_TEMPOFFSETL); 282 + 283 + enable_monitor = true; 284 + } 285 + 286 + /* Enable sensor 0 monitor after trip are set */ 287 + if (enable_monitor) 288 + writel(EN7581_SENSE0_EN, priv->base + EN7581_TEMPMONCTL0); 289 + 290 + return 0; 291 + } 292 + 293 + static const struct thermal_zone_device_ops thdev_ops = { 294 + .get_temp = airoha_thermal_get_temp, 295 + .set_trips = airoha_thermal_set_trips, 296 + }; 297 + 298 + static irqreturn_t airoha_thermal_irq(int irq, void *data) 299 + { 300 + struct airoha_thermal_priv *priv = data; 301 + enum thermal_notify_event event; 302 + bool update = false; 303 + u32 status; 304 + 305 + status = readl(priv->base + EN7581_TEMPMONINTSTS); 306 + switch (status & (EN7581_HOFSINTSTS0 | EN7581_LOFSINTSTS0)) { 307 + case EN7581_HOFSINTSTS0: 308 + event = THERMAL_TRIP_VIOLATED; 309 + update = true; 310 + break; 311 + case EN7581_LOFSINTSTS0: 312 + event = THERMAL_EVENT_UNSPECIFIED; 313 + update = true; 314 + break; 315 + default: 316 + /* Should be impossible as we enable only these Interrupt */ 317 + break; 318 + } 319 + 320 + /* Reset Interrupt */ 321 + writel(status, priv->base + EN7581_TEMPMONINTSTS); 322 + 323 + if (update) 324 + thermal_zone_device_update(priv->tz, event); 325 + 326 + return IRQ_HANDLED; 327 + } 328 + 329 + static void airoha_thermal_setup_adc_val(struct device *dev, 330 + struct airoha_thermal_priv *priv) 331 + { 332 + u32 efuse_calib_info, cpu_sensor; 333 + 334 + /* Setup thermal sensor to ADC mode and setup the mux to DIODE1 */ 335 + airoha_init_thermal_ADC_mode(priv); 336 + /* sleep 10 ms for ADC to enable */ 337 + usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC); 338 + 339 + efuse_calib_info = readl(priv->base + EN7581_EFUSE_TEMP_OFFSET_REG); 340 + if (efuse_calib_info) { 341 + priv->default_offset = FIELD_GET(EN7581_EFUSE_TEMP_OFFSET, efuse_calib_info); 342 + /* Different slope are applied if the sensor is used for CPU or for package */ 343 + cpu_sensor = readl(priv->base + EN7581_EFUSE_TEMP_CPU_SENSOR_REG); 344 + if (cpu_sensor) { 345 + priv->default_slope = EN7581_SLOPE_X100_DIO_DEFAULT; 346 + priv->init_temp = EN7581_INIT_TEMP_FTK_X10; 347 + } else { 348 + priv->default_slope = EN7581_SLOPE_X100_DIO_AVS; 349 + priv->init_temp = EN7581_INIT_TEMP_CPK_X10; 350 + } 351 + } else { 352 + priv->default_offset = airoha_get_thermal_ADC(priv); 353 + priv->default_slope = EN7581_SLOPE_X100_DIO_DEFAULT; 354 + priv->init_temp = EN7581_INIT_TEMP_NONK_X10; 355 + dev_info(dev, "missing thermal calibrarion EFUSE, using non calibrated value\n"); 356 + } 357 + } 358 + 359 + static void airoha_thermal_setup_monitor(struct airoha_thermal_priv *priv) 360 + { 361 + /* Set measure mode */ 362 + writel(FIELD_PREP(EN7581_MSRCTL0, EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4), 363 + priv->base + EN7581_TEMPMSRCTL0); 364 + 365 + /* 366 + * Configure ADC valid reading addr 367 + * The AHB temp monitor system doesn't have direct access to the 368 + * thermal sensor. It does instead work by providing various 369 + * addresses to configure how to access and setup an ADC for the 370 + * sensor. EN7581 supports only one sensor hence the 371 + * implementation is greatly simplified but the AHB supports 372 + * up to 4 different sensors from the same ADC that can be 373 + * switched by tuning the ADC mux or writing address. 374 + * 375 + * We set valid instead of volt as we don't enable valid/volt 376 + * split reading and AHB read valid addr in such case. 377 + */ 378 + writel(priv->scu_adc_res.start + EN7581_DOUT_TADC, 379 + priv->base + EN7581_TEMPADCVALIDADDR); 380 + 381 + /* 382 + * Configure valid bit on a fake value of bit 16. The ADC outputs 383 + * max of 2 bytes for voltage. 384 + */ 385 + writel(FIELD_PREP(EN7581_ADV_RD_VALID_POS, 16), 386 + priv->base + EN7581_TEMPADCVALIDMASK); 387 + 388 + /* 389 + * AHB supports max 12 bytes for ADC voltage. Shift the read 390 + * value 4 bit to the right. Precision lost by this is minimal 391 + * in the order of half a °C and is acceptable in the context 392 + * of triggering interrupt in critical condition. 393 + */ 394 + writel(FIELD_PREP(EN7581_ADC_VOLTAGE_SHIFT, 4), 395 + priv->base + EN7581_TEMPADCVOLTAGESHIFT); 396 + 397 + /* BUS clock is 300MHz counting unit is 3 * 68.64 * 256 = 52.715us */ 398 + writel(FIELD_PREP(EN7581_PERIOD_UNIT, 3), 399 + priv->base + EN7581_TEMPMONCTL1); 400 + 401 + /* 402 + * filt interval is 1 * 52.715us = 52.715us, 403 + * sen interval is 379 * 52.715us = 19.97ms 404 + */ 405 + writel(FIELD_PREP(EN7581_FILT_INTERVAL, 1) | 406 + FIELD_PREP(EN7581_FILT_INTERVAL, 379), 407 + priv->base + EN7581_TEMPMONCTL2); 408 + 409 + /* AHB poll is set to 146 * 68.64 = 10.02us */ 410 + writel(FIELD_PREP(EN7581_ADC_POLL_INTVL, 146), 411 + priv->base + EN7581_TEMPAHBPOLL); 412 + } 413 + 414 + static int airoha_thermal_probe(struct platform_device *pdev) 415 + { 416 + struct airoha_thermal_priv *priv; 417 + struct device_node *chip_scu_np; 418 + struct device *dev = &pdev->dev; 419 + int irq, ret; 420 + 421 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 422 + if (!priv) 423 + return -ENOMEM; 424 + 425 + priv->base = devm_platform_ioremap_resource(pdev, 0); 426 + if (IS_ERR(priv->base)) 427 + return PTR_ERR(priv->base); 428 + 429 + chip_scu_np = of_parse_phandle(dev->of_node, "airoha,chip-scu", 0); 430 + if (!chip_scu_np) 431 + return -EINVAL; 432 + 433 + priv->chip_scu = syscon_node_to_regmap(chip_scu_np); 434 + if (IS_ERR(priv->chip_scu)) 435 + return PTR_ERR(priv->chip_scu); 436 + 437 + of_address_to_resource(chip_scu_np, 0, &priv->scu_adc_res); 438 + of_node_put(chip_scu_np); 439 + 440 + irq = platform_get_irq(pdev, 0); 441 + if (irq < 0) 442 + return irq; 443 + 444 + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 445 + airoha_thermal_irq, IRQF_ONESHOT, 446 + pdev->name, priv); 447 + if (ret) { 448 + dev_err(dev, "Can't get interrupt working.\n"); 449 + return ret; 450 + } 451 + 452 + airoha_thermal_setup_monitor(priv); 453 + airoha_thermal_setup_adc_val(dev, priv); 454 + 455 + /* register of thermal sensor and get info from DT */ 456 + priv->tz = devm_thermal_of_zone_register(dev, 0, priv, &thdev_ops); 457 + if (IS_ERR(priv->tz)) { 458 + dev_err(dev, "register thermal zone sensor failed\n"); 459 + return PTR_ERR(priv->tz); 460 + } 461 + 462 + platform_set_drvdata(pdev, priv); 463 + 464 + /* Enable LOW and HIGH interrupt */ 465 + writel(EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0, 466 + priv->base + EN7581_TEMPMONINT); 467 + 468 + return 0; 469 + } 470 + 471 + static const struct of_device_id airoha_thermal_match[] = { 472 + { .compatible = "airoha,en7581-thermal" }, 473 + {}, 474 + }; 475 + MODULE_DEVICE_TABLE(of, airoha_thermal_match); 476 + 477 + static struct platform_driver airoha_thermal_driver = { 478 + .driver = { 479 + .name = "airoha-thermal", 480 + .of_match_table = airoha_thermal_match, 481 + }, 482 + .probe = airoha_thermal_probe, 483 + }; 484 + 485 + module_platform_driver(airoha_thermal_driver); 486 + 487 + MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>"); 488 + MODULE_DESCRIPTION("Airoha thermal driver"); 489 + MODULE_LICENSE("GPL");
+8 -8
drivers/thermal/amlogic_thermal.c
··· 7 7 * 8 8 * Register value to celsius temperature formulas: 9 9 * Read_Val m * U 10 - * U = ---------, Uptat = --------- 10 + * U = ---------, uptat = --------- 11 11 * 2^16 1 + n * U 12 12 * 13 - * Temperature = A * ( Uptat + u_efuse / 2^16 )- B 13 + * Temperature = A * ( uptat + u_efuse / 2^16 )- B 14 14 * 15 15 * A B m n : calibration parameters 16 16 * u_efuse : fused calibration value, it's a signed 16 bits value ··· 112 112 const struct amlogic_thermal_soc_calib_data *param = 113 113 pdata->data->calibration_parameters; 114 114 int temp; 115 - s64 factor, Uptat, uefuse; 115 + s64 factor, uptat, uefuse; 116 116 117 117 uefuse = pdata->trim_info & TSENSOR_TRIM_SIGN_MASK ? 118 118 ~(pdata->trim_info & TSENSOR_TRIM_TEMP_MASK) + 1 : ··· 121 121 factor = param->n * temp_code; 122 122 factor = div_s64(factor, 100); 123 123 124 - Uptat = temp_code * param->m; 125 - Uptat = div_s64(Uptat, 100); 126 - Uptat = Uptat * BIT(16); 127 - Uptat = div_s64(Uptat, BIT(16) + factor); 124 + uptat = temp_code * param->m; 125 + uptat = div_s64(uptat, 100); 126 + uptat = uptat * BIT(16); 127 + uptat = div_s64(uptat, BIT(16) + factor); 128 128 129 - temp = (Uptat + uefuse) * param->A; 129 + temp = (uptat + uefuse) * param->A; 130 130 temp = div_s64(temp, BIT(16)); 131 131 temp = (temp - param->B) * 100; 132 132
+1 -1
drivers/thermal/broadcom/bcm2835_thermal.c
··· 192 192 rate = clk_get_rate(data->clk); 193 193 if ((rate < 1920000) || (rate > 5000000)) 194 194 dev_warn(dev, 195 - "Clock %pCn running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n", 195 + "Clock %pC running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n", 196 196 data->clk, rate); 197 197 198 198 /* register of thermal sensor and get info from DT */
+8 -10
drivers/thermal/mediatek/lvts_thermal.c
··· 213 213 LVTS_DEBUG_FS_REGS(LVTS_CLKEN), 214 214 }; 215 215 216 + static void lvts_debugfs_exit(void *data) 217 + { 218 + struct lvts_domain *lvts_td = data; 219 + 220 + debugfs_remove_recursive(lvts_td->dom_dentry); 221 + } 222 + 216 223 static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td) 217 224 { 218 225 struct debugfs_regset32 *regset; ··· 252 245 debugfs_create_regset32("registers", 0400, dentry, regset); 253 246 } 254 247 255 - return 0; 256 - } 257 - 258 - static void lvts_debugfs_exit(struct lvts_domain *lvts_td) 259 - { 260 - debugfs_remove_recursive(lvts_td->dom_dentry); 248 + return devm_add_action_or_reset(dev, lvts_debugfs_exit, lvts_td); 261 249 } 262 250 263 251 #else ··· 262 260 { 263 261 return 0; 264 262 } 265 - 266 - static void lvts_debugfs_exit(struct lvts_domain *lvts_td) { } 267 263 268 264 #endif 269 265 ··· 1374 1374 1375 1375 for (i = 0; i < lvts_td->num_lvts_ctrl; i++) 1376 1376 lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); 1377 - 1378 - lvts_debugfs_exit(lvts_td); 1379 1377 } 1380 1378 1381 1379 static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = {
+62
drivers/thermal/qcom/tsens-v1.c
··· 79 79 .trip_max_temp = 120000, 80 80 }; 81 81 82 + static struct tsens_features tsens_v1_no_rpm_feat = { 83 + .ver_major = VER_1_X_NO_RPM, 84 + .crit_int = 0, 85 + .combo_int = 0, 86 + .adc = 1, 87 + .srot_split = 1, 88 + .max_sensors = 11, 89 + .trip_min_temp = -40000, 90 + .trip_max_temp = 120000, 91 + }; 92 + 82 93 static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = { 83 94 /* ----- SROT ------ */ 84 95 /* VERSION */ ··· 161 150 return init_common(priv); 162 151 } 163 152 153 + static int __init init_tsens_v1_no_rpm(struct tsens_priv *priv) 154 + { 155 + int i, ret; 156 + u32 mask = 0; 157 + 158 + ret = init_common(priv); 159 + if (ret < 0) { 160 + dev_err(priv->dev, "Init common failed %d\n", ret); 161 + return ret; 162 + } 163 + 164 + ret = regmap_field_write(priv->rf[TSENS_SW_RST], 1); 165 + if (ret) { 166 + dev_err(priv->dev, "Reset failed\n"); 167 + return ret; 168 + } 169 + 170 + for (i = 0; i < priv->num_sensors; i++) 171 + mask |= BIT(priv->sensor[i].hw_id); 172 + 173 + ret = regmap_field_update_bits(priv->rf[SENSOR_EN], mask, mask); 174 + if (ret) { 175 + dev_err(priv->dev, "Sensor Enable failed\n"); 176 + return ret; 177 + } 178 + 179 + ret = regmap_field_write(priv->rf[TSENS_EN], 1); 180 + if (ret) { 181 + dev_err(priv->dev, "Enable failed\n"); 182 + return ret; 183 + } 184 + 185 + ret = regmap_field_write(priv->rf[TSENS_SW_RST], 0); 186 + 187 + return ret; 188 + } 189 + 164 190 static const struct tsens_ops ops_generic_v1 = { 165 191 .init = init_common, 166 192 .calibrate = calibrate_v1, ··· 240 192 .num_sensors = 11, 241 193 .ops = &ops_common, 242 194 .feat = &tsens_v1_feat, 195 + .fields = tsens_v1_regfields, 196 + }; 197 + 198 + const struct tsens_ops ops_ipq5018 = { 199 + .init = init_tsens_v1_no_rpm, 200 + .calibrate = tsens_calibrate_common, 201 + .get_temp = get_temp_tsens_valid, 202 + }; 203 + 204 + const struct tsens_plat_data data_ipq5018 = { 205 + .num_sensors = 5, 206 + .ops = &ops_ipq5018, 207 + .hw_ids = (unsigned int []){0, 1, 2, 3, 4}, 208 + .feat = &tsens_v1_no_rpm_feat, 243 209 .fields = tsens_v1_regfields, 244 210 };
+18 -9
drivers/thermal/qcom/tsens.c
··· 447 447 dev_dbg(priv->dev, "[%u] %s: %s -> %s\n", hw_id, __func__, 448 448 irq_type ? ((irq_type == 1) ? "UP" : "CRITICAL") : "LOW", 449 449 enable ? "en" : "dis"); 450 - if (tsens_version(priv) > VER_1_X) 450 + if (tsens_version(priv) >= VER_2_X) 451 451 tsens_set_interrupt_v2(priv, hw_id, irq_type, enable); 452 452 else 453 453 tsens_set_interrupt_v1(priv, hw_id, irq_type, enable); ··· 499 499 ret = regmap_field_read(priv->rf[LOW_INT_CLEAR_0 + hw_id], &d->low_irq_clear); 500 500 if (ret) 501 501 return ret; 502 - if (tsens_version(priv) > VER_1_X) { 502 + if (tsens_version(priv) >= VER_2_X) { 503 503 ret = regmap_field_read(priv->rf[UP_INT_MASK_0 + hw_id], &d->up_irq_mask); 504 504 if (ret) 505 505 return ret; ··· 543 543 544 544 static inline u32 masked_irq(u32 hw_id, u32 mask, enum tsens_ver ver) 545 545 { 546 - if (ver > VER_1_X) 546 + if (ver >= VER_2_X) 547 547 return mask & (1 << hw_id); 548 548 549 549 /* v1, v0.1 don't have a irq mask register */ ··· 733 733 static int tsens_enable_irq(struct tsens_priv *priv) 734 734 { 735 735 int ret; 736 - int val = tsens_version(priv) > VER_1_X ? 7 : 1; 736 + int val = tsens_version(priv) >= VER_2_X ? 7 : 1; 737 737 738 738 ret = regmap_field_write(priv->rf[INT_EN], val); 739 739 if (ret < 0) ··· 975 975 ret = regmap_field_read(priv->rf[TSENS_EN], &enabled); 976 976 if (ret) 977 977 goto err_put_device; 978 - if (!enabled && (tsens_version(priv) != VER_2_X_NO_RPM)) { 979 - dev_err(dev, "%s: device not enabled\n", __func__); 980 - ret = -ENODEV; 981 - goto err_put_device; 978 + if (!enabled) { 979 + switch (tsens_version(priv)) { 980 + case VER_1_X_NO_RPM: 981 + case VER_2_X_NO_RPM: 982 + break; 983 + default: 984 + dev_err(dev, "%s: device not enabled\n", __func__); 985 + ret = -ENODEV; 986 + goto err_put_device; 987 + } 982 988 } 983 989 984 990 priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map, ··· 1046 1040 } 1047 1041 } 1048 1042 1049 - if (tsens_version(priv) > VER_1_X && ver_minor > 2) { 1043 + if (tsens_version(priv) >= VER_2_X && ver_minor > 2) { 1050 1044 /* Watchdog is present only on v2.3+ */ 1051 1045 priv->feat->has_watchdog = 1; 1052 1046 for (i = WDOG_BARK_STATUS; i <= CC_MON_MASK; i++) { ··· 1108 1102 1109 1103 static const struct of_device_id tsens_table[] = { 1110 1104 { 1105 + .compatible = "qcom,ipq5018-tsens", 1106 + .data = &data_ipq5018, 1107 + }, { 1111 1108 .compatible = "qcom,ipq5332-tsens", 1112 1109 .data = &data_ipq5332, 1113 1110 }, {
+4
drivers/thermal/qcom/tsens.h
··· 34 34 VER_0 = 0, 35 35 VER_0_1, 36 36 VER_1_X, 37 + VER_1_X_NO_RPM, 37 38 VER_2_X, 38 39 VER_2_X_NO_RPM, 39 40 }; ··· 651 650 652 651 /* TSENS v1 targets */ 653 652 extern struct tsens_plat_data data_tsens_v1, data_8937, data_8976, data_8956; 653 + 654 + /* TSENS v1 with no RPM targets */ 655 + extern const struct tsens_plat_data data_ipq5018; 654 656 655 657 /* TSENS v2 targets */ 656 658 extern struct tsens_plat_data data_8996, data_ipq8074, data_tsens_v2;
+2 -8
lib/vsprintf.c
··· 1981 1981 if (check_pointer(&buf, end, clk, spec)) 1982 1982 return buf; 1983 1983 1984 - switch (fmt[1]) { 1985 - case 'n': 1986 - default: 1987 1984 #ifdef CONFIG_COMMON_CLK 1988 - return string(buf, end, __clk_get_name(clk), spec); 1985 + return string(buf, end, __clk_get_name(clk), spec); 1989 1986 #else 1990 - return ptr_to_id(buf, end, clk, spec); 1987 + return ptr_to_id(buf, end, clk, spec); 1991 1988 #endif 1992 - } 1993 1989 } 1994 1990 1995 1991 static ··· 2387 2391 * T time64_t 2388 2392 * - 'C' For a clock, it prints the name (Common Clock Framework) or address 2389 2393 * (legacy clock framework) of the clock 2390 - * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address 2391 - * (legacy clock framework) of the clock 2392 2394 * - 'G' For flags to be printed as a collection of symbolic strings that would 2393 2395 * construct the specific value. Supported flags given by option: 2394 2396 * p page flags (see struct page) given as pointer to unsigned long