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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'thermal-6.20-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 "slow" (long-term trend) workload type hints to
the Intel int340x thermal driver and selftests (and enable it for
Panther Lake), add support for MT8196 along with DT bindings and for
MT7987 to the Mediatek LVTS thermal driver, add support for RZ/T2H and
RZ/N2H along with DT bindings to the Renesas rzg3e thermal driver, add
support for the Panther Lake, Wildcat Lake and Nova Lake processors to
the intel_tcc_cooling driver, fix bugs, make some cosmetic changes
including code cleanups and library function substitutions, and update
documentation.

Specifics:

- Add Panther Lake, Wildcat Lake and Nova Lake processor IDs to the
list of supported processors in the intel_tcc_cooling thermal
driver (Srinivas Pandruvada)

- Drop unnecessary explicit driver data clearing on removal from the
intel_pch_thermal driver (Kaushlendra Kumar)

- Add support for "slow" workload type hints to the int340x
processor_thermal driver and enable it on the Panther Lake platform
(Srinivas Pandruvada)

- Use sysfs_emit{_at}() in sysfs show functions in Intel thermal
drivers (Thorsten Blum)

- Update the x86_pkg_temp_thermal driver to handle
THERMAL_TEMP_INVALID that can be passed to it via sysfs as expected
(Rafael Wysocki)

- Drop a redundant local variable from the intel_tcc_cooling thermal
driver and fix a kerneldoc comment typo in the TCC library (Sumeet
Pawnikar)

- Fix CFLAGS and LDFLAGS in the pkg-config libthermal template
(Romain Gantois)

- Support multiple temp to raw conversion functions in the Mediatek
LVTS thermal driver and add MT8196 and MT6991 support to it (Laura
Nao)

- Add Mediatek LVTS driver support for MT7987 (Frank Wunderlich)

- Use the existing HZ_PER_MHZ macro on STM32 (Andy Shevchenko)

- Use the existing clamp() macro on BCM2835 (Thorsten Blum)

- Make the reset line optional in order to support new Renesas SoCs
where it is not available and add support for RZ/T2H and RZ/N2H to
the rzg3e thermal driver (Cosmin Tanislav)

- Document RZ/V2N TSU in the r9a09g047-tsu DT bindings (Ovidiu
Panait)

- Fix all kernel-doc warnings in the internal thermal core header
file (Randy Dunlap)

- Fix a device node reference leak in thermal_of_cm_lookup() (Felix
Gu)

- Replace some old-style library function calls with ones that are
currently recommended in several places in the thermal core and
debugfs code (Sumeet Pawnikar, Thorsten Blum)

* tag 'thermal-6.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (34 commits)
drivers: thermal: intel: tcc_cooling: Drop redundant local variable
thermal/of: Fix reference leak in thermal_of_cm_lookup()
thermal: core: thermal_core.h: fix all kernel-doc warnings
thermal: intel: x86_pkg_temp_thermal: Handle invalid temperature
thermal: renesas: rzg3e: add support for RZ/T2H and RZ/N2H
dt-bindings: thermal: r9a09g047-tsu: document RZ/T2H and RZ/N2H
thermal: renesas: rzg3e: make calibration value retrieval per-chip
thermal: renesas: rzg3e: make min and max temperature per-chip
thermal: renesas: rzg3e: make reset optional
dt-bindings: thermal: r9a09g047-tsu: Document RZ/V2N TSU
thermal/drivers/broadcom: Use clamp to simplify bcm2835_thermal_temp2adc
thermal/drivers/stm32: Use predefined HZ_PER_MHZ instead of a custom one
thermal/drivers/mediatek/lvts_thermal: Add mt7987 support
dt-bindings: thermal: mediatek: Add LVTS thermal controller definition for MT7987
dt-bindings: nvmem: mediatek: efuse: Add support for MT8196
thermal/drivers/mediatek/lvts_thermal: Add MT8196 support
thermal/drivers/mediatek/lvts: Support MSR offset for 16-bit calibration data
thermal/drivers/mediatek/lvts: Add support for ATP mode
thermal/drivers/mediatek/lvts: Add lvts_temp_to_raw variant
thermal/drivers/mediatek/lvts: Add platform ops to support alternative conversion logic
...

