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.6-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull more thermal control updates from Rafael Wysocki:
"These are mostly updates of thermal control drivers for ARM platforms,
new thermal control support for Loongson-2 and a couple of core
cleanups made possible by recent changes merged previously.

Specifics:

- Check if the Tegra BPMP supports the trip points in order to set
the .set_trips callback (Mikko Perttunen)

- Add new Loongson-2 thermal sensor along with the DT bindings (Yinbo
Zhu)

- Use IS_ERR_OR_NULL() helper to replace a double test on the TI
bandgap sensor (Li Zetao)

- Remove redundant platform_set_drvdata() calls, as there are no
corresponding calls to platform_get_drvdata(), from a bunch of
drivers (Andrei Coardos)

- Switch the Mediatek LVTS mode to filtered in order to enable
interrupts (Nícolas F. R. A. Prado)

- Fix Wvoid-pointer-to-enum-cast warning on the Exynos TMU (Krzysztof
Kozlowski)

- Remove redundant dev_err_probe(), because the underlying function
already called it, from the Mediatek sensor (Chen Jiahao)

- Free calibration nvmem after reading it on sun8i (Mark Brown)

- Remove useless comment from the sun8i driver (Yangtao Li)

- Make tsens_xxxx_nvmem static to fix a sparse warning on QCom tsens
(Min-Hua Chen)

- Remove error message at probe deferral on imx8mm (Ahmad Fatoum)

- Fix parameter check in lvts_debugfs_init() with IS_ERR() on
Mediatek LVTS (Minjie Du)

- Fix interrupt routine and configuratoin for Mediatek LVTS (Nícolas
F. R. A. Prado)

- Drop unused .get_trip_type(), .get_trip_temp() and .get_trip_hyst()
thermal zone callbacks from the core and rework the .get_trend()
one to take a trip point pointer as an argument (Rafael Wysocki)"

* tag 'thermal-6.6-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (29 commits)
thermal: core: Rework .get_trend() thermal zone callback
thermal: core: Drop unused .get_trip_*() callbacks
thermal/drivers/tegra-bpmp: Check if BPMP supports trip points
thermal: dt-bindings: add loongson-2 thermal
thermal/drivers/loongson-2: Add thermal management support
thermal/drivers/ti-soc-thermal: Use helper function IS_ERR_OR_NULL()
thermal/drivers/generic-adc: Removed unneeded call to platform_set_drvdata()
thermal/drivers/max77620_thermal: Removed unneeded call to platform_set_drvdata()
thermal/drivers/mediatek/auxadc_thermal: Removed call to platform_set_drvdata()
thermal/drivers/sun8i_thermal: Remove unneeded call to platform_set_drvdata()
thermal/drivers/broadcom/brcstb_thermal: Removed unneeded platform_set_drvdata()
thermal/drivers/mediatek/lvts_thermal: Make readings valid in filtered mode
thermal/drivers/k3_bandgap: Remove unneeded call to platform_set_drvdata()
thermal/drivers/k3_j72xx_bandgap: Removed unneeded call to platform_set_drvdata()
thermal/drivers/broadcom/sr-thermal: Removed call to platform_set_drvdata()
thermal/drivers/samsung: Fix Wvoid-pointer-to-enum-cast warning
thermal/drivers/db8500: Remove redundant of_match_ptr()
thermal/drivers/mediatek: Clean up redundant dev_err_probe()
thermal/drivers/sun8i: Free calibration nvmem after reading it
thermal/drivers/sun8i: Remove unneeded comments
...

+472 -144
+44
Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/thermal/loongson,ls2k-thermal.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Thermal sensors on Loongson-2 SoCs 8 + 9 + maintainers: 10 + - zhanghongchen <zhanghongchen@loongson.cn> 11 + - Yinbo Zhu <zhuyinbo@loongson.cn> 12 + 13 + properties: 14 + compatible: 15 + oneOf: 16 + - enum: 17 + - loongson,ls2k1000-thermal 18 + - items: 19 + - enum: 20 + - loongson,ls2k2000-thermal 21 + - const: loongson,ls2k1000-thermal 22 + 23 + reg: 24 + maxItems: 1 25 + 26 + interrupts: 27 + maxItems: 1 28 + 29 + required: 30 + - compatible 31 + - reg 32 + - interrupts 33 + 34 + additionalProperties: false 35 + 36 + examples: 37 + - | 38 + #include <dt-bindings/interrupt-controller/irq.h> 39 + thermal: thermal-sensor@1fe01500 { 40 + compatible = "loongson,ls2k1000-thermal"; 41 + reg = <0x1fe01500 0x30>; 42 + interrupt-parent = <&liointc0>; 43 + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; 44 + };
+8
MAINTAINERS
··· 12390 12390 F: Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml 12391 12391 F: drivers/pinctrl/pinctrl-loongson2.c 12392 12392 12393 + LOONGSON-2 SOC SERIES THERMAL DRIVER 12394 + M: zhanghongchen <zhanghongchen@loongson.cn> 12395 + M: Yinbo Zhu <zhuyinbo@loongson.cn> 12396 + L: linux-pm@vger.kernel.org 12397 + S: Maintained 12398 + F: Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml 12399 + F: drivers/thermal/loongson2_thermal.c 12400 + 12393 12401 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) 12394 12402 M: Sathya Prakash <sathya.prakash@broadcom.com> 12395 12403 M: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
+18 -23
drivers/acpi/thermal.c
··· 492 492 } 493 493 494 494 static int thermal_get_trend(struct thermal_zone_device *thermal, 495 - int trip_index, enum thermal_trend *trend) 495 + struct thermal_trip *trip, 496 + enum thermal_trend *trend) 496 497 { 497 498 struct acpi_thermal *tz = thermal_zone_device_priv(thermal); 498 499 struct acpi_thermal_trip *acpi_trip; 499 - int t, i; 500 + int t; 500 501 501 - if (!tz || trip_index < 0) 502 + if (!tz || !trip) 502 503 return -EINVAL; 503 504 504 - if (tz->trips.critical.valid) 505 - trip_index--; 506 - 507 - if (tz->trips.hot.valid) 508 - trip_index--; 509 - 510 - if (trip_index < 0) 505 + acpi_trip = trip->priv; 506 + if (!acpi_trip || !acpi_trip->valid) 511 507 return -EINVAL; 512 508 513 - acpi_trip = &tz->trips.passive.trip; 514 - if (acpi_trip->valid && !trip_index--) { 509 + switch (trip->type) { 510 + case THERMAL_TRIP_PASSIVE: 515 511 t = tz->trips.passive.tc1 * (tz->temperature - 516 512 tz->last_temperature) + 517 513 tz->trips.passive.tc2 * (tz->temperature - ··· 520 524 *trend = THERMAL_TREND_STABLE; 521 525 522 526 return 0; 523 - } 524 527 525 - t = acpi_thermal_temp(tz, tz->temperature); 526 - 527 - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 528 - acpi_trip = &tz->trips.active[i].trip; 529 - if (acpi_trip->valid && !trip_index--) { 530 - if (t > acpi_thermal_temp(tz, acpi_trip->temperature)) { 531 - *trend = THERMAL_TREND_RAISING; 532 - return 0; 533 - } 528 + case THERMAL_TRIP_ACTIVE: 529 + t = acpi_thermal_temp(tz, tz->temperature); 530 + if (t <= trip->temperature) 534 531 break; 535 - } 532 + 533 + *trend = THERMAL_TREND_RAISING; 534 + 535 + return 0; 536 + 537 + default: 538 + break; 536 539 } 537 540 538 541 return -EINVAL;
+12
drivers/thermal/Kconfig
··· 510 510 If you say yes here you get support for the FAN controlled 511 511 by the Microcontroller found on the Khadas VIM boards. 512 512 513 + config LOONGSON2_THERMAL 514 + tristate "Loongson-2 SoC series thermal driver" 515 + depends on LOONGARCH || COMPILE_TEST 516 + depends on OF 517 + help 518 + Support for Thermal driver found on Loongson-2 SoC series platforms. 519 + The thermal driver realizes get_temp and set_trips function, which 520 + are used to obtain the temperature of the current node and set the 521 + temperature range to trigger the interrupt. When the input temperature 522 + is higher than the high temperature threshold or lower than the low 523 + temperature threshold, the interrupt will occur. 524 + 513 525 endif
+1
drivers/thermal/Makefile
··· 63 63 obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o 64 64 obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o 65 65 obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL) += khadas_mcu_fan.o 66 + obj-$(CONFIG_LOONGSON2_THERMAL) += loongson2_thermal.o
-1
drivers/thermal/broadcom/brcmstb_thermal.c
··· 334 334 return PTR_ERR(priv->tmon_base); 335 335 336 336 priv->dev = &pdev->dev; 337 - platform_set_drvdata(pdev, priv); 338 337 of_ops = priv->temp_params->of_ops; 339 338 340 339 thermal = devm_thermal_of_zone_register(&pdev->dev, 0, priv,
-1
drivers/thermal/broadcom/sr-thermal.c
··· 91 91 92 92 dev_dbg(dev, "thermal sensor %d registered\n", i); 93 93 } 94 - platform_set_drvdata(pdev, sr_thermal); 95 94 96 95 return 0; 97 96 }
+1 -1
drivers/thermal/db8500_thermal.c
··· 229 229 static struct platform_driver db8500_thermal_driver = { 230 230 .driver = { 231 231 .name = "db8500-thermal", 232 - .of_match_table = of_match_ptr(db8500_thermal_match), 232 + .of_match_table = db8500_thermal_match, 233 233 }, 234 234 .probe = db8500_thermal_probe, 235 235 .suspend = db8500_thermal_suspend,
+2 -4
drivers/thermal/imx8mm_thermal.c
··· 178 178 int ret; 179 179 180 180 ret = nvmem_cell_read_u32(&pdev->dev, "calib", &ana0); 181 - if (ret) { 182 - dev_warn(dev, "Failed to read OCOTP nvmem cell (%d).\n", ret); 183 - return ret; 184 - } 181 + if (ret) 182 + return dev_err_probe(dev, ret, "Failed to read OCOTP nvmem cell\n"); 185 183 186 184 writel(FIELD_PREP(TASR_BUF_VREF_MASK, 187 185 FIELD_GET(ANA0_BUF_VREF_MASK, ana0)) |
-1
drivers/thermal/k3_bandgap.c
··· 225 225 devm_thermal_add_hwmon_sysfs(dev, data[id].tzd); 226 226 } 227 227 228 - platform_set_drvdata(pdev, bgp); 229 228 230 229 return 0; 231 230
-2
drivers/thermal/k3_j72xx_bandgap.c
··· 502 502 writel(K3_VTM_ANYMAXT_OUTRG_ALERT_EN, data[0].bgp->cfg2_base + 503 503 K3_VTM_MISC_CTRL_OFFSET); 504 504 505 - platform_set_drvdata(pdev, bgp); 506 - 507 505 print_look_up_table(dev, ref_table); 508 506 /* 509 507 * Now that the derived_table has the appropriate look up values
+169
drivers/thermal/loongson2_thermal.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Author: zhanghongchen <zhanghongchen@loongson.cn> 4 + * Yinbo Zhu <zhuyinbo@loongson.cn> 5 + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited 6 + */ 7 + 8 + #include <linux/interrupt.h> 9 + #include <linux/io.h> 10 + #include <linux/minmax.h> 11 + #include <linux/module.h> 12 + #include <linux/of_device.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/thermal.h> 15 + #include <linux/units.h> 16 + #include "thermal_hwmon.h" 17 + 18 + #define LOONGSON2_MAX_SENSOR_SEL_NUM 3 19 + 20 + #define LOONGSON2_THSENS_CTRL_HI_REG 0x0 21 + #define LOONGSON2_THSENS_CTRL_LOW_REG 0x8 22 + #define LOONGSON2_THSENS_STATUS_REG 0x10 23 + #define LOONGSON2_THSENS_OUT_REG 0x14 24 + 25 + #define LOONGSON2_THSENS_INT_LO BIT(0) 26 + #define LOONGSON2_THSENS_INT_HIGH BIT(1) 27 + #define LOONGSON2_THSENS_OUT_MASK 0xFF 28 + 29 + struct loongson2_thermal_chip_data { 30 + unsigned int thermal_sensor_sel; 31 + }; 32 + 33 + struct loongson2_thermal_data { 34 + void __iomem *regs; 35 + const struct loongson2_thermal_chip_data *chip_data; 36 + }; 37 + 38 + static int loongson2_thermal_set(struct loongson2_thermal_data *data, 39 + int low, int high, bool enable) 40 + { 41 + u64 reg_ctrl = 0; 42 + int reg_off = data->chip_data->thermal_sensor_sel * 2; 43 + 44 + low = clamp(-40, low, high); 45 + high = clamp(125, low, high); 46 + 47 + low += HECTO; 48 + high += HECTO; 49 + 50 + reg_ctrl = low; 51 + reg_ctrl |= enable ? 0x100 : 0; 52 + writew(reg_ctrl, data->regs + LOONGSON2_THSENS_CTRL_LOW_REG + reg_off); 53 + 54 + reg_ctrl = high; 55 + reg_ctrl |= enable ? 0x100 : 0; 56 + writew(reg_ctrl, data->regs + LOONGSON2_THSENS_CTRL_HI_REG + reg_off); 57 + 58 + return 0; 59 + } 60 + 61 + static int loongson2_thermal_get_temp(struct thermal_zone_device *tz, int *temp) 62 + { 63 + u32 reg_val; 64 + struct loongson2_thermal_data *data = thermal_zone_device_priv(tz); 65 + 66 + reg_val = readl(data->regs + LOONGSON2_THSENS_OUT_REG); 67 + *temp = ((reg_val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; 68 + 69 + return 0; 70 + } 71 + 72 + static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev) 73 + { 74 + struct thermal_zone_device *tzd = dev; 75 + struct loongson2_thermal_data *data = thermal_zone_device_priv(tzd); 76 + 77 + writeb(LOONGSON2_THSENS_INT_LO | LOONGSON2_THSENS_INT_HIGH, data->regs + 78 + LOONGSON2_THSENS_STATUS_REG); 79 + 80 + thermal_zone_device_update(tzd, THERMAL_EVENT_UNSPECIFIED); 81 + 82 + return IRQ_HANDLED; 83 + } 84 + 85 + static int loongson2_thermal_set_trips(struct thermal_zone_device *tz, int low, int high) 86 + { 87 + struct loongson2_thermal_data *data = thermal_zone_device_priv(tz); 88 + 89 + return loongson2_thermal_set(data, low/MILLI, high/MILLI, true); 90 + } 91 + 92 + static const struct thermal_zone_device_ops loongson2_of_thermal_ops = { 93 + .get_temp = loongson2_thermal_get_temp, 94 + .set_trips = loongson2_thermal_set_trips, 95 + }; 96 + 97 + static int loongson2_thermal_probe(struct platform_device *pdev) 98 + { 99 + struct device *dev = &pdev->dev; 100 + struct loongson2_thermal_data *data; 101 + struct thermal_zone_device *tzd; 102 + int ret, irq, i; 103 + 104 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 105 + if (!data) 106 + return -ENOMEM; 107 + 108 + data->chip_data = device_get_match_data(dev); 109 + 110 + data->regs = devm_platform_ioremap_resource(pdev, 0); 111 + if (IS_ERR(data->regs)) 112 + return PTR_ERR(data->regs); 113 + 114 + irq = platform_get_irq(pdev, 0); 115 + if (irq < 0) 116 + return irq; 117 + 118 + writeb(LOONGSON2_THSENS_INT_LO | LOONGSON2_THSENS_INT_HIGH, data->regs + 119 + LOONGSON2_THSENS_STATUS_REG); 120 + 121 + loongson2_thermal_set(data, 0, 0, false); 122 + 123 + for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) { 124 + tzd = devm_thermal_of_zone_register(dev, i, data, 125 + &loongson2_of_thermal_ops); 126 + 127 + if (!IS_ERR(tzd)) 128 + break; 129 + 130 + if (PTR_ERR(tzd) != ENODEV) 131 + continue; 132 + 133 + return dev_err_probe(dev, PTR_ERR(tzd), "failed to register"); 134 + } 135 + 136 + ret = devm_request_threaded_irq(dev, irq, NULL, loongson2_thermal_irq_thread, 137 + IRQF_ONESHOT, "loongson2_thermal", tzd); 138 + if (ret < 0) 139 + return dev_err_probe(dev, ret, "failed to request alarm irq\n"); 140 + 141 + devm_thermal_add_hwmon_sysfs(dev, tzd); 142 + 143 + return 0; 144 + } 145 + 146 + static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = { 147 + .thermal_sensor_sel = 0, 148 + }; 149 + 150 + static const struct of_device_id of_loongson2_thermal_match[] = { 151 + { 152 + .compatible = "loongson,ls2k1000-thermal", 153 + .data = &loongson2_thermal_ls2k1000_data, 154 + }, 155 + { /* end */ } 156 + }; 157 + MODULE_DEVICE_TABLE(of, of_loongson2_thermal_match); 158 + 159 + static struct platform_driver loongson2_thermal_driver = { 160 + .driver = { 161 + .name = "loongson2_thermal", 162 + .of_match_table = of_loongson2_thermal_match, 163 + }, 164 + .probe = loongson2_thermal_probe, 165 + }; 166 + module_platform_driver(loongson2_thermal_driver); 167 + 168 + MODULE_DESCRIPTION("Loongson2 thermal driver"); 169 + MODULE_LICENSE("GPL");
-2
drivers/thermal/max77620_thermal.c
··· 139 139 return ret; 140 140 } 141 141 142 - platform_set_drvdata(pdev, mtherm); 143 - 144 142 return 0; 145 143 } 146 144
-2
drivers/thermal/mediatek/auxadc_thermal.c
··· 1282 1282 mtk_thermal_init_bank(mt, i, apmixed_phys_base, 1283 1283 auxadc_phys_base, ctrl_id); 1284 1284 1285 - platform_set_drvdata(pdev, mt); 1286 - 1287 1285 tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, 1288 1286 &mtk_thermal_ops); 1289 1287 if (IS_ERR(tzdev))
+129 -46
drivers/thermal/mediatek/lvts_thermal.c
··· 58 58 #define LVTS_PROTTC(__base) (__base + 0x00CC) 59 59 #define LVTS_CLKEN(__base) (__base + 0x00E4) 60 60 61 - #define LVTS_PERIOD_UNIT ((118 * 1000) / (256 * 38)) 62 - #define LVTS_GROUP_INTERVAL 1 63 - #define LVTS_FILTER_INTERVAL 1 64 - #define LVTS_SENSOR_INTERVAL 1 65 - #define LVTS_HW_FILTER 0x2 61 + #define LVTS_PERIOD_UNIT 0 62 + #define LVTS_GROUP_INTERVAL 0 63 + #define LVTS_FILTER_INTERVAL 0 64 + #define LVTS_SENSOR_INTERVAL 0 65 + #define LVTS_HW_FILTER 0x0 66 66 #define LVTS_TSSEL_CONF 0x13121110 67 67 #define LVTS_CALSCALE_CONF 0x300 68 - #define LVTS_MONINT_CONF 0x9FBF7BDE 68 + #define LVTS_MONINT_CONF 0x8300318C 69 + 70 + #define LVTS_MONINT_OFFSET_SENSOR0 0xC 71 + #define LVTS_MONINT_OFFSET_SENSOR1 0x180 72 + #define LVTS_MONINT_OFFSET_SENSOR2 0x3000 73 + #define LVTS_MONINT_OFFSET_SENSOR3 0x3000000 69 74 70 75 #define LVTS_INT_SENSOR0 0x0009001F 71 76 #define LVTS_INT_SENSOR1 0x001203E0 ··· 86 81 #define LVTS_MSR_IMMEDIATE_MODE 0 87 82 #define LVTS_MSR_FILTERED_MODE 1 88 83 84 + #define LVTS_MSR_READ_TIMEOUT_US 400 85 + #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) 86 + 89 87 #define LVTS_HW_SHUTDOWN_MT8195 105000 88 + 89 + #define LVTS_MINIMUM_THRESHOLD 20000 90 90 91 91 static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; 92 92 static int coeff_b = LVTS_COEFF_B; ··· 120 110 void __iomem *base; 121 111 int id; 122 112 int dt_id; 113 + int low_thresh; 114 + int high_thresh; 123 115 }; 124 116 125 117 struct lvts_ctrl { ··· 131 119 int num_lvts_sensor; 132 120 int mode; 133 121 void __iomem *base; 122 + int low_thresh; 123 + int high_thresh; 134 124 }; 135 125 136 126 struct lvts_domain { ··· 204 190 int i; 205 191 206 192 lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL); 207 - if (!lvts_td->dom_dentry) 193 + if (IS_ERR(lvts_td->dom_dentry)) 208 194 return 0; 209 195 210 196 for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { ··· 271 257 struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); 272 258 void __iomem *msr = lvts_sensor->msr; 273 259 u32 value; 260 + int rc; 274 261 275 262 /* 276 263 * Measurement registers: ··· 284 269 * 16 : Valid temperature 285 270 * 15-0 : Raw temperature 286 271 */ 287 - value = readl(msr); 272 + rc = readl_poll_timeout(msr, value, value & BIT(16), 273 + LVTS_MSR_READ_WAIT_US, LVTS_MSR_READ_TIMEOUT_US); 288 274 289 275 /* 290 276 * As the thermal zone temperature will read before the ··· 298 282 * functionning temperature and directly jump to a system 299 283 * shutdown. 300 284 */ 301 - if (!(value & BIT(16))) 285 + if (rc) 302 286 return -EAGAIN; 303 287 304 288 *temp = lvts_raw_to_temp(value & 0xFFFF); ··· 306 290 return 0; 307 291 } 308 292 293 + static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl) 294 + { 295 + u32 masks[] = { 296 + LVTS_MONINT_OFFSET_SENSOR0, 297 + LVTS_MONINT_OFFSET_SENSOR1, 298 + LVTS_MONINT_OFFSET_SENSOR2, 299 + LVTS_MONINT_OFFSET_SENSOR3, 300 + }; 301 + u32 value = 0; 302 + int i; 303 + 304 + value = readl(LVTS_MONINT(lvts_ctrl->base)); 305 + 306 + for (i = 0; i < ARRAY_SIZE(masks); i++) { 307 + if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh 308 + && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) 309 + value |= masks[i]; 310 + else 311 + value &= ~masks[i]; 312 + } 313 + 314 + writel(value, LVTS_MONINT(lvts_ctrl->base)); 315 + } 316 + 317 + static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high) 318 + { 319 + int i; 320 + 321 + if (high > lvts_ctrl->high_thresh) 322 + return true; 323 + 324 + for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) 325 + if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh 326 + && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) 327 + return false; 328 + 329 + return true; 330 + } 331 + 309 332 static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) 310 333 { 311 334 struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); 335 + struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]); 312 336 void __iomem *base = lvts_sensor->base; 313 - u32 raw_low = lvts_temp_to_raw(low); 337 + u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD); 314 338 u32 raw_high = lvts_temp_to_raw(high); 339 + bool should_update_thresh; 340 + 341 + lvts_sensor->low_thresh = low; 342 + lvts_sensor->high_thresh = high; 343 + 344 + should_update_thresh = lvts_should_update_thresh(lvts_ctrl, high); 345 + if (should_update_thresh) { 346 + lvts_ctrl->high_thresh = high; 347 + lvts_ctrl->low_thresh = low; 348 + } 349 + lvts_update_irq_mask(lvts_ctrl); 350 + 351 + if (!should_update_thresh) 352 + return 0; 315 353 316 354 /* 317 - * Hot to normal temperature threshold 355 + * Low offset temperature threshold 318 356 * 319 - * LVTS_H2NTHRE 357 + * LVTS_OFFSETL 320 358 * 321 359 * Bits: 322 360 * 323 361 * 14-0 : Raw temperature for threshold 324 362 */ 325 - if (low != -INT_MAX) { 326 - pr_debug("%s: Setting low limit temperature interrupt: %d\n", 327 - thermal_zone_device_type(tz), low); 328 - writel(raw_low, LVTS_H2NTHRE(base)); 329 - } 363 + pr_debug("%s: Setting low limit temperature interrupt: %d\n", 364 + thermal_zone_device_type(tz), low); 365 + writel(raw_low, LVTS_OFFSETL(base)); 330 366 331 367 /* 332 - * Hot temperature threshold 368 + * High offset temperature threshold 333 369 * 334 - * LVTS_HTHRE 370 + * LVTS_OFFSETH 335 371 * 336 372 * Bits: 337 373 * ··· 391 323 */ 392 324 pr_debug("%s: Setting high limit temperature interrupt: %d\n", 393 325 thermal_zone_device_type(tz), high); 394 - writel(raw_high, LVTS_HTHRE(base)); 326 + writel(raw_high, LVTS_OFFSETH(base)); 395 327 396 328 return 0; 397 329 } ··· 519 451 520 452 for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { 521 453 522 - aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl); 454 + aux = lvts_ctrl_irq_handler(&lvts_td->lvts_ctrl[i]); 523 455 if (aux != IRQ_HANDLED) 524 456 continue; 525 457 ··· 589 521 */ 590 522 lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ? 591 523 imm_regs[i] : msr_regs[i]; 524 + 525 + lvts_sensor[i].low_thresh = INT_MIN; 526 + lvts_sensor[i].high_thresh = INT_MIN; 592 527 }; 593 528 594 529 lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor; ··· 759 688 */ 760 689 lvts_ctrl[i].hw_tshut_raw_temp = 761 690 lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); 691 + 692 + lvts_ctrl[i].low_thresh = INT_MIN; 693 + lvts_ctrl[i].high_thresh = INT_MIN; 762 694 } 763 695 764 696 /* ··· 971 897 writel(value, LVTS_MSRCTL0(lvts_ctrl->base)); 972 898 973 899 /* 974 - * LVTS_MSRCTL1 : Measurement control 975 - * 976 - * Bits: 977 - * 978 - * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 979 - * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 980 - * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 981 - * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 982 - * 983 - * That configuration will ignore the filtering and the delays 984 - * introduced below in MONCTL1 and MONCTL2 985 - */ 986 - if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { 987 - value = BIT(9) | BIT(6) | BIT(5) | BIT(4); 988 - writel(value, LVTS_MSRCTL1(lvts_ctrl->base)); 989 - } 990 - 991 - /* 992 900 * LVTS_MONCTL1 : Period unit and group interval configuration 993 901 * 994 902 * The clock source of LVTS thermal controller is 26MHz. ··· 1035 979 struct thermal_zone_device *tz; 1036 980 u32 sensor_map = 0; 1037 981 int i; 982 + /* 983 + * Bitmaps to enable each sensor on immediate and filtered modes, as 984 + * described in MSRCTL1 and MONCTL0 registers below, respectively. 985 + */ 986 + u32 sensor_imm_bitmap[] = { BIT(4), BIT(5), BIT(6), BIT(9) }; 987 + u32 sensor_filt_bitmap[] = { BIT(0), BIT(1), BIT(2), BIT(3) }; 988 + 989 + u32 *sensor_bitmap = lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE ? 990 + sensor_imm_bitmap : sensor_filt_bitmap; 1038 991 1039 992 for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) { 1040 993 ··· 1081 1016 * map, so we can enable the temperature monitoring in 1082 1017 * the hardware thermal controller. 1083 1018 */ 1084 - sensor_map |= BIT(i); 1019 + sensor_map |= sensor_bitmap[i]; 1085 1020 } 1086 1021 1087 1022 /* 1088 - * Bits: 1089 - * 9: Single point access flow 1090 - * 0-3: Enable sensing point 0-3 1091 - * 1092 1023 * The initialization of the thermal zones give us 1093 1024 * which sensor point to enable. If any thermal zone 1094 1025 * was not described in the device tree, it won't be 1095 1026 * enabled here in the sensor map. 1096 1027 */ 1097 - writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); 1028 + if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { 1029 + /* 1030 + * LVTS_MSRCTL1 : Measurement control 1031 + * 1032 + * Bits: 1033 + * 1034 + * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 1035 + * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 1036 + * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 1037 + * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 1038 + * 1039 + * That configuration will ignore the filtering and the delays 1040 + * introduced in MONCTL1 and MONCTL2 1041 + */ 1042 + writel(sensor_map, LVTS_MSRCTL1(lvts_ctrl->base)); 1043 + } else { 1044 + /* 1045 + * Bits: 1046 + * 9: Single point access flow 1047 + * 0-3: Enable sensing point 0-3 1048 + */ 1049 + writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); 1050 + } 1098 1051 1099 1052 return 0; 1100 1053 } ··· 1221 1138 1222 1139 irq = platform_get_irq(pdev, 0); 1223 1140 if (irq < 0) 1224 - return dev_err_probe(dev, irq, "No irq resource\n"); 1141 + return irq; 1225 1142 1226 1143 ret = lvts_domain_init(dev, lvts_td, lvts_data); 1227 1144 if (ret)
+3 -3
drivers/thermal/qcom/tsens-v0_1.c
··· 23 23 24 24 #define BIT_APPEND 0x3 25 25 26 - struct tsens_legacy_calibration_format tsens_8916_nvmem = { 26 + static struct tsens_legacy_calibration_format tsens_8916_nvmem = { 27 27 .base_len = 7, 28 28 .base_shift = 3, 29 29 .sp_len = 5, ··· 39 39 }, 40 40 }; 41 41 42 - struct tsens_legacy_calibration_format tsens_8974_nvmem = { 42 + static struct tsens_legacy_calibration_format tsens_8974_nvmem = { 43 43 .base_len = 8, 44 44 .base_shift = 2, 45 45 .sp_len = 6, ··· 61 61 }, 62 62 }; 63 63 64 - struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = { 64 + static struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = { 65 65 .base_len = 8, 66 66 .base_shift = 2, 67 67 .sp_len = 6,
+1 -1
drivers/thermal/qcom/tsens-v1.c
··· 21 21 #define TM_HIGH_LOW_INT_STATUS_OFF 0x0088 22 22 #define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x0090 23 23 24 - struct tsens_legacy_calibration_format tsens_qcs404_nvmem = { 24 + static struct tsens_legacy_calibration_format tsens_qcs404_nvmem = { 25 25 .base_len = 8, 26 26 .base_shift = 2, 27 27 .sp_len = 6,
+1 -1
drivers/thermal/samsung/exynos_tmu.c
··· 887 887 return -EADDRNOTAVAIL; 888 888 } 889 889 890 - data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev); 890 + data->soc = (uintptr_t)of_device_get_match_data(&pdev->dev); 891 891 892 892 switch (data->soc) { 893 893 case SOC_ARCH_EXYNOS4210:
+3 -5
drivers/thermal/sun8i_thermal.c
··· 56 56 #define SUN50I_H6_THS_PC_TEMP_PERIOD(x) ((GENMASK(19, 0) & (x)) << 12) 57 57 #define SUN50I_H6_THS_DATA_IRQ_STS(x) BIT(x) 58 58 59 - /* millidegree celsius */ 60 - 61 59 struct tsensor { 62 60 struct ths_device *tmdev; 63 61 struct thermal_zone_device *tzd; ··· 284 286 size_t callen; 285 287 int ret = 0; 286 288 287 - calcell = devm_nvmem_cell_get(dev, "calibration"); 289 + calcell = nvmem_cell_get(dev, "calibration"); 288 290 if (IS_ERR(calcell)) { 289 291 if (PTR_ERR(calcell) == -EPROBE_DEFER) 290 292 return -EPROBE_DEFER; ··· 314 316 315 317 kfree(caldata); 316 318 out: 319 + if (!IS_ERR(calcell)) 320 + nvmem_cell_put(calcell); 317 321 return ret; 318 322 } 319 323 ··· 488 488 tmdev->chip = of_device_get_match_data(&pdev->dev); 489 489 if (!tmdev->chip) 490 490 return -EINVAL; 491 - 492 - platform_set_drvdata(pdev, tmdev); 493 491 494 492 ret = sun8i_ths_resource_init(tmdev); 495 493 if (ret)
+51 -1
drivers/thermal/tegra/tegra-bpmp-thermal.c
··· 167 167 return 0; 168 168 } 169 169 170 + static int tegra_bpmp_thermal_trips_supported(struct tegra_bpmp *bpmp, bool *supported) 171 + { 172 + struct mrq_thermal_host_to_bpmp_request req; 173 + union mrq_thermal_bpmp_to_host_response reply; 174 + struct tegra_bpmp_message msg; 175 + int err; 176 + 177 + memset(&req, 0, sizeof(req)); 178 + req.type = CMD_THERMAL_QUERY_ABI; 179 + req.query_abi.type = CMD_THERMAL_SET_TRIP; 180 + 181 + memset(&msg, 0, sizeof(msg)); 182 + msg.mrq = MRQ_THERMAL; 183 + msg.tx.data = &req; 184 + msg.tx.size = sizeof(req); 185 + msg.rx.data = &reply; 186 + msg.rx.size = sizeof(reply); 187 + 188 + err = tegra_bpmp_transfer(bpmp, &msg); 189 + if (err) 190 + return err; 191 + 192 + if (msg.rx.ret == 0) { 193 + *supported = true; 194 + return 0; 195 + } else if (msg.rx.ret == -BPMP_ENODEV) { 196 + *supported = false; 197 + return 0; 198 + } else { 199 + return -EINVAL; 200 + } 201 + } 202 + 170 203 static const struct thermal_zone_device_ops tegra_bpmp_of_thermal_ops = { 171 204 .get_temp = tegra_bpmp_thermal_get_temp, 172 205 .set_trips = tegra_bpmp_thermal_set_trips, 173 206 }; 174 207 208 + static const struct thermal_zone_device_ops tegra_bpmp_of_thermal_ops_notrips = { 209 + .get_temp = tegra_bpmp_thermal_get_temp, 210 + }; 211 + 175 212 static int tegra_bpmp_thermal_probe(struct platform_device *pdev) 176 213 { 177 214 struct tegra_bpmp *bpmp = dev_get_drvdata(pdev->dev.parent); 215 + const struct thermal_zone_device_ops *thermal_ops; 178 216 struct tegra_bpmp_thermal *tegra; 179 217 struct thermal_zone_device *tzd; 180 218 unsigned int i, max_num_zones; 219 + bool supported; 181 220 int err; 221 + 222 + err = tegra_bpmp_thermal_trips_supported(bpmp, &supported); 223 + if (err) { 224 + dev_err(&pdev->dev, "failed to determine if trip points are supported\n"); 225 + return err; 226 + } 227 + 228 + if (supported) 229 + thermal_ops = &tegra_bpmp_of_thermal_ops; 230 + else 231 + thermal_ops = &tegra_bpmp_of_thermal_ops_notrips; 182 232 183 233 tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); 184 234 if (!tegra) ··· 272 222 } 273 223 274 224 tzd = devm_thermal_of_zone_register( 275 - &pdev->dev, i, zone, &tegra_bpmp_of_thermal_ops); 225 + &pdev->dev, i, zone, thermal_ops); 276 226 if (IS_ERR(tzd)) { 277 227 if (PTR_ERR(tzd) == -EPROBE_DEFER) 278 228 return -EPROBE_DEFER;
-1
drivers/thermal/thermal-generic-adc.c
··· 142 142 return ret; 143 143 144 144 gti->dev = &pdev->dev; 145 - platform_set_drvdata(pdev, gti); 146 145 147 146 gti->tz_dev = devm_thermal_of_zone_register(&pdev->dev, 0, gti, 148 147 &gadc_thermal_ops);
+1 -1
drivers/thermal/thermal_core.c
··· 1266 1266 return ERR_PTR(-EINVAL); 1267 1267 } 1268 1268 1269 - if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp) && !trips) 1269 + if (num_trips > 0 && !trips) 1270 1270 return ERR_PTR(-EINVAL); 1271 1271 1272 1272 if (!thermal_class)
+1 -1
drivers/thermal/thermal_core.h
··· 70 70 void thermal_cdev_update(struct thermal_cooling_device *); 71 71 void __thermal_cdev_update(struct thermal_cooling_device *cdev); 72 72 73 - int get_tz_trend(struct thermal_zone_device *tz, int trip); 73 + int get_tz_trend(struct thermal_zone_device *tz, int trip_index); 74 74 75 75 struct thermal_instance * 76 76 get_thermal_instance(struct thermal_zone_device *tz,
+2 -1
drivers/thermal/thermal_helpers.c
··· 22 22 #include "thermal_core.h" 23 23 #include "thermal_trace.h" 24 24 25 - int get_tz_trend(struct thermal_zone_device *tz, int trip) 25 + int get_tz_trend(struct thermal_zone_device *tz, int trip_index) 26 26 { 27 + struct thermal_trip *trip = tz->trips ? &tz->trips[trip_index] : NULL; 27 28 enum thermal_trend trend; 28 29 29 30 if (tz->emul_temperature || !tz->ops->get_trend ||
+3 -21
drivers/thermal/thermal_trip.c
··· 101 101 int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, 102 102 struct thermal_trip *trip) 103 103 { 104 - int ret; 105 - 106 - if (!tz || trip_id < 0 || trip_id >= tz->num_trips || !trip) 104 + if (!tz || !tz->trips || trip_id < 0 || trip_id >= tz->num_trips || !trip) 107 105 return -EINVAL; 108 106 109 - if (tz->trips) { 110 - *trip = tz->trips[trip_id]; 111 - return 0; 112 - } 113 - 114 - if (tz->ops->get_trip_hyst) { 115 - ret = tz->ops->get_trip_hyst(tz, trip_id, &trip->hysteresis); 116 - if (ret) 117 - return ret; 118 - } else { 119 - trip->hysteresis = 0; 120 - } 121 - 122 - ret = tz->ops->get_trip_temp(tz, trip_id, &trip->temperature); 123 - if (ret) 124 - return ret; 125 - 126 - return tz->ops->get_trip_type(tz, trip_id, &trip->type); 107 + *trip = tz->trips[trip_id]; 108 + return 0; 127 109 } 128 110 EXPORT_SYMBOL_GPL(__thermal_zone_get_trip); 129 111
+1 -1
drivers/thermal/ti-soc-thermal/ti-bandgap.c
··· 314 314 */ 315 315 static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id) 316 316 { 317 - if (!bgp || IS_ERR(bgp)) { 317 + if (IS_ERR_OR_NULL(bgp)) { 318 318 pr_err("%s: invalid bandgap pointer\n", __func__); 319 319 return -EINVAL; 320 320 }
+2 -1
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
··· 109 109 return ret; 110 110 } 111 111 112 - static int __ti_thermal_get_trend(struct thermal_zone_device *tz, int trip, enum thermal_trend *trend) 112 + static int __ti_thermal_get_trend(struct thermal_zone_device *tz, 113 + struct thermal_trip *trip, enum thermal_trend *trend) 113 114 { 114 115 struct ti_thermal_data *data = thermal_zone_device_priv(tz); 115 116 struct ti_bandgap *bgp;
+19 -23
include/linux/thermal.h
··· 53 53 THERMAL_EVENT_KEEP_ALIVE, /* Request for user space handler to respond */ 54 54 }; 55 55 56 - struct thermal_zone_device_ops { 57 - int (*bind) (struct thermal_zone_device *, 58 - struct thermal_cooling_device *); 59 - int (*unbind) (struct thermal_zone_device *, 60 - struct thermal_cooling_device *); 61 - int (*get_temp) (struct thermal_zone_device *, int *); 62 - int (*set_trips) (struct thermal_zone_device *, int, int); 63 - int (*change_mode) (struct thermal_zone_device *, 64 - enum thermal_device_mode); 65 - int (*get_trip_type) (struct thermal_zone_device *, int, 66 - enum thermal_trip_type *); 67 - int (*get_trip_temp) (struct thermal_zone_device *, int, int *); 68 - int (*set_trip_temp) (struct thermal_zone_device *, int, int); 69 - int (*get_trip_hyst) (struct thermal_zone_device *, int, int *); 70 - int (*set_trip_hyst) (struct thermal_zone_device *, int, int); 71 - int (*get_crit_temp) (struct thermal_zone_device *, int *); 72 - int (*set_emul_temp) (struct thermal_zone_device *, int); 73 - int (*get_trend) (struct thermal_zone_device *, int, 74 - enum thermal_trend *); 75 - void (*hot)(struct thermal_zone_device *); 76 - void (*critical)(struct thermal_zone_device *); 77 - }; 78 - 79 56 /** 80 57 * struct thermal_trip - representation of a point in temperature domain 81 58 * @temperature: temperature value in miliCelsius ··· 65 88 int hysteresis; 66 89 enum thermal_trip_type type; 67 90 void *priv; 91 + }; 92 + 93 + struct thermal_zone_device_ops { 94 + int (*bind) (struct thermal_zone_device *, 95 + struct thermal_cooling_device *); 96 + int (*unbind) (struct thermal_zone_device *, 97 + struct thermal_cooling_device *); 98 + int (*get_temp) (struct thermal_zone_device *, int *); 99 + int (*set_trips) (struct thermal_zone_device *, int, int); 100 + int (*change_mode) (struct thermal_zone_device *, 101 + enum thermal_device_mode); 102 + int (*set_trip_temp) (struct thermal_zone_device *, int, int); 103 + int (*set_trip_hyst) (struct thermal_zone_device *, int, int); 104 + int (*get_crit_temp) (struct thermal_zone_device *, int *); 105 + int (*set_emul_temp) (struct thermal_zone_device *, int); 106 + int (*get_trend) (struct thermal_zone_device *, struct thermal_trip *, 107 + enum thermal_trend *); 108 + void (*hot)(struct thermal_zone_device *); 109 + void (*critical)(struct thermal_zone_device *); 68 110 }; 69 111 70 112 struct thermal_cooling_device_ops {