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

Merge tag 'thermal-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control updates from Rafael Wysocki:
"These add support for a new feature, Platform Temperature Control
(PTC), to the Intel int340x thermal driver, add support for the Airoha
EN7581 thermal sensor and the IPQ5018 platform, fix up the ACPI
thermal zones handling, fix other assorted issues and clean up code

Specifics:

- Add Platform Temperature Control (PTC) support to the Intel int340x
thermal driver (Srinivas Pandruvada)

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

- Clean up printk() format by using %pC instead of %pCn in the
bcm2835 thermal driver (Luca Ceresoli)

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

- Fix missing debugfs entry removal on failure by using the devm_
variant in the LVTS thermal 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 to the QCom Tsens thermal driver (Sricharan Ramabadhran,
George Moussalem)

- Fix comments typos in the Airoha driver (Christian Marangi, Colin
Ian King)

- Address a sparse warning by making a local variable static in the
QCom thermal driver (George Moussalem)

- Fix the usage of the _SCP control method in the driver for ACPI
thermal zones (Armin Wolf)"

* tag 'thermal-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
thermal: qcom: ipq5018: make ops_ipq5018 struct static
thermal/drivers/airoha: Fix spelling mistake "calibrarion" -> "calibration"
ACPI: thermal: Execute _SCP before reading trip points
ACPI: OSI: Stop advertising support for "3.0 _SCP Extensions"
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
thermal: int340x: processor_thermal: Platform temperature control documentation
thermal: intel: int340x: Enable platform temperature control
thermal: intel: int340x: Add platform temperature control interface

+946 -49
+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
+21
Documentation/driver-api/thermal/intel_dptf.rst
··· 191 191 User space can specify any one of the available workload type using 192 192 this interface. 193 193 194 + :file:`/sys/bus/pci/devices/0000\:00\:04.0/ptc_0_control` 195 + :file:`/sys/bus/pci/devices/0000\:00\:04.0/ptc_1_control` 196 + :file:`/sys/bus/pci/devices/0000\:00\:04.0/ptc_2_control` 197 + 198 + All these controls needs admin privilege to update. 199 + 200 + ``enable`` (RW) 201 + 1 for enable, 0 for disable. Shows the current enable status of 202 + platform temperature control feature. User space can enable/disable 203 + hardware controls. 204 + 205 + ``temperature_target`` (RW) 206 + Update a new temperature target in milli degree celsius for hardware to 207 + use for the temperature control. 208 + 209 + Given that this is platform temperature control, it is expected that a 210 + single user-level manager owns and manages the controls. If multiple 211 + user-level software applications attempt to write different targets, it 212 + can lead to unexpected behavior. 213 + 214 + 194 215 DPTF Processor thermal RFIM interface 195 216 -------------------------------------------- 196 217
+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 通过引用传递。
-1
drivers/acpi/osi.c
··· 42 42 osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = { 43 43 {"Module Device", true}, 44 44 {"Processor Device", true}, 45 - {"3.0 _SCP Extensions", true}, 46 45 {"Processor Aggregator Device", true}, 47 46 }; 48 47
+6 -4
drivers/acpi/thermal.c
··· 803 803 804 804 acpi_thermal_aml_dependency_fix(tz); 805 805 806 + /* 807 + * Set the cooling mode [_SCP] to active cooling. This needs to happen before 808 + * we retrieve the trip point values. 809 + */ 810 + acpi_execute_simple_method(tz->device->handle, "_SCP", ACPI_THERMAL_MODE_ACTIVE); 811 + 806 812 /* Get trip points [_ACi, _PSV, etc.] (required). */ 807 813 acpi_thermal_get_trip_points(tz); 808 814 ··· 819 813 result = acpi_thermal_get_temperature(tz); 820 814 if (result) 821 815 goto free_memory; 822 - 823 - /* Set the cooling mode [_SCP] to active cooling. */ 824 - acpi_execute_simple_method(tz->device->handle, "_SCP", 825 - ACPI_THERMAL_MODE_ACTIVE); 826 816 827 817 /* Determine the default polling frequency [_TZP]. */ 828 818 if (tzp)
+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 calibration 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 */
+1
drivers/thermal/intel/int340x_thermal/Makefile
··· 9 9 obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device_pci.o 10 10 obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o 11 11 obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o 12 + obj-$(CONFIG_INT340X_THERMAL) += platform_temperature_control.o 12 13 obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o 13 14 obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_req.o 14 15 obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_hint.o
+243
drivers/thermal/intel/int340x_thermal/platform_temperature_control.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * processor thermal device platform temperature controls 4 + * Copyright (c) 2025, Intel Corporation. 5 + */ 6 + 7 + /* 8 + * Platform temperature controls hardware interface 9 + * 10 + * The hardware control interface is via MMIO offsets in the processor 11 + * thermal device MMIO space. There are three instances of MMIO registers. 12 + * All registers are 64 bit wide with RW access. 13 + * 14 + * Name: PLATFORM_TEMPERATURE_CONTROL 15 + * Offsets: 0x5B20, 0x5B28, 0x5B30 16 + * 17 + * Bits Description 18 + * 7:0 TARGET_TEMP : Target temperature limit to which the control 19 + * mechanism is regulating. Units: 0.5C. 20 + * 8:8 ENABLE: Read current enable status of the feature or enable 21 + * feature. 22 + * 11:9 GAIN: Sets the aggressiveness of control loop from 0 to 7 23 + * 7 graceful, favors performance at the expense of temperature 24 + * overshoots 25 + * 0 aggressive, favors tight regulation over performance 26 + * 12:12 TEMPERATURE_OVERRIDE_EN 27 + * When set, hardware will use TEMPERATURE_OVERRIDE values instead 28 + * of reading from corresponding sensor. 29 + * 15:13 RESERVED 30 + * 23:16 MIN_PERFORMANCE_LEVEL: Minimum Performance level below which the 31 + * there will be no throttling. 0 - all levels of throttling allowed 32 + * including survivability actions. 255 - no throttling allowed. 33 + * 31:24 TEMPERATURE_OVERRIDE: Allows SW to override the input temperature. 34 + * hardware will use this value instead of the sensor temperature. 35 + * Units: 0.5C. 36 + * 63:32 RESERVED 37 + */ 38 + 39 + #include <linux/kernel.h> 40 + #include <linux/module.h> 41 + #include <linux/pci.h> 42 + #include "processor_thermal_device.h" 43 + 44 + struct mmio_reg { 45 + int bits; 46 + u16 mask; 47 + u16 shift; 48 + u16 units; 49 + }; 50 + 51 + #define MAX_ATTR_GROUP_NAME_LEN 32 52 + #define PTC_MAX_ATTRS 3 53 + 54 + struct ptc_data { 55 + u32 offset; 56 + struct attribute_group ptc_attr_group; 57 + struct attribute *ptc_attrs[PTC_MAX_ATTRS]; 58 + struct device_attribute temperature_target_attr; 59 + struct device_attribute enable_attr; 60 + char group_name[MAX_ATTR_GROUP_NAME_LEN]; 61 + }; 62 + 63 + static const struct mmio_reg ptc_mmio_regs[] = { 64 + { 8, 0xFF, 0, 500}, /* temperature_target, units 0.5C*/ 65 + { 1, 0x01, 8, 0}, /* enable */ 66 + { 3, 0x7, 9, 0}, /* gain */ 67 + { 8, 0xFF, 16, 0}, /* min_performance_level */ 68 + { 1, 0x1, 12, 0}, /* temperature_override_enable */ 69 + { 8, 0xFF, 24, 500}, /* temperature_override, units 0.5C */ 70 + }; 71 + 72 + #define PTC_MAX_INSTANCES 3 73 + 74 + /* Unique offset for each PTC instance */ 75 + static u32 ptc_offsets[PTC_MAX_INSTANCES] = {0x5B20, 0x5B28, 0x5B30}; 76 + 77 + /* These will represent sysfs attribute names */ 78 + static const char * const ptc_strings[] = { 79 + "temperature_target", 80 + "enable", 81 + NULL 82 + }; 83 + 84 + /* Lock to protect concurrent read/write and read-modify-write */ 85 + static DEFINE_MUTEX(ptc_lock); 86 + 87 + static ssize_t ptc_mmio_show(struct ptc_data *data, struct device *dev, 88 + struct device_attribute *attr, char *buf) 89 + { 90 + struct pci_dev *pdev = to_pci_dev(dev); 91 + struct proc_thermal_device *proc_priv; 92 + const struct mmio_reg *mmio_regs; 93 + int ret, units; 94 + u64 reg_val; 95 + 96 + proc_priv = pci_get_drvdata(pdev); 97 + mmio_regs = ptc_mmio_regs; 98 + ret = match_string(ptc_strings, -1, attr->attr.name); 99 + if (ret < 0) 100 + return ret; 101 + 102 + units = mmio_regs[ret].units; 103 + 104 + guard(mutex)(&ptc_lock); 105 + 106 + reg_val = readq((void __iomem *) (proc_priv->mmio_base + data->offset)); 107 + ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask; 108 + if (units) 109 + ret *= units; 110 + 111 + return sysfs_emit(buf, "%d\n", ret); 112 + } 113 + 114 + #define PTC_SHOW(suffix)\ 115 + static ssize_t suffix##_show(struct device *dev,\ 116 + struct device_attribute *attr,\ 117 + char *buf)\ 118 + {\ 119 + struct ptc_data *data = container_of(attr, struct ptc_data, suffix##_attr);\ 120 + return ptc_mmio_show(data, dev, attr, buf);\ 121 + } 122 + 123 + static void ptc_mmio_write(struct pci_dev *pdev, u32 offset, int index, u32 value) 124 + { 125 + struct proc_thermal_device *proc_priv; 126 + u64 mask, reg_val; 127 + 128 + proc_priv = pci_get_drvdata(pdev); 129 + 130 + mask = GENMASK_ULL(ptc_mmio_regs[index].shift + ptc_mmio_regs[index].bits - 1, 131 + ptc_mmio_regs[index].shift); 132 + 133 + guard(mutex)(&ptc_lock); 134 + 135 + reg_val = readq((void __iomem *) (proc_priv->mmio_base + offset)); 136 + reg_val &= ~mask; 137 + reg_val |= (value << ptc_mmio_regs[index].shift); 138 + writeq(reg_val, (void __iomem *) (proc_priv->mmio_base + offset)); 139 + } 140 + 141 + static int ptc_store(struct ptc_data *data, struct device *dev, struct device_attribute *attr, 142 + const char *buf, size_t count) 143 + { 144 + struct pci_dev *pdev = to_pci_dev(dev); 145 + unsigned int input; 146 + int ret; 147 + 148 + ret = kstrtouint(buf, 10, &input); 149 + if (ret) 150 + return ret; 151 + 152 + ret = match_string(ptc_strings, -1, attr->attr.name); 153 + if (ret < 0) 154 + return ret; 155 + 156 + if (ptc_mmio_regs[ret].units) 157 + input /= ptc_mmio_regs[ret].units; 158 + 159 + if (input > ptc_mmio_regs[ret].mask) 160 + return -EINVAL; 161 + 162 + ptc_mmio_write(pdev, data->offset, ret, input); 163 + 164 + return count; 165 + } 166 + 167 + #define PTC_STORE(suffix)\ 168 + static ssize_t suffix##_store(struct device *dev,\ 169 + struct device_attribute *attr,\ 170 + const char *buf, size_t count)\ 171 + {\ 172 + struct ptc_data *data = container_of(attr, struct ptc_data, suffix##_attr);\ 173 + return ptc_store(data, dev, attr, buf, count);\ 174 + } 175 + 176 + PTC_SHOW(temperature_target); 177 + PTC_STORE(temperature_target); 178 + PTC_SHOW(enable); 179 + PTC_STORE(enable); 180 + 181 + #define ptc_init_attribute(_name)\ 182 + do {\ 183 + sysfs_attr_init(&data->_name##_attr.attr);\ 184 + data->_name##_attr.show = _name##_show;\ 185 + data->_name##_attr.store = _name##_store;\ 186 + data->_name##_attr.attr.name = #_name;\ 187 + data->_name##_attr.attr.mode = 0644;\ 188 + } while (0) 189 + 190 + static int ptc_create_groups(struct pci_dev *pdev, int instance, struct ptc_data *data) 191 + { 192 + int ret, index = 0; 193 + 194 + ptc_init_attribute(temperature_target); 195 + ptc_init_attribute(enable); 196 + 197 + data->ptc_attrs[index++] = &data->temperature_target_attr.attr; 198 + data->ptc_attrs[index++] = &data->enable_attr.attr; 199 + data->ptc_attrs[index] = NULL; 200 + 201 + snprintf(data->group_name, MAX_ATTR_GROUP_NAME_LEN, 202 + "ptc_%d_control", instance); 203 + data->ptc_attr_group.name = data->group_name; 204 + data->ptc_attr_group.attrs = data->ptc_attrs; 205 + 206 + ret = sysfs_create_group(&pdev->dev.kobj, &data->ptc_attr_group); 207 + 208 + return ret; 209 + } 210 + 211 + static struct ptc_data ptc_instance[PTC_MAX_INSTANCES]; 212 + 213 + int proc_thermal_ptc_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 214 + { 215 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_PTC) { 216 + int i; 217 + 218 + for (i = 0; i < PTC_MAX_INSTANCES; i++) { 219 + ptc_instance[i].offset = ptc_offsets[i]; 220 + ptc_create_groups(pdev, i, &ptc_instance[i]); 221 + } 222 + } 223 + 224 + return 0; 225 + } 226 + EXPORT_SYMBOL_GPL(proc_thermal_ptc_add); 227 + 228 + void proc_thermal_ptc_remove(struct pci_dev *pdev) 229 + { 230 + struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); 231 + 232 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_PTC) { 233 + int i; 234 + 235 + for (i = 0; i < PTC_MAX_INSTANCES; i++) 236 + sysfs_remove_group(&pdev->dev.kobj, &ptc_instance[i].ptc_attr_group); 237 + } 238 + } 239 + EXPORT_SYMBOL_GPL(proc_thermal_ptc_remove); 240 + 241 + MODULE_IMPORT_NS("INT340X_THERMAL"); 242 + MODULE_LICENSE("GPL"); 243 + MODULE_DESCRIPTION("Processor Thermal PTC Interface");
+14 -1
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
··· 400 400 } 401 401 } 402 402 403 + if (feature_mask & PROC_THERMAL_FEATURE_PTC) { 404 + ret = proc_thermal_ptc_add(pdev, proc_priv); 405 + if (ret) { 406 + dev_err(&pdev->dev, "failed to add PTC MMIO interface\n"); 407 + goto err_rem_rapl; 408 + } 409 + } 410 + 403 411 if (feature_mask & PROC_THERMAL_FEATURE_FIVR || 404 412 feature_mask & PROC_THERMAL_FEATURE_DVFS || 405 413 feature_mask & PROC_THERMAL_FEATURE_DLVR) { 406 414 ret = proc_thermal_rfim_add(pdev, proc_priv); 407 415 if (ret) { 408 416 dev_err(&pdev->dev, "failed to add RFIM interface\n"); 409 - goto err_rem_rapl; 417 + goto err_rem_ptc; 410 418 } 411 419 } 412 420 ··· 436 428 437 429 err_rem_rfim: 438 430 proc_thermal_rfim_remove(pdev); 431 + err_rem_ptc: 432 + proc_thermal_ptc_remove(pdev); 439 433 err_rem_rapl: 440 434 proc_thermal_rapl_remove(); 441 435 ··· 449 439 { 450 440 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_RAPL) 451 441 proc_thermal_rapl_remove(); 442 + 443 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_PTC) 444 + proc_thermal_ptc_remove(pdev); 452 445 453 446 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR || 454 447 proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS ||
+3
drivers/thermal/intel/int340x_thermal/processor_thermal_device.h
··· 67 67 #define PROC_THERMAL_FEATURE_WT_HINT 0x20 68 68 #define PROC_THERMAL_FEATURE_POWER_FLOOR 0x40 69 69 #define PROC_THERMAL_FEATURE_MSI_SUPPORT 0x80 70 + #define PROC_THERMAL_FEATURE_PTC 0x100 70 71 71 72 #if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) 72 73 int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); ··· 124 123 struct proc_thermal_device *proc_priv, 125 124 kernel_ulong_t feature_mask); 126 125 void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 126 + int proc_thermal_ptc_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 127 + void proc_thermal_ptc_remove(struct pci_dev *pdev); 127 128 #endif
+3 -2
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
··· 486 486 PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, 487 487 { PCI_DEVICE_DATA(INTEL, LNLM_THERMAL, PROC_THERMAL_FEATURE_MSI_SUPPORT | 488 488 PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS | 489 - PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) }, 489 + PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR | 490 + PROC_THERMAL_FEATURE_PTC) }, 490 491 { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | 491 492 PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | 492 493 PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) }, ··· 498 497 { PCI_DEVICE_DATA(INTEL, PTL_THERMAL, PROC_THERMAL_FEATURE_RAPL | 499 498 PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS | 500 499 PROC_THERMAL_FEATURE_MSI_SUPPORT | PROC_THERMAL_FEATURE_WT_HINT | 501 - PROC_THERMAL_FEATURE_POWER_FLOOR) }, 500 + PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC) }, 502 501 { }, 503 502 }; 504 503
+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 + static 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