+654 -168
+1
Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml
··· 28 28 - enum: 29 29 - mediatek,mt8188-efuse 30 30 - mediatek,mt8189-efuse 31 + - mediatek,mt8196-efuse 31 32 - const: mediatek,mt8186-efuse 32 33 - const: mediatek,mt8186-efuse 33 34
+3
Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
··· 18 18 properties: 19 19 compatible: 20 20 enum: 21 + - mediatek,mt7987-lvts-ap 21 22 - mediatek,mt7988-lvts-ap 22 23 - mediatek,mt8186-lvts 23 24 - mediatek,mt8188-lvts-ap ··· 27 26 - mediatek,mt8192-lvts-mcu 28 27 - mediatek,mt8195-lvts-ap 29 28 - mediatek,mt8195-lvts-mcu 29 + - mediatek,mt8196-lvts-ap 30 + - mediatek,mt8196-lvts-mcu 30 31 31 32 reg: 32 33 maxItems: 1
+30 -4
Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml
··· 17 17 properties: 18 18 compatible: 19 19 oneOf: 20 - - const: renesas,r9a09g047-tsu # RZ/G3E 20 + - enum: 21 + - renesas,r9a09g047-tsu # RZ/G3E 22 + - renesas,r9a09g077-tsu # RZ/T2H 21 23 - items: 22 - - const: renesas,r9a09g057-tsu # RZ/V2H 24 + - enum: 25 + - renesas,r9a09g056-tsu # RZ/V2N 26 + - renesas,r9a09g057-tsu # RZ/V2H 23 27 - const: renesas,r9a09g047-tsu # RZ/G3E 28 + - items: 29 + - const: renesas,r9a09g087-tsu # RZ/N2H 30 + - const: renesas,r9a09g077-tsu # RZ/T2H 24 31 25 32 reg: 26 33 maxItems: 1 ··· 70 63 - compatible 71 64 - reg 72 65 - clocks 73 - - resets 74 66 - power-domains 75 67 - interrupts 76 68 - interrupt-names 77 69 - "#thermal-sensor-cells" 78 - - renesas,tsu-trim 70 + 71 + allOf: 72 + - if: 73 + properties: 74 + compatible: 75 + contains: 76 + const: renesas,r9a09g047-tsu 77 + then: 78 + required: 79 + - resets 80 + - renesas,tsu-trim 81 + 82 + - if: 83 + properties: 84 + compatible: 85 + contains: 86 + const: renesas,r9a09g077-tsu 87 + then: 88 + properties: 89 + resets: false 90 + renesas,tsu-trim: false 79 91 80 92 additionalProperties: false 81 93
+3
Documentation/driver-api/thermal/intel_dptf.rst
··· 375 375 ``workload_hint_enable`` (RW) 376 376 Enable firmware to send workload type hints to user space. 377 377 378 + ``workload_slow_hint_enable`` (RW) 379 + Enable firmware to send slow workload type hints to user space. 380 + 378 381 ``notification_delay_ms`` (RW) 379 382 Minimum delay in milliseconds before firmware will notify OS. This is 380 383 for the rate control of notifications. This delay is between changing
+2 -6
drivers/thermal/broadcom/bcm2835_thermal.c
··· 11 11 #include <linux/err.h> 12 12 #include <linux/io.h> 13 13 #include <linux/kernel.h> 14 + #include <linux/minmax.h> 14 15 #include <linux/module.h> 15 16 #include <linux/of.h> 16 17 #include <linux/of_address.h> ··· 81 80 temp -= offset; 82 81 temp /= slope; 83 82 84 - if (temp < 0) 85 - temp = 0; 86 - if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS)) 87 - temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1; 88 - 89 - return temp; 83 + return clamp(temp, 0, (int)BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1); 90 84 } 91 85 92 86 static int bcm2835_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
+3 -2
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
··· 8 8 #include <linux/kernel.h> 9 9 #include <linux/module.h> 10 10 #include <linux/pci.h> 11 + #include <linux/sysfs.h> 11 12 #include <linux/thermal.h> 12 13 #include <asm/msr.h> 13 14 #include "int340x_thermal_zone.h" ··· 24 23 { \ 25 24 struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); \ 26 25 \ 27 - return sprintf(buf, "%lu\n",\ 26 + return sysfs_emit(buf, "%lu\n",\ 28 27 (unsigned long)proc_dev->power_limits[index].suffix * 1000); \ 29 28 } 30 29 ··· 144 143 if (offset < 0) 145 144 return offset; 146 145 147 - return sprintf(buf, "%d\n", offset); 146 + return sysfs_emit(buf, "%d\n", offset); 148 147 } 149 148 150 149 static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
+5 -4
drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
··· 7 7 #include <linux/kernel.h> 8 8 #include <linux/module.h> 9 9 #include <linux/pci.h> 10 + #include <linux/sysfs.h> 10 11 #include "processor_thermal_device.h" 11 12 12 13 MODULE_IMPORT_NS("INT340X_THERMAL"); ··· 212 211 ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\ 213 212 err = get_mapped_string(mapping, attr->attr.name, ret, &str);\ 214 213 if (!err)\ 215 - return sprintf(buf, "%s\n", str);\ 214 + return sysfs_emit(buf, "%s\n", str);\ 216 215 if (err == -EOPNOTSUPP)\ 217 - return sprintf(buf, "%u\n", ret);\ 216 + return sysfs_emit(buf, "%u\n", ret);\ 218 217 return err;\ 219 218 } 220 219 ··· 399 398 if (ret) 400 399 return ret; 401 400 402 - return sprintf(buf, "%llu\n", resp); 401 + return sysfs_emit(buf, "%llu\n", resp); 403 402 } 404 403 405 404 static ssize_t ddr_data_rate_show(struct device *dev, ··· 414 413 if (ret) 415 414 return ret; 416 415 417 - return sprintf(buf, "%llu\n", resp); 416 + return sysfs_emit(buf, "%llu\n", resp); 418 417 } 419 418 420 419 static DEVICE_ATTR_RW(rfi_restriction);
+49 -8
drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c
··· 34 34 35 35 #define SOC_WT GENMASK_ULL(47, 40) 36 36 37 + #define SOC_WT_SLOW_PREDICTION_INT_ENABLE_BIT 22 37 38 #define SOC_WT_PREDICTION_INT_ENABLE_BIT 23 38 39 39 40 #define SOC_WT_PREDICTION_INT_ACTIVE BIT(2) ··· 48 47 49 48 static DEFINE_MUTEX(wt_lock); 50 49 static u8 wt_enable; 50 + static u8 wt_slow_enable; 51 51 52 52 /* Show current predicted workload type index */ 53 53 static ssize_t workload_type_index_show(struct device *dev, ··· 61 59 int wt; 62 60 63 61 mutex_lock(&wt_lock); 64 - if (!wt_enable) { 62 + if (!wt_enable && !wt_slow_enable) { 65 63 mutex_unlock(&wt_lock); 66 64 return -ENODATA; 67 65 } ··· 86 84 return sysfs_emit(buf, "%d\n", wt_enable); 87 85 } 88 86 89 - static ssize_t workload_hint_enable_store(struct device *dev, 90 - struct device_attribute *attr, 91 - const char *buf, size_t size) 87 + static ssize_t workload_hint_enable(struct device *dev, u8 enable_bit, u8 *status, 88 + struct device_attribute *attr, 89 + const char *buf, size_t size) 92 90 { 93 91 struct pci_dev *pdev = to_pci_dev(dev); 94 92 u8 mode; ··· 101 99 102 100 if (mode) 103 101 ret = processor_thermal_mbox_interrupt_config(pdev, true, 104 - SOC_WT_PREDICTION_INT_ENABLE_BIT, 102 + enable_bit, 105 103 notify_delay); 106 104 else 107 105 ret = processor_thermal_mbox_interrupt_config(pdev, false, 108 - SOC_WT_PREDICTION_INT_ENABLE_BIT, 0); 106 + enable_bit, 0); 109 107 110 108 if (ret) 111 109 goto ret_enable_store; 112 110 113 111 ret = size; 114 - wt_enable = mode; 112 + *status = mode; 115 113 116 114 ret_enable_store: 117 115 mutex_unlock(&wt_lock); ··· 119 117 return ret; 120 118 } 121 119 120 + static ssize_t workload_hint_enable_store(struct device *dev, struct device_attribute *attr, 121 + const char *buf, size_t size) 122 + { 123 + return workload_hint_enable(dev, SOC_WT_PREDICTION_INT_ENABLE_BIT, &wt_enable, 124 + attr, buf, size); 125 + } 122 126 static DEVICE_ATTR_RW(workload_hint_enable); 127 + 128 + static ssize_t workload_slow_hint_enable_show(struct device *dev, struct device_attribute *attr, 129 + char *buf) 130 + { 131 + return sysfs_emit(buf, "%d\n", wt_slow_enable); 132 + } 133 + 134 + static ssize_t workload_slow_hint_enable_store(struct device *dev, struct device_attribute *attr, 135 + const char *buf, size_t size) 136 + { 137 + return workload_hint_enable(dev, SOC_WT_SLOW_PREDICTION_INT_ENABLE_BIT, &wt_slow_enable, 138 + attr, buf, size); 139 + } 140 + static DEVICE_ATTR_RW(workload_slow_hint_enable); 123 141 124 142 static ssize_t notification_delay_ms_show(struct device *dev, 125 143 struct device_attribute *attr, ··· 200 178 201 179 static DEVICE_ATTR_RW(notification_delay_ms); 202 180 181 + static umode_t workload_hint_attr_visible(struct kobject *kobj, struct attribute *attr, int unused) 182 + { 183 + if (attr != &dev_attr_workload_slow_hint_enable.attr) 184 + return attr->mode; 185 + 186 + switch (to_pci_dev(kobj_to_dev(kobj))->device) { 187 + case PCI_DEVICE_ID_INTEL_LNLM_THERMAL: 188 + case PCI_DEVICE_ID_INTEL_MTLP_THERMAL: 189 + case PCI_DEVICE_ID_INTEL_ARL_S_THERMAL: 190 + return 0; 191 + default: 192 + break; 193 + } 194 + 195 + return attr->mode; 196 + } 197 + 203 198 static struct attribute *workload_hint_attrs[] = { 204 199 &dev_attr_workload_type_index.attr, 205 200 &dev_attr_workload_hint_enable.attr, 201 + &dev_attr_workload_slow_hint_enable.attr, 206 202 &dev_attr_notification_delay_ms.attr, 207 203 NULL 208 204 }; 209 205 210 206 static const struct attribute_group workload_hint_attribute_group = { 211 207 .attrs = workload_hint_attrs, 212 - .name = "workload_hint" 208 + .name = "workload_hint", 209 + .is_visible = workload_hint_attr_visible 213 210 }; 214 211 215 212 /*
+4 -3
drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c
··· 7 7 */ 8 8 9 9 #include <linux/pci.h> 10 + #include <linux/sysfs.h> 10 11 #include "processor_thermal_device.h" 11 12 12 13 /* List of workload types */ ··· 29 28 int ret = 0; 30 29 31 30 while (workload_types[i] != NULL) 32 - ret += sprintf(&buf[ret], "%s ", workload_types[i++]); 31 + ret += sysfs_emit_at(buf, ret, "%s ", workload_types[i++]); 33 32 34 - ret += sprintf(&buf[ret], "\n"); 33 + ret += sysfs_emit_at(buf, ret, "\n"); 35 34 36 35 return ret; 37 36 } ··· 86 85 if (cmd_resp > ARRAY_SIZE(workload_types) - 1) 87 86 return -EINVAL; 88 87 89 - return sprintf(buf, "%s\n", workload_types[cmd_resp]); 88 + return sysfs_emit(buf, "%s\n", workload_types[cmd_resp]); 90 89 } 91 90 92 91 static DEVICE_ATTR_RW(workload_type);
-1
drivers/thermal/intel/intel_pch_thermal.c
··· 269 269 270 270 thermal_zone_device_unregister(ptd->tzd); 271 271 iounmap(ptd->hw_base); 272 - pci_set_drvdata(pdev, NULL); 273 272 pci_release_regions(pdev); 274 273 pci_disable_device(pdev); 275 274 }
+4 -4
drivers/thermal/intel/intel_tcc.c
··· 172 172 173 173 /** 174 174 * intel_tcc_get_tjmax() - returns the default TCC activation Temperature 175 - * @cpu: cpu that the MSR should be run on, nagative value means any cpu. 175 + * @cpu: cpu that the MSR should be run on, negative value means any cpu. 176 176 * 177 177 * Get the TjMax value, which is the default thermal throttling or TCC 178 178 * activation temperature in degrees C. ··· 199 199 200 200 /** 201 201 * intel_tcc_get_offset() - returns the TCC Offset value to Tjmax 202 - * @cpu: cpu that the MSR should be run on, nagative value means any cpu. 202 + * @cpu: cpu that the MSR should be run on, negative value means any cpu. 203 203 * 204 204 * Get the TCC offset value to Tjmax. The effective thermal throttling or TCC 205 205 * activation temperature equals "Tjmax" - "TCC Offset", in degrees C. ··· 224 224 225 225 /** 226 226 * intel_tcc_set_offset() - set the TCC offset value to Tjmax 227 - * @cpu: cpu that the MSR should be run on, nagative value means any cpu. 227 + * @cpu: cpu that the MSR should be run on, negative value means any cpu. 228 228 * @offset: TCC offset value in degree C 229 229 * 230 230 * Set the TCC Offset value to Tjmax. The effective thermal throttling or TCC ··· 267 267 268 268 /** 269 269 * intel_tcc_get_temp() - returns the current temperature 270 - * @cpu: cpu that the MSR should be run on, nagative value means any cpu. 270 + * @cpu: cpu that the MSR should be run on, negative value means any cpu. 271 271 * @temp: pointer to the memory for saving cpu temperature. 272 272 * @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor. 273 273 *
+7 -6
drivers/thermal/intel/intel_tcc_cooling.c
··· 65 65 X86_MATCH_VFM(INTEL_RAPTORLAKE, NULL), 66 66 X86_MATCH_VFM(INTEL_RAPTORLAKE_P, NULL), 67 67 X86_MATCH_VFM(INTEL_RAPTORLAKE_S, NULL), 68 + X86_MATCH_VFM(INTEL_PANTHERLAKE_L, NULL), 69 + X86_MATCH_VFM(INTEL_WILDCATLAKE_L, NULL), 70 + X86_MATCH_VFM(INTEL_NOVALAKE, NULL), 71 + X86_MATCH_VFM(INTEL_NOVALAKE_L, NULL), 68 72 {} 69 73 }; 70 74 ··· 76 72 77 73 static int __init tcc_cooling_init(void) 78 74 { 79 - int ret; 80 75 u64 val; 81 76 const struct x86_cpu_id *id; 82 - 83 77 int err; 84 78 85 79 id = x86_match_cpu(tcc_ids); ··· 105 103 tcc_cdev = 106 104 thermal_cooling_device_register("TCC Offset", NULL, 107 105 &tcc_cooling_ops); 108 - if (IS_ERR(tcc_cdev)) { 109 - ret = PTR_ERR(tcc_cdev); 110 - return ret; 111 - } 106 + if (IS_ERR(tcc_cdev)) 107 + return PTR_ERR(tcc_cdev); 108 + 112 109 return 0; 113 110 } 114 111
+3 -2
drivers/thermal/intel/therm_throt.c
··· 23 23 #include <linux/types.h> 24 24 #include <linux/init.h> 25 25 #include <linux/smp.h> 26 + #include <linux/sysfs.h> 26 27 #include <linux/cpu.h> 27 28 28 29 #include <asm/processor.h> ··· 145 144 \ 146 145 preempt_disable(); /* CPU hotplug */ \ 147 146 if (cpu_online(cpu)) { \ 148 - ret = sprintf(buf, "%lu\n", \ 149 - per_cpu(thermal_state, cpu).event.name); \ 147 + ret = sysfs_emit(buf, "%lu\n", \ 148 + per_cpu(thermal_state, cpu).event.name); \ 150 149 } else \ 151 150 ret = 0; \ 152 151 preempt_enable(); \
+3
drivers/thermal/intel/x86_pkg_temp_thermal.c
··· 128 128 u32 l, h, mask, shift, intr; 129 129 int tj_max, val, ret; 130 130 131 + if (temp == THERMAL_TEMP_INVALID) 132 + temp = 0; 133 + 131 134 tj_max = intel_tcc_get_tjmax(zonedev->cpu); 132 135 if (tj_max < 0) 133 136 return tj_max;
+340 -22
drivers/thermal/mediatek/lvts_thermal.c
··· 44 44 #define LVTS_EDATA01(__base) (__base + 0x0058) 45 45 #define LVTS_EDATA02(__base) (__base + 0x005C) 46 46 #define LVTS_EDATA03(__base) (__base + 0x0060) 47 + #define LVTS_MSROFT(__base) (__base + 0x006C) 48 + #define LVTS_ATP0(__base) (__base + 0x0070) 49 + #define LVTS_ATP1(__base) (__base + 0x0074) 50 + #define LVTS_ATP2(__base) (__base + 0x0078) 51 + #define LVTS_ATP3(__base) (__base + 0x007C) 47 52 #define LVTS_MSR0(__base) (__base + 0x0090) 48 53 #define LVTS_MSR1(__base) (__base + 0x0094) 49 54 #define LVTS_MSR2(__base) (__base + 0x0098) ··· 90 85 #define LVTS_GOLDEN_TEMP_DEFAULT 50 91 86 #define LVTS_COEFF_A_MT8195 -250460 92 87 #define LVTS_COEFF_B_MT8195 250460 88 + #define LVTS_COEFF_A_MT7987 -204650 89 + #define LVTS_COEFF_B_MT7987 204650 93 90 #define LVTS_COEFF_A_MT7988 -204650 94 91 #define LVTS_COEFF_B_MT7988 204650 92 + #define LVTS_COEFF_A_MT8196 391460 93 + #define LVTS_COEFF_B_MT8196 -391460 95 94 96 - #define LVTS_MSR_IMMEDIATE_MODE 0 97 - #define LVTS_MSR_FILTERED_MODE 1 95 + #define LVTS_MSR_OFFSET_MT8196 -984 98 96 99 97 #define LVTS_MSR_READ_TIMEOUT_US 400 100 98 #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) 101 99 102 100 #define LVTS_MINIMUM_THRESHOLD 20000 103 101 102 + #define LVTS_MAX_CAL_OFFSETS 3 103 + #define LVTS_NUM_CAL_OFFSETS_MT7988 3 104 + #define LVTS_NUM_CAL_OFFSETS_MT8196 2 105 + 104 106 static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; 105 107 static int golden_temp_offset; 106 108 109 + enum lvts_msr_mode { 110 + LVTS_MSR_IMMEDIATE_MODE, 111 + LVTS_MSR_FILTERED_MODE, 112 + LVTS_MSR_ATP_MODE, 113 + }; 114 + 107 115 struct lvts_sensor_data { 108 116 int dt_id; 109 - u8 cal_offsets[3]; 117 + u8 cal_offsets[LVTS_MAX_CAL_OFFSETS]; 110 118 }; 111 119 112 120 struct lvts_ctrl_data { 113 121 struct lvts_sensor_data lvts_sensor[LVTS_SENSOR_MAX]; 114 122 u8 valid_sensor_mask; 115 123 int offset; 116 - int mode; 124 + enum lvts_msr_mode mode; 117 125 }; 118 126 119 127 #define VALID_SENSOR_MAP(s0, s1, s2, s3) \ ··· 141 123 continue; \ 142 124 else 143 125 126 + struct lvts_platform_ops { 127 + int (*lvts_raw_to_temp)(u32 raw_temp, int temp_factor); 128 + u32 (*lvts_temp_to_raw)(int temperature, int temp_factor); 129 + }; 130 + 144 131 struct lvts_data { 145 132 const struct lvts_ctrl_data *lvts_ctrl; 133 + const struct lvts_platform_ops *ops; 146 134 const u32 *conn_cmd; 147 135 const u32 *init_cmd; 136 + int num_cal_offsets; 148 137 int num_lvts_ctrl; 149 138 int num_conn_cmd; 150 139 int num_init_cmd; ··· 159 134 int temp_offset; 160 135 int gt_calib_bit_offset; 161 136 unsigned int def_calibration; 137 + u16 msr_offset; 162 138 }; 163 139 164 140 struct lvts_sensor { ··· 228 202 LVTS_DEBUG_FS_REGS(LVTS_EDATA01), 229 203 LVTS_DEBUG_FS_REGS(LVTS_EDATA02), 230 204 LVTS_DEBUG_FS_REGS(LVTS_EDATA03), 205 + LVTS_DEBUG_FS_REGS(LVTS_MSROFT), 206 + LVTS_DEBUG_FS_REGS(LVTS_ATP0), 207 + LVTS_DEBUG_FS_REGS(LVTS_ATP1), 208 + LVTS_DEBUG_FS_REGS(LVTS_ATP2), 209 + LVTS_DEBUG_FS_REGS(LVTS_ATP3), 231 210 LVTS_DEBUG_FS_REGS(LVTS_MSR0), 232 211 LVTS_DEBUG_FS_REGS(LVTS_MSR1), 233 212 LVTS_DEBUG_FS_REGS(LVTS_MSR2), ··· 300 269 301 270 #endif 302 271 303 - static int lvts_raw_to_temp(u32 raw_temp, int temp_factor) 272 + static int lvts_raw_to_temp(u32 raw_temp, const struct lvts_data *lvts_data) 273 + { 274 + return lvts_data->ops->lvts_raw_to_temp(raw_temp & 0xFFFF, lvts_data->temp_factor); 275 + } 276 + 277 + static u32 lvts_temp_to_raw(int temperature, const struct lvts_data *lvts_data) 278 + { 279 + return lvts_data->ops->lvts_temp_to_raw(temperature, lvts_data->temp_factor); 280 + } 281 + 282 + static int lvts_raw_to_temp_mt7988(u32 raw_temp, int temp_factor) 304 283 { 305 284 int temperature; 306 285 ··· 320 279 return temperature; 321 280 } 322 281 323 - static u32 lvts_temp_to_raw(int temperature, int temp_factor) 282 + static u32 lvts_temp_to_raw_mt7988(int temperature, int temp_factor) 324 283 { 325 284 u32 raw_temp = ((s64)(golden_temp_offset - temperature)) << 14; 326 285 327 286 raw_temp = div_s64(raw_temp, -temp_factor); 328 287 329 288 return raw_temp; 289 + } 290 + 291 + static u32 lvts_temp_to_raw_mt8196(int temperature, int temp_factor) 292 + { 293 + u32 raw_temp; 294 + 295 + raw_temp = temperature - golden_temp_offset; 296 + 297 + return div_s64((s64)temp_factor << 14, raw_temp); 330 298 } 331 299 332 300 static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) ··· 376 326 if (rc) 377 327 return -EAGAIN; 378 328 379 - *temp = lvts_raw_to_temp(value & 0xFFFF, lvts_data->temp_factor); 329 + *temp = lvts_raw_to_temp(value, lvts_data); 380 330 381 331 return 0; 382 332 } ··· 446 396 const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; 447 397 void __iomem *base = lvts_sensor->base; 448 398 u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD, 449 - lvts_data->temp_factor); 450 - u32 raw_high = lvts_temp_to_raw(high, lvts_data->temp_factor); 399 + lvts_data); 400 + u32 raw_high = lvts_temp_to_raw(high, lvts_data); 451 401 bool should_update_thresh; 452 402 453 403 lvts_sensor->low_thresh = low; ··· 649 599 LVTS_IMMD3(lvts_ctrl->base) 650 600 }; 651 601 602 + void __iomem *atp_regs[] = { 603 + LVTS_ATP0(lvts_ctrl->base), 604 + LVTS_ATP1(lvts_ctrl->base), 605 + LVTS_ATP2(lvts_ctrl->base), 606 + LVTS_ATP3(lvts_ctrl->base) 607 + }; 608 + 652 609 int i; 653 610 654 611 lvts_for_each_valid_sensor(i, lvts_ctrl_data) { ··· 691 634 /* 692 635 * Each sensor has its own register address to read from. 693 636 */ 694 - lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ? 695 - imm_regs[i] : msr_regs[i]; 637 + switch (lvts_ctrl_data->mode) { 638 + case LVTS_MSR_IMMEDIATE_MODE: 639 + lvts_sensor[i].msr = imm_regs[i]; 640 + break; 641 + case LVTS_MSR_FILTERED_MODE: 642 + lvts_sensor[i].msr = msr_regs[i]; 643 + break; 644 + case LVTS_MSR_ATP_MODE: 645 + lvts_sensor[i].msr = atp_regs[i]; 646 + break; 647 + default: 648 + lvts_sensor[i].msr = imm_regs[i]; 649 + break; 650 + } 696 651 697 652 lvts_sensor[i].low_thresh = INT_MIN; 698 653 lvts_sensor[i].high_thresh = INT_MIN; ··· 712 643 713 644 lvts_ctrl->valid_sensor_mask = lvts_ctrl_data->valid_sensor_mask; 714 645 646 + return 0; 647 + } 648 + 649 + static int lvts_decode_sensor_calibration(const struct lvts_sensor_data *sensor, 650 + const u8 *efuse_calibration, u32 calib_len, 651 + u8 num_offsets, u32 *calib) 652 + { 653 + int i; 654 + u32 calib_val = 0; 655 + 656 + for (i = 0; i < num_offsets; i++) { 657 + u8 offset = sensor->cal_offsets[i]; 658 + 659 + if (offset >= calib_len) 660 + return -EINVAL; 661 + // Pack each calibration byte into the correct position 662 + calib_val |= efuse_calibration[offset] << (8 * i); 663 + } 664 + 665 + *calib = calib_val; 715 666 return 0; 716 667 } 717 668 ··· 791 702 * <-----ap--tc#3-----> <-----sensor#7-----> <-----sensor#8-----> 792 703 * 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 | 0x48 793 704 * 705 + * MT8196 : 706 + * Stream index map for MCU Domain mt8196 : 707 + * 708 + * <-sensor#1--> <-sensor#0--> <-sensor#3--> <-sensor#2--> 709 + * 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0A | 0x0B 710 + * 711 + * <-sensor#5--> <-sensor#4--> <-sensor#7--> <-sensor#6--> 712 + * 0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12 | 0x13 713 + * 714 + * <-sensor#9--> <-sensor#8--> <-sensor#11-> <-sensor#10-> 715 + * 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0X1B 716 + * 717 + * <-sensor#13-> <-sensor#12-> <-sensor#15-> <-sensor#14-> 718 + * 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 | 0x22 | 0x23 719 + * 720 + * Stream index map for APU Domain mt8196 : 721 + * 722 + * <-sensor#1--> <-sensor#0--> <-sensor#3--> <-sensor#2--> 723 + * 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A | 0x2B 724 + * 725 + * Stream index map for GPU Domain mt8196 : 726 + * 727 + * <-sensor#1--> <-sensor#0--> 728 + * 0x2C | 0x2D | 0x2E | 0x2F 729 + * 730 + * Stream index map for AP Domain mt8196 : 731 + * 732 + * <-sensor#1--> <-sensor#0--> <-sensor#3--> <-sensor#2--> 733 + * 0x30 | 0x31 | 0x32 | 0x33 | 0x34 | 0x35 | 0x36 | 0x37 734 + * 735 + * <-sensor#5--> <-sensor#4--> <-sensor#6--> <-sensor#7--> 736 + * 0x38 | 0x39 | 0x3A | 0x3B | 0x3C | 0x3D | 0x3E | 0x3F 737 + * 794 738 * Note: In some cases, values don't strictly follow a little endian ordering. 795 739 * The data description gives byte offsets constituting each calibration value 796 740 * for each sensor. ··· 833 711 u8 *efuse_calibration, 834 712 size_t calib_len) 835 713 { 836 - int i; 714 + const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; 715 + int i, ret; 837 716 u32 gt; 838 717 839 718 /* A zero value for gt means that device has invalid efuse data */ 840 - gt = (((u32 *)efuse_calibration)[0] >> lvts_ctrl->lvts_data->gt_calib_bit_offset) & 0xff; 719 + gt = (((u32 *)efuse_calibration)[0] >> lvts_data->gt_calib_bit_offset) & 0xff; 841 720 842 721 lvts_for_each_valid_sensor(i, lvts_ctrl_data) { 843 722 const struct lvts_sensor_data *sensor = 844 723 &lvts_ctrl_data->lvts_sensor[i]; 724 + u32 calib = 0; 845 725 846 - if (sensor->cal_offsets[0] >= calib_len || 847 - sensor->cal_offsets[1] >= calib_len || 848 - sensor->cal_offsets[2] >= calib_len) 849 - return -EINVAL; 726 + ret = lvts_decode_sensor_calibration(sensor, efuse_calibration, 727 + calib_len, 728 + lvts_data->num_cal_offsets, 729 + &calib); 730 + if (ret) 731 + return ret; 850 732 851 733 if (gt) { 852 - lvts_ctrl->calibration[i] = 853 - (efuse_calibration[sensor->cal_offsets[0]] << 0) + 854 - (efuse_calibration[sensor->cal_offsets[1]] << 8) + 855 - (efuse_calibration[sensor->cal_offsets[2]] << 16); 734 + lvts_ctrl->calibration[i] = calib; 735 + if (lvts_ctrl->lvts_data->msr_offset) 736 + lvts_ctrl->calibration[i] += lvts_ctrl->lvts_data->msr_offset; 856 737 } else if (lvts_ctrl->lvts_data->def_calibration) { 857 738 lvts_ctrl->calibration[i] = lvts_ctrl->lvts_data->def_calibration; 858 739 } else { ··· 1009 884 u32 sensor_map = 0; 1010 885 int i; 1011 886 1012 - if (lvts_ctrl->mode != LVTS_MSR_FILTERED_MODE) 887 + if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) 1013 888 return; 1014 889 1015 890 if (enable) { ··· 1162 1037 */ 1163 1038 for (i = 0; i < LVTS_SENSOR_MAX; i++) 1164 1039 writel(lvts_ctrl->calibration[i], lvts_edata[i]); 1040 + 1041 + /* LVTS_MSROFT : Constant offset applied to MSR values 1042 + * for post-processing 1043 + * 1044 + * Bits: 1045 + * 1046 + * 20-0 : Constant data added to MSR values 1047 + */ 1048 + if (lvts_ctrl->lvts_data->msr_offset) 1049 + writel(lvts_ctrl->lvts_data->msr_offset, 1050 + LVTS_MSROFT(lvts_ctrl->base)); 1165 1051 1166 1052 return 0; 1167 1053 } ··· 1509 1373 lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); 1510 1374 } 1511 1375 1376 + static const struct lvts_ctrl_data mt7987_lvts_ap_data_ctrl[] = { 1377 + { 1378 + .lvts_sensor = { 1379 + { .dt_id = MT7987_CPU, 1380 + .cal_offsets = { 0x04, 0x05, 0x06 } }, 1381 + { .dt_id = MT7987_ETH2P5G, 1382 + .cal_offsets = { 0x08, 0x09, 0x0a } }, 1383 + }, 1384 + VALID_SENSOR_MAP(1, 1, 0, 0), 1385 + .offset = 0x0, 1386 + .mode = LVTS_MSR_FILTERED_MODE, 1387 + }, 1388 + }; 1389 + 1512 1390 static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { 1513 1391 { 1514 1392 .lvts_sensor = { ··· 1603 1453 0xC10307A6, 0xC10306B8, 0xC1030500, 0xC1030420, 0xC1030300, 1604 1454 0xC1030030, 0xC10300F6, 0xC1030050, 0xC1030060, 0xC10300AC, 1605 1455 0xC10300FC, 0xC103009D, 0xC10300F1, 0xC10300E1 1456 + }; 1457 + 1458 + static const u32 mt7987_init_cmds[] = { 1459 + 0xC1030300, 0xC1030420, 0xC1030500, 0xC10307A6, 0xC10308C7, 1460 + 0xC103098D, 0xC1030C7C, 0xC1030AA8, 0xC10308CE, 0xC10308C7, 1461 + 0xC1030B04, 0xC1030E01, 0xC10306B8 1606 1462 }; 1607 1463 1608 1464 static const u32 mt7988_init_cmds[] = { ··· 1909 1753 } 1910 1754 }; 1911 1755 1756 + static const struct lvts_ctrl_data mt8196_lvts_mcu_data_ctrl[] = { 1757 + { 1758 + .lvts_sensor = { 1759 + { .dt_id = MT8196_MCU_MEDIUM_CPU6_0, 1760 + .cal_offsets = { 0x06, 0x07 } }, 1761 + { .dt_id = MT8196_MCU_MEDIUM_CPU6_1, 1762 + .cal_offsets = { 0x04, 0x05 } }, 1763 + { .dt_id = MT8196_MCU_DSU2, 1764 + .cal_offsets = { 0x0A, 0x0B } }, 1765 + { .dt_id = MT8196_MCU_DSU3, 1766 + .cal_offsets = { 0x08, 0x09 } } 1767 + }, 1768 + VALID_SENSOR_MAP(1, 1, 1, 1), 1769 + .offset = 0x0, 1770 + .mode = LVTS_MSR_ATP_MODE, 1771 + }, 1772 + { 1773 + .lvts_sensor = { 1774 + { .dt_id = MT8196_MCU_LITTLE_CPU3, 1775 + .cal_offsets = { 0x0E, 0x0F } }, 1776 + { .dt_id = MT8196_MCU_LITTLE_CPU0, 1777 + .cal_offsets = { 0x0C, 0x0D } }, 1778 + { .dt_id = MT8196_MCU_LITTLE_CPU1, 1779 + .cal_offsets = { 0x12, 0x13 } }, 1780 + { .dt_id = MT8196_MCU_LITTLE_CPU2, 1781 + .cal_offsets = { 0x10, 0x11 } } 1782 + }, 1783 + VALID_SENSOR_MAP(1, 1, 1, 1), 1784 + .offset = 0x100, 1785 + .mode = LVTS_MSR_ATP_MODE, 1786 + }, 1787 + { 1788 + .lvts_sensor = { 1789 + { .dt_id = MT8196_MCU_MEDIUM_CPU4_0, 1790 + .cal_offsets = { 0x16, 0x17 } }, 1791 + { .dt_id = MT8196_MCU_MEDIUM_CPU4_1, 1792 + .cal_offsets = { 0x14, 0x15 } }, 1793 + { .dt_id = MT8196_MCU_MEDIUM_CPU5_0, 1794 + .cal_offsets = { 0x1A, 0x1B } }, 1795 + { .dt_id = MT8196_MCU_MEDIUM_CPU5_1, 1796 + .cal_offsets = { 0x18, 0x19 } } 1797 + }, 1798 + VALID_SENSOR_MAP(1, 1, 1, 1), 1799 + .offset = 0x200, 1800 + .mode = LVTS_MSR_ATP_MODE, 1801 + }, 1802 + { 1803 + .lvts_sensor = { 1804 + { .dt_id = MT8196_MCU_DSU0, 1805 + .cal_offsets = { 0x1E, 0x1F } }, 1806 + { .dt_id = MT8196_MCU_DSU1, 1807 + .cal_offsets = { 0x1C, 0x1D } }, 1808 + { .dt_id = MT8196_MCU_BIG_CPU7_0, 1809 + .cal_offsets = { 0x22, 0x23 } }, 1810 + { .dt_id = MT8196_MCU_BIG_CPU7_1, 1811 + .cal_offsets = { 0x20, 0x21 } } 1812 + }, 1813 + VALID_SENSOR_MAP(1, 1, 1, 1), 1814 + .offset = 0x300, 1815 + .mode = LVTS_MSR_ATP_MODE, 1816 + } 1817 + }; 1818 + 1819 + static const struct lvts_ctrl_data mt8196_lvts_ap_data_ctrl[] = { 1820 + { 1821 + .lvts_sensor = { 1822 + { .dt_id = MT8196_AP_TOP0, 1823 + .cal_offsets = { 0x32, 0x33 } }, 1824 + { .dt_id = MT8196_AP_TOP1, 1825 + .cal_offsets = { 0x30, 0x31 } }, 1826 + { .dt_id = MT8196_AP_TOP2, 1827 + .cal_offsets = { 0x36, 0x37 } }, 1828 + { .dt_id = MT8196_AP_TOP3, 1829 + .cal_offsets = { 0x34, 0x35 } } 1830 + }, 1831 + VALID_SENSOR_MAP(1, 1, 1, 1), 1832 + .offset = 0x0, 1833 + .mode = LVTS_MSR_ATP_MODE, 1834 + }, 1835 + { 1836 + .lvts_sensor = { 1837 + { .dt_id = MT8196_AP_BOT0, 1838 + .cal_offsets = { 0x3A, 0x3B } }, 1839 + { .dt_id = MT8196_AP_BOT1, 1840 + .cal_offsets = { 0x38, 0x39 } }, 1841 + { .dt_id = MT8196_AP_BOT2, 1842 + .cal_offsets = { 0x3E, 0x3F } }, 1843 + { .dt_id = MT8196_AP_BOT3, 1844 + .cal_offsets = { 0x3C, 0x3D } } 1845 + }, 1846 + VALID_SENSOR_MAP(1, 1, 1, 1), 1847 + .offset = 0x100, 1848 + .mode = LVTS_MSR_ATP_MODE, 1849 + } 1850 + }; 1851 + 1852 + static const struct lvts_platform_ops lvts_platform_ops_mt7988 = { 1853 + .lvts_raw_to_temp = lvts_raw_to_temp_mt7988, 1854 + .lvts_temp_to_raw = lvts_temp_to_raw_mt7988, 1855 + }; 1856 + 1857 + static const struct lvts_platform_ops lvts_platform_ops_mt8196 = { 1858 + .lvts_raw_to_temp = lvts_raw_to_temp_mt7988, 1859 + .lvts_temp_to_raw = lvts_temp_to_raw_mt8196, 1860 + }; 1861 + 1862 + static const struct lvts_data mt7987_lvts_ap_data = { 1863 + .lvts_ctrl = mt7987_lvts_ap_data_ctrl, 1864 + .num_lvts_ctrl = ARRAY_SIZE(mt7987_lvts_ap_data_ctrl), 1865 + .conn_cmd = mt7988_conn_cmds, 1866 + .init_cmd = mt7987_init_cmds, 1867 + .num_conn_cmd = ARRAY_SIZE(mt7988_conn_cmds), 1868 + .num_init_cmd = ARRAY_SIZE(mt7987_init_cmds), 1869 + .temp_factor = LVTS_COEFF_A_MT7987, 1870 + .temp_offset = LVTS_COEFF_B_MT7987, 1871 + .gt_calib_bit_offset = 32, 1872 + .def_calibration = 19380, 1873 + }; 1874 + 1912 1875 static const struct lvts_data mt7988_lvts_ap_data = { 1913 1876 .lvts_ctrl = mt7988_lvts_ap_data_ctrl, 1914 1877 .conn_cmd = mt7988_conn_cmds, ··· 2038 1763 .temp_factor = LVTS_COEFF_A_MT7988, 2039 1764 .temp_offset = LVTS_COEFF_B_MT7988, 2040 1765 .gt_calib_bit_offset = 24, 1766 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, 1767 + .ops = &lvts_platform_ops_mt7988, 2041 1768 }; 2042 1769 2043 1770 static const struct lvts_data mt8186_lvts_data = { ··· 2053 1776 .temp_offset = LVTS_COEFF_B_MT7988, 2054 1777 .gt_calib_bit_offset = 24, 2055 1778 .def_calibration = 19000, 1779 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, 1780 + .ops = &lvts_platform_ops_mt7988, 2056 1781 }; 2057 1782 2058 1783 static const struct lvts_data mt8188_lvts_mcu_data = { ··· 2068 1789 .temp_offset = LVTS_COEFF_B_MT8195, 2069 1790 .gt_calib_bit_offset = 20, 2070 1791 .def_calibration = 35000, 1792 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, 1793 + .ops = &lvts_platform_ops_mt7988, 2071 1794 }; 2072 1795 2073 1796 static const struct lvts_data mt8188_lvts_ap_data = { ··· 2083 1802 .temp_offset = LVTS_COEFF_B_MT8195, 2084 1803 .gt_calib_bit_offset = 20, 2085 1804 .def_calibration = 35000, 1805 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, 1806 + .ops = &lvts_platform_ops_mt7988, 2086 1807 }; 2087 1808 2088 1809 static const struct lvts_data mt8192_lvts_mcu_data = { ··· 2098 1815 .temp_offset = LVTS_COEFF_B_MT8195, 2099 1816 .gt_calib_bit_offset = 24, 2100 1817 .def_calibration = 35000, 1818 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, 1819 + .ops = &lvts_platform_ops_mt7988, 2101 1820 }; 2102 1821 2103 1822 static const struct lvts_data mt8192_lvts_ap_data = { ··· 2113 1828 .temp_offset = LVTS_COEFF_B_MT8195, 2114 1829 .gt_calib_bit_offset = 24, 2115 1830 .def_calibration = 35000, 1831 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, 1832 + .ops = &lvts_platform_ops_mt7988, 2116 1833 }; 2117 1834 2118 1835 static const struct lvts_data mt8195_lvts_mcu_data = { ··· 2128 1841 .temp_offset = LVTS_COEFF_B_MT8195, 2129 1842 .gt_calib_bit_offset = 24, 2130 1843 .def_calibration = 35000, 1844 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, 1845 + .ops = &lvts_platform_ops_mt7988, 2131 1846 }; 2132 1847 2133 1848 static const struct lvts_data mt8195_lvts_ap_data = { ··· 2143 1854 .temp_offset = LVTS_COEFF_B_MT8195, 2144 1855 .gt_calib_bit_offset = 24, 2145 1856 .def_calibration = 35000, 1857 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, 1858 + .ops = &lvts_platform_ops_mt7988, 1859 + }; 1860 + 1861 + static const struct lvts_data mt8196_lvts_mcu_data = { 1862 + .lvts_ctrl = mt8196_lvts_mcu_data_ctrl, 1863 + .num_lvts_ctrl = ARRAY_SIZE(mt8196_lvts_mcu_data_ctrl), 1864 + .temp_factor = LVTS_COEFF_A_MT8196, 1865 + .temp_offset = LVTS_COEFF_B_MT8196, 1866 + .gt_calib_bit_offset = 0, 1867 + .def_calibration = 14437, 1868 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT8196, 1869 + .msr_offset = LVTS_MSR_OFFSET_MT8196, 1870 + .ops = &lvts_platform_ops_mt8196, 1871 + }; 1872 + 1873 + static const struct lvts_data mt8196_lvts_ap_data = { 1874 + .lvts_ctrl = mt8196_lvts_ap_data_ctrl, 1875 + .num_lvts_ctrl = ARRAY_SIZE(mt8196_lvts_ap_data_ctrl), 1876 + .temp_factor = LVTS_COEFF_A_MT8196, 1877 + .temp_offset = LVTS_COEFF_B_MT8196, 1878 + .gt_calib_bit_offset = 0, 1879 + .def_calibration = 14437, 1880 + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT8196, 1881 + .msr_offset = LVTS_MSR_OFFSET_MT8196, 1882 + .ops = &lvts_platform_ops_mt8196, 2146 1883 }; 2147 1884 2148 1885 static const struct of_device_id lvts_of_match[] = { 1886 + { .compatible = "mediatek,mt7987-lvts-ap", .data = &mt7987_lvts_ap_data }, 2149 1887 { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data }, 2150 1888 { .compatible = "mediatek,mt8186-lvts", .data = &mt8186_lvts_data }, 2151 1889 { .compatible = "mediatek,mt8188-lvts-mcu", .data = &mt8188_lvts_mcu_data }, ··· 2181 1865 { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data }, 2182 1866 { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, 2183 1867 { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data }, 1868 + { .compatible = "mediatek,mt8196-lvts-mcu", .data = &mt8196_lvts_mcu_data }, 1869 + { .compatible = "mediatek,mt8196-lvts-ap", .data = &mt8196_lvts_ap_data }, 2184 1870 {}, 2185 1871 }; 2186 1872 MODULE_DEVICE_TABLE(of, lvts_of_match);
+74 -49
drivers/thermal/renesas/rzg3e_thermal.c
··· 4 4 * 5 5 * Copyright (C) 2025 Renesas Electronics Corporation 6 6 */ 7 + #include <linux/arm-smccc.h> 7 8 #include <linux/clk.h> 8 9 #include <linux/cleanup.h> 9 10 #include <linux/delay.h> ··· 63 62 #define TSU_SICR_CMPCLR BIT(1) 64 63 65 64 /* Temperature calculation constants from datasheet */ 66 - #define TSU_TEMP_D (-41) 67 - #define TSU_TEMP_E 126 68 65 #define TSU_CODE_MAX 0xFFF 69 66 70 67 /* Timing specifications from datasheet */ ··· 71 72 #define TSU_POLL_DELAY_US 10 /* Polling interval */ 72 73 #define TSU_MIN_CLOCK_RATE 24000000 /* TSU_PCLK minimum 24MHz */ 73 74 75 + #define RZ_SIP_SVC_GET_SYSTSU 0x82000022 76 + #define OTP_TSU_REG_ADR_TEMPHI 0x01DC 77 + #define OTP_TSU_REG_ADR_TEMPLO 0x01DD 78 + 79 + struct rzg3e_thermal_priv; 80 + 81 + struct rzg3e_thermal_info { 82 + int (*get_trim)(struct rzg3e_thermal_priv *priv); 83 + int temp_d_mc; 84 + int temp_e_mc; 85 + }; 86 + 74 87 /** 75 88 * struct rzg3e_thermal_priv - RZ/G3E TSU private data 76 89 * @base: TSU register base ··· 90 79 * @syscon: regmap for calibration values 91 80 * @zone: thermal zone device 92 81 * @rstc: reset control 82 + * @info: chip type specific information 93 83 * @trmval0: calibration value 0 (b) 94 84 * @trmval1: calibration value 1 (c) 95 85 * @trim_offset: offset for trim registers in syscon ··· 99 87 struct rzg3e_thermal_priv { 100 88 void __iomem *base; 101 89 struct device *dev; 102 - struct regmap *syscon; 103 90 struct thermal_zone_device *zone; 104 91 struct reset_control *rstc; 92 + const struct rzg3e_thermal_info *info; 105 93 u16 trmval0; 106 94 u16 trmval1; 107 - u32 trim_offset; 108 95 struct mutex lock; 109 96 }; 110 97 ··· 172 161 */ 173 162 static int rzg3e_thermal_code_to_temp(struct rzg3e_thermal_priv *priv, u16 code) 174 163 { 175 - int temp_e_mc = TSU_TEMP_E * MILLIDEGREE_PER_DEGREE; 176 - int temp_d_mc = TSU_TEMP_D * MILLIDEGREE_PER_DEGREE; 164 + const struct rzg3e_thermal_info *info = priv->info; 177 165 s64 numerator, denominator; 178 166 int temp_mc; 179 167 180 - numerator = (temp_e_mc - temp_d_mc) * (s64)(code - priv->trmval0); 168 + numerator = (info->temp_e_mc - info->temp_d_mc) * 169 + (s64)(code - priv->trmval0); 181 170 denominator = priv->trmval1 - priv->trmval0; 182 171 183 - temp_mc = div64_s64(numerator, denominator) + temp_d_mc; 172 + temp_mc = div64_s64(numerator, denominator) + info->temp_d_mc; 184 173 185 - return clamp(temp_mc, temp_d_mc, temp_e_mc); 174 + return clamp(temp_mc, info->temp_d_mc, info->temp_e_mc); 186 175 } 187 176 188 177 /* ··· 191 180 */ 192 181 static u16 rzg3e_thermal_temp_to_code(struct rzg3e_thermal_priv *priv, int temp_mc) 193 182 { 194 - int temp_e_mc = TSU_TEMP_E * MILLIDEGREE_PER_DEGREE; 195 - int temp_d_mc = TSU_TEMP_D * MILLIDEGREE_PER_DEGREE; 183 + const struct rzg3e_thermal_info *info = priv->info; 196 184 s64 numerator, denominator; 197 185 s64 code; 198 186 199 - numerator = (temp_mc - temp_d_mc) * (priv->trmval1 - priv->trmval0); 200 - denominator = temp_e_mc - temp_d_mc; 187 + numerator = (temp_mc - info->temp_d_mc) * (priv->trmval1 - priv->trmval0); 188 + denominator = info->temp_e_mc - info->temp_d_mc; 201 189 202 190 code = div64_s64(numerator, denominator) + priv->trmval0; 203 191 ··· 340 330 .set_trips = rzg3e_thermal_set_trips, 341 331 }; 342 332 343 - static int rzg3e_thermal_get_calibration(struct rzg3e_thermal_priv *priv) 333 + static int rzg3e_thermal_get_syscon_trim(struct rzg3e_thermal_priv *priv) 344 334 { 345 - u32 val; 335 + struct device_node *np = priv->dev->of_node; 336 + struct regmap *syscon; 337 + u32 offset; 346 338 int ret; 339 + u32 val; 340 + 341 + syscon = syscon_regmap_lookup_by_phandle_args(np, "renesas,tsu-trim", 1, &offset); 342 + if (IS_ERR(syscon)) 343 + return dev_err_probe(priv->dev, PTR_ERR(syscon), 344 + "Failed to parse renesas,tsu-trim\n"); 347 345 348 346 /* Read calibration values from syscon */ 349 - ret = regmap_read(priv->syscon, priv->trim_offset, &val); 347 + ret = regmap_read(syscon, offset, &val); 350 348 if (ret) 351 349 return ret; 352 - priv->trmval0 = val & GENMASK(11, 0); 350 + priv->trmval0 = val & TSU_CODE_MAX; 353 351 354 - ret = regmap_read(priv->syscon, priv->trim_offset + 4, &val); 352 + ret = regmap_read(syscon, offset + 4, &val); 355 353 if (ret) 356 354 return ret; 357 - priv->trmval1 = val & GENMASK(11, 0); 358 - 359 - /* Validate calibration data */ 360 - if (!priv->trmval0 || !priv->trmval1 || 361 - priv->trmval0 == priv->trmval1 || 362 - priv->trmval0 == 0xFFF || priv->trmval1 == 0xFFF) { 363 - dev_err(priv->dev, "Invalid calibration: b=0x%03x, c=0x%03x\n", 364 - priv->trmval0, priv->trmval1); 365 - return -EINVAL; 366 - } 367 - 368 - dev_dbg(priv->dev, "Calibration: b=0x%03x (%u), c=0x%03x (%u)\n", 369 - priv->trmval0, priv->trmval0, priv->trmval1, priv->trmval1); 355 + priv->trmval1 = val & TSU_CODE_MAX; 370 356 371 357 return 0; 372 358 } 373 359 374 - static int rzg3e_thermal_parse_dt(struct rzg3e_thermal_priv *priv) 360 + static int rzg3e_thermal_get_smc_trim(struct rzg3e_thermal_priv *priv) 375 361 { 376 - struct device_node *np = priv->dev->of_node; 377 - u32 offset; 362 + struct arm_smccc_res local_res; 378 363 379 - priv->syscon = syscon_regmap_lookup_by_phandle_args(np, "renesas,tsu-trim", 1, &offset); 380 - if (IS_ERR(priv->syscon)) 381 - return dev_err_probe(priv->dev, PTR_ERR(priv->syscon), 382 - "Failed to parse renesas,tsu-trim\n"); 364 + arm_smccc_smc(RZ_SIP_SVC_GET_SYSTSU, OTP_TSU_REG_ADR_TEMPLO, 365 + 0, 0, 0, 0, 0, 0, &local_res); 366 + priv->trmval0 = local_res.a0 & TSU_CODE_MAX; 383 367 384 - priv->trim_offset = offset; 368 + arm_smccc_smc(RZ_SIP_SVC_GET_SYSTSU, OTP_TSU_REG_ADR_TEMPHI, 369 + 0, 0, 0, 0, 0, 0, &local_res); 370 + priv->trmval1 = local_res.a0 & TSU_CODE_MAX; 371 + 385 372 return 0; 386 373 } 387 374 ··· 399 392 return ret; 400 393 platform_set_drvdata(pdev, priv); 401 394 395 + priv->info = device_get_match_data(dev); 396 + 402 397 priv->base = devm_platform_ioremap_resource(pdev, 0); 403 398 if (IS_ERR(priv->base)) 404 399 return PTR_ERR(priv->base); 405 400 406 - /* Parse device tree for trim register info */ 407 - ret = rzg3e_thermal_parse_dt(priv); 401 + ret = priv->info->get_trim(priv); 408 402 if (ret) 409 403 return ret; 404 + 405 + if (!priv->trmval0 || !priv->trmval1 || 406 + priv->trmval0 == priv->trmval1 || 407 + priv->trmval0 == TSU_CODE_MAX || priv->trmval1 == TSU_CODE_MAX) 408 + return dev_err_probe(priv->dev, -EINVAL, 409 + "Invalid calibration: b=0x%03x, c=0x%03x\n", 410 + priv->trmval0, priv->trmval1); 411 + 412 + dev_dbg(priv->dev, "Calibration: b=0x%03x (%u), c=0x%03x (%u)\n", 413 + priv->trmval0, priv->trmval0, priv->trmval1, priv->trmval1); 410 414 411 415 /* Get clock to verify frequency - clock is managed by power domain */ 412 416 clk = devm_clk_get(dev, NULL); ··· 430 412 "Clock rate %lu Hz too low (min %u Hz)\n", 431 413 clk_get_rate(clk), TSU_MIN_CLOCK_RATE); 432 414 433 - priv->rstc = devm_reset_control_get_exclusive_deasserted(dev, NULL); 415 + priv->rstc = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL); 434 416 if (IS_ERR(priv->rstc)) 435 417 return dev_err_probe(dev, PTR_ERR(priv->rstc), 436 418 "Failed to get/deassert reset control\n"); 437 - 438 - /* Get calibration data */ 439 - ret = rzg3e_thermal_get_calibration(priv); 440 - if (ret) 441 - return dev_err_probe(dev, ret, 442 - "Failed to get valid calibration data\n"); 443 419 444 420 /* Get comparison interrupt */ 445 421 irq = platform_get_irq_byname(pdev, "adcmpi"); ··· 538 526 SYSTEM_SLEEP_PM_OPS(rzg3e_thermal_suspend, rzg3e_thermal_resume) 539 527 }; 540 528 529 + static const struct rzg3e_thermal_info rzg3e_thermal_info = { 530 + .get_trim = rzg3e_thermal_get_syscon_trim, 531 + .temp_d_mc = -41000, 532 + .temp_e_mc = 126000, 533 + }; 534 + 535 + static const struct rzg3e_thermal_info rzt2h_thermal_info = { 536 + .get_trim = rzg3e_thermal_get_smc_trim, 537 + .temp_d_mc = -40000, 538 + .temp_e_mc = 125000, 539 + }; 540 + 541 541 static const struct of_device_id rzg3e_thermal_dt_ids[] = { 542 - { .compatible = "renesas,r9a09g047-tsu" }, 542 + { .compatible = "renesas,r9a09g047-tsu", .data = &rzg3e_thermal_info }, 543 + { .compatible = "renesas,r9a09g077-tsu", .data = &rzt2h_thermal_info }, 543 544 { /* sentinel */ } 544 545 }; 545 546 MODULE_DEVICE_TABLE(of, rzg3e_thermal_dt_ids);
+2 -2
drivers/thermal/st/stm_thermal.c
··· 16 16 #include <linux/of.h> 17 17 #include <linux/platform_device.h> 18 18 #include <linux/thermal.h> 19 + #include <linux/units.h> 19 20 20 21 #include "../thermal_hwmon.h" 21 22 ··· 77 76 78 77 /* Constants */ 79 78 #define ADJUST 100 80 - #define ONE_MHZ 1000000 81 79 #define POLL_TIMEOUT 5000 82 80 #define STARTUP_TIME 40 83 81 #define TS1_T0_VAL0 30000 /* 30 celsius */ ··· 205 205 return -EINVAL; 206 206 207 207 prescaler = 0; 208 - clk_freq /= ONE_MHZ; 208 + clk_freq /= HZ_PER_MHZ; 209 209 if (clk_freq) { 210 210 while (prescaler <= clk_freq) 211 211 prescaler++;
+6 -2
drivers/thermal/thermal_core.c
··· 1505 1505 const struct thermal_trip *trip = trips; 1506 1506 struct thermal_zone_device *tz; 1507 1507 struct thermal_trip_desc *td; 1508 + size_t type_len = 0; 1508 1509 int id; 1509 1510 int result; 1510 1511 1511 - if (!type || strlen(type) == 0) { 1512 + if (type) 1513 + type_len = strnlen(type, THERMAL_NAME_LENGTH); 1514 + 1515 + if (type_len == 0) { 1512 1516 pr_err("No thermal zone type defined\n"); 1513 1517 return ERR_PTR(-EINVAL); 1514 1518 } 1515 1519 1516 - if (strlen(type) >= THERMAL_NAME_LENGTH) { 1520 + if (type_len == THERMAL_NAME_LENGTH) { 1517 1521 pr_err("Thermal zone name (%s) too long, should be under %d chars\n", 1518 1522 type, THERMAL_NAME_LENGTH); 1519 1523 return ERR_PTR(-EINVAL);
+5 -2
drivers/thermal/thermal_core.h
··· 77 77 * @device: &struct device for this thermal zone 78 78 * @removal: removal completion 79 79 * @resume: resume completion 80 + * @trips_attribute_group: trip point sysfs attributes 80 81 * @trips_high: trips above the current zone temperature 81 82 * @trips_reached: trips below or at the current zone temperature 82 83 * @trips_invalid: trips with invalid temperature ··· 98 97 * @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION 99 98 * @passive: 1 if you've crossed a passive trip point, 0 otherwise. 100 99 * @prev_low_trip: the low current temperature if you've crossed a passive 101 - trip point. 100 + * trip point. 102 101 * @prev_high_trip: the above current temperature if you've crossed a 103 - passive trip point. 102 + * passive trip point. 104 103 * @ops: operations this &thermal_zone_device supports 105 104 * @tzp: thermal zone parameters 106 105 * @governor: pointer to the governor for this thermal zone ··· 112 111 * @poll_queue: delayed work for polling 113 112 * @notify_event: Last notification event 114 113 * @state: current state of the thermal zone 114 + * @debugfs: this thermal zone device's thermal zone debug info 115 + * @user_thresholds: list of userspace thresholds for temp. limit notifications 115 116 * @trips: array of struct thermal_trip objects 116 117 */ 117 118 struct thermal_zone_device {
+1 -1
drivers/thermal/thermal_debugfs.c
··· 807 807 seq_printf(s, ",-Mitigation at %llums, duration%c%llums, max. temp=%dm°C\n", 808 808 ktime_to_ms(tze->timestamp), c, duration_ms, tze->max_temp); 809 809 810 - seq_printf(s, "| trip | type | temp(m°C) | hyst(m°C) | duration(ms) | avg(m°C) | min(m°C) |\n"); 810 + seq_puts(s, "| trip | type | temp(m°C) | hyst(m°C) | duration(ms) | avg(m°C) | min(m°C) |\n"); 811 811 812 812 for_each_trip_desc(tz, td) { 813 813 const struct thermal_trip *trip = &td->trip;
+2 -2
drivers/thermal/thermal_hwmon.c
··· 63 63 if (ret) 64 64 return ret; 65 65 66 - return sprintf(buf, "%d\n", temperature); 66 + return sysfs_emit(buf, "%d\n", temperature); 67 67 } 68 68 69 69 static ssize_t ··· 84 84 if (ret) 85 85 return ret; 86 86 87 - return sprintf(buf, "%d\n", temperature); 87 + return sysfs_emit(buf, "%d\n", temperature); 88 88 } 89 89 90 90
+2 -2
drivers/thermal/thermal_of.c
··· 280 280 struct cooling_spec *c) 281 281 { 282 282 for_each_child_of_node_scoped(cm_np, child) { 283 - struct device_node *tr_np; 284 283 int count, i; 285 284 286 - tr_np = of_parse_phandle(child, "trip", 0); 285 + struct device_node *tr_np __free(device_node) = 286 + of_parse_phandle(child, "trip", 0); 287 287 if (tr_np != trip->priv) 288 288 continue; 289 289
+19 -19
drivers/thermal/thermal_sysfs.c
··· 29 29 { 30 30 struct thermal_zone_device *tz = to_thermal_zone(dev); 31 31 32 - return sprintf(buf, "%s\n", tz->type); 32 + return sysfs_emit(buf, "%s\n", tz->type); 33 33 } 34 34 35 35 static ssize_t ··· 41 41 ret = thermal_zone_get_temp(tz, &temperature); 42 42 43 43 if (!ret) 44 - return sprintf(buf, "%d\n", temperature); 44 + return sysfs_emit(buf, "%d\n", temperature); 45 45 46 46 if (ret == -EAGAIN) 47 47 return -ENODATA; ··· 57 57 guard(thermal_zone)(tz); 58 58 59 59 if (tz->mode == THERMAL_DEVICE_ENABLED) 60 - return sprintf(buf, "enabled\n"); 60 + return sysfs_emit(buf, "enabled\n"); 61 61 62 - return sprintf(buf, "disabled\n"); 62 + return sysfs_emit(buf, "disabled\n"); 63 63 } 64 64 65 65 static ssize_t ··· 97 97 { 98 98 struct thermal_trip *trip = thermal_trip_of_attr(attr, type); 99 99 100 - return sprintf(buf, "%s\n", thermal_trip_type_name(trip->type)); 100 + return sysfs_emit(buf, "%s\n", thermal_trip_type_name(trip->type)); 101 101 } 102 102 103 103 static ssize_t ··· 142 142 { 143 143 struct thermal_trip *trip = thermal_trip_of_attr(attr, temp); 144 144 145 - return sprintf(buf, "%d\n", READ_ONCE(trip->temperature)); 145 + return sysfs_emit(buf, "%d\n", READ_ONCE(trip->temperature)); 146 146 } 147 147 148 148 static ssize_t ··· 188 188 { 189 189 struct thermal_trip *trip = thermal_trip_of_attr(attr, hyst); 190 190 191 - return sprintf(buf, "%d\n", READ_ONCE(trip->hysteresis)); 191 + return sysfs_emit(buf, "%d\n", READ_ONCE(trip->hysteresis)); 192 192 } 193 193 194 194 static ssize_t ··· 199 199 char name[THERMAL_NAME_LENGTH]; 200 200 int ret; 201 201 202 - snprintf(name, sizeof(name), "%s", buf); 202 + strscpy(name, buf); 203 203 204 204 ret = thermal_zone_device_set_policy(tz, name); 205 205 if (!ret) ··· 213 213 { 214 214 struct thermal_zone_device *tz = to_thermal_zone(dev); 215 215 216 - return sprintf(buf, "%s\n", tz->governor->name); 216 + return sysfs_emit(buf, "%s\n", tz->governor->name); 217 217 } 218 218 219 219 static ssize_t ··· 260 260 struct thermal_zone_device *tz = to_thermal_zone(dev); 261 261 262 262 if (tz->tzp) 263 - return sprintf(buf, "%u\n", tz->tzp->sustainable_power); 263 + return sysfs_emit(buf, "%u\n", tz->tzp->sustainable_power); 264 264 else 265 265 return -EIO; 266 266 } ··· 291 291 struct thermal_zone_device *tz = to_thermal_zone(dev); \ 292 292 \ 293 293 if (tz->tzp) \ 294 - return sprintf(buf, "%d\n", tz->tzp->name); \ 294 + return sysfs_emit(buf, "%d\n", tz->tzp->name); \ 295 295 else \ 296 296 return -EIO; \ 297 297 } \ ··· 505 505 { 506 506 struct thermal_cooling_device *cdev = to_cooling_device(dev); 507 507 508 - return sprintf(buf, "%s\n", cdev->type); 508 + return sysfs_emit(buf, "%s\n", cdev->type); 509 509 } 510 510 511 511 static ssize_t max_state_show(struct device *dev, struct device_attribute *attr, ··· 513 513 { 514 514 struct thermal_cooling_device *cdev = to_cooling_device(dev); 515 515 516 - return sprintf(buf, "%ld\n", cdev->max_state); 516 + return sysfs_emit(buf, "%ld\n", cdev->max_state); 517 517 } 518 518 519 519 static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr, ··· 526 526 ret = cdev->ops->get_cur_state(cdev, &state); 527 527 if (ret) 528 528 return ret; 529 - return sprintf(buf, "%ld\n", state); 529 + return sysfs_emit(buf, "%ld\n", state); 530 530 } 531 531 532 532 static ssize_t ··· 638 638 return 0; 639 639 640 640 spin_lock(&stats->lock); 641 - ret = sprintf(buf, "%u\n", stats->total_trans); 641 + ret = sysfs_emit(buf, "%u\n", stats->total_trans); 642 642 spin_unlock(&stats->lock); 643 643 644 644 return ret; ··· 664 664 update_time_in_state(stats); 665 665 666 666 for (i = 0; i <= cdev->max_state; i++) { 667 - len += sprintf(buf + len, "state%u\t%llu\n", i, 668 - ktime_to_ms(stats->time_in_state[i])); 667 + len += sysfs_emit_at(buf, len, "state%u\t%llu\n", i, 668 + ktime_to_ms(stats->time_in_state[i])); 669 669 } 670 670 spin_unlock(&stats->lock); 671 671 ··· 846 846 847 847 instance = container_of(attr, struct thermal_instance, attr); 848 848 849 - return sprintf(buf, "%d\n", thermal_zone_trip_id(tz, instance->trip)); 849 + return sysfs_emit(buf, "%d\n", thermal_zone_trip_id(tz, instance->trip)); 850 850 } 851 851 852 852 ssize_t ··· 856 856 857 857 instance = container_of(attr, struct thermal_instance, weight_attr); 858 858 859 - return sprintf(buf, "%d\n", instance->weight); 859 + return sysfs_emit(buf, "%d\n", instance->weight); 860 860 } 861 861 862 862 ssize_t weight_store(struct device *dev, struct device_attribute *attr,
+29
include/dt-bindings/thermal/mediatek,lvts-thermal.h
··· 7 7 #ifndef __MEDIATEK_LVTS_DT_H 8 8 #define __MEDIATEK_LVTS_DT_H 9 9 10 + #define MT7987_CPU 0 11 + #define MT7987_ETH2P5G 1 12 + 10 13 #define MT7988_CPU_0 0 11 14 #define MT7988_CPU_1 1 12 15 #define MT7988_ETH2P5G_0 2 ··· 82 79 #define MT8192_AP_MD0 14 83 80 #define MT8192_AP_MD1 15 84 81 #define MT8192_AP_MD2 16 82 + 83 + #define MT8196_MCU_MEDIUM_CPU6_0 0 84 + #define MT8196_MCU_MEDIUM_CPU6_1 1 85 + #define MT8196_MCU_DSU2 2 86 + #define MT8196_MCU_DSU3 3 87 + #define MT8196_MCU_LITTLE_CPU3 4 88 + #define MT8196_MCU_LITTLE_CPU0 5 89 + #define MT8196_MCU_LITTLE_CPU1 6 90 + #define MT8196_MCU_LITTLE_CPU2 7 91 + #define MT8196_MCU_MEDIUM_CPU4_0 8 92 + #define MT8196_MCU_MEDIUM_CPU4_1 9 93 + #define MT8196_MCU_MEDIUM_CPU5_0 10 94 + #define MT8196_MCU_MEDIUM_CPU5_1 11 95 + #define MT8196_MCU_DSU0 12 96 + #define MT8196_MCU_DSU1 13 97 + #define MT8196_MCU_BIG_CPU7_0 14 98 + #define MT8196_MCU_BIG_CPU7_1 15 99 + 100 + #define MT8196_AP_TOP0 0 101 + #define MT8196_AP_TOP1 1 102 + #define MT8196_AP_TOP2 2 103 + #define MT8196_AP_TOP3 3 104 + #define MT8196_AP_BOT0 4 105 + #define MT8196_AP_BOT1 5 106 + #define MT8196_AP_BOT2 6 107 + #define MT8196_AP_BOT3 7 85 108 86 109 #endif /* __MEDIATEK_LVTS_DT_H */
+2 -2
tools/lib/thermal/libthermal.pc.template
··· 8 8 Description: thermal library 9 9 Requires: libnl-3.0 libnl-genl-3.0 10 10 Version: @VERSION@ 11 - Libs: -L${libdir} -lnl-genl-3 -lnl-3 12 - Cflags: -I${includedir} -I${include}/libnl3 11 + Libs: -L${libdir} -lnl-genl-3 -lnl-3 -lthermal 12 + Cflags: -I${includedir} -I${includedir}/libnl3
+55 -25
tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c
··· 12 12 13 13 #define WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/notification_delay_ms" 14 14 #define WORKLOAD_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_hint_enable" 15 + #define WORKLOAD_SLOW_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_slow_hint_enable" 15 16 #define WORKLOAD_TYPE_INDEX_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_type_index" 16 17 17 18 static const char * const workload_types[] = { ··· 23 22 NULL 24 23 }; 25 24 25 + static int wlt_slow; 26 + static char *wlt_enable_attr; 27 + 26 28 #define WORKLOAD_TYPE_MAX_INDEX 3 27 29 28 30 void workload_hint_exit(int signum) ··· 34 30 35 31 /* Disable feature via sysfs knob */ 36 32 37 - fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); 33 + fd = open(wlt_enable_attr, O_RDWR); 38 34 if (fd < 0) { 39 35 perror("Unable to open workload type feature enable file"); 40 36 exit(1); ··· 50 46 close(fd); 51 47 } 52 48 49 + static void update_delay(char *delay_str) 50 + { 51 + int fd; 52 + 53 + printf("Setting notification delay in ms to %s\n", delay_str); 54 + 55 + fd = open(WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE, O_RDWR); 56 + if (fd < 0) { 57 + perror("Unable to open workload notification delay"); 58 + exit(1); 59 + } 60 + 61 + if (write(fd, delay_str, strlen(delay_str)) < 0) { 62 + perror("Can't set delay"); 63 + exit(1); 64 + } 65 + 66 + close(fd); 67 + } 68 + 53 69 int main(int argc, char **argv) 54 70 { 55 71 struct pollfd ufd; ··· 78 54 char delay_str[64]; 79 55 int delay = 0; 80 56 81 - printf("Usage: workload_hint_test [notification delay in milli seconds]\n"); 57 + printf("Usage: workload_hint_test [notification delay in milli seconds][slow]\n"); 82 58 83 59 if (argc > 1) { 84 - ret = sscanf(argv[1], "%d", &delay); 85 - if (ret < 0) { 86 - printf("Invalid delay\n"); 87 - exit(1); 60 + int i; 61 + 62 + for (i = 1; i < argc; ++i) { 63 + if (!strcmp(argv[i], "slow")) { 64 + wlt_slow = 1; 65 + continue; 66 + } 67 + 68 + ret = sscanf(argv[1], "%d", &delay); 69 + if (ret < 0) { 70 + printf("Invalid delay\n"); 71 + exit(1); 72 + } 73 + 74 + sprintf(delay_str, "%s\n", argv[1]); 75 + update_delay(delay_str); 88 76 } 89 - 90 - printf("Setting notification delay to %d ms\n", delay); 91 - if (delay < 0) 92 - exit(1); 93 - 94 - sprintf(delay_str, "%s\n", argv[1]); 95 - fd = open(WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE, O_RDWR); 96 - if (fd < 0) { 97 - perror("Unable to open workload notification delay"); 98 - exit(1); 99 - } 100 - 101 - if (write(fd, delay_str, strlen(delay_str)) < 0) { 102 - perror("Can't set delay"); 103 - exit(1); 104 - } 105 - 106 - close(fd); 107 77 } 108 78 109 79 if (signal(SIGINT, workload_hint_exit) == SIG_IGN) ··· 107 89 if (signal(SIGTERM, workload_hint_exit) == SIG_IGN) 108 90 signal(SIGTERM, SIG_IGN); 109 91 92 + if (wlt_slow) 93 + wlt_enable_attr = WORKLOAD_SLOW_ENABLE_ATTRIBUTE; 94 + else 95 + wlt_enable_attr = WORKLOAD_ENABLE_ATTRIBUTE; 96 + 110 97 /* Enable feature via sysfs knob */ 111 - fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); 98 + fd = open(wlt_enable_attr, O_RDWR); 112 99 if (fd < 0) { 113 100 perror("Unable to open workload type feature enable file"); 114 101 exit(1); ··· 167 144 ret = sscanf(index_str, "%d", &index); 168 145 if (ret < 0) 169 146 break; 147 + 148 + if (wlt_slow) { 149 + if (index & 0x10) 150 + printf("workload type slow:%s\n", "power"); 151 + else 152 + printf("workload type slow:%s\n", "performance"); 153 + } 170 154 171 155 index &= 0x0f; 172 156 if (index > WORKLOAD_TYPE_MAX_INDEX)