From 16bee043fc0a6eb6e9d5306f8e9366a3dcee1fea Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 6 May 2021 14:55:14 -0300 Subject: thermal/drivers/rockchip: Support RK3568 SoCs in the thermal driver The RK3568 SoCs have two Temperature Sensors, channel 0 is for CPU, channel 1 is for GPU. Signed-off-by: Finley Xiao Signed-off-by: Ezequiel Garcia Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210506175514.168365-5-ezequiel@collabora.com --- drivers/thermal/rockchip_thermal.c | 121 +++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index aa9e0e31ef98..657d84b9963e 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -211,7 +211,11 @@ struct rockchip_thermal_data { #define TSADCV3_AUTO_PERIOD_TIME 1875 /* 2.5ms */ #define TSADCV3_AUTO_PERIOD_HT_TIME 1875 /* 2.5ms */ +#define TSADCV5_AUTO_PERIOD_TIME 1622 /* 2.5ms */ +#define TSADCV5_AUTO_PERIOD_HT_TIME 1622 /* 2.5ms */ + #define TSADCV2_USER_INTER_PD_SOC 0x340 /* 13 clocks */ +#define TSADCV5_USER_INTER_PD_SOC 0xfc0 /* 97us, at least 90us */ #define GRF_SARADC_TESTBIT 0x0e644 #define GRF_TSADC_TESTBIT_L 0x0e648 @@ -219,6 +223,12 @@ struct rockchip_thermal_data { #define PX30_GRF_SOC_CON2 0x0408 +#define RK3568_GRF_TSADC_CON 0x0600 +#define RK3568_GRF_TSADC_ANA_REG0 (0x10001 << 0) +#define RK3568_GRF_TSADC_ANA_REG1 (0x10001 << 1) +#define RK3568_GRF_TSADC_ANA_REG2 (0x10001 << 2) +#define RK3568_GRF_TSADC_TSEN (0x10001 << 8) + #define GRF_SARADC_TESTBIT_ON (0x10001 << 2) #define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2) #define GRF_TSADC_VCM_EN_L (0x10001 << 7) @@ -474,6 +484,45 @@ static const struct tsadc_table rk3399_code_table[] = { {TSADCV3_DATA_MASK, 125000}, }; +static const struct tsadc_table rk3568_code_table[] = { + {0, -40000}, + {1584, -40000}, + {1620, -35000}, + {1652, -30000}, + {1688, -25000}, + {1720, -20000}, + {1756, -15000}, + {1788, -10000}, + {1824, -5000}, + {1856, 0}, + {1892, 5000}, + {1924, 10000}, + {1956, 15000}, + {1992, 20000}, + {2024, 25000}, + {2060, 30000}, + {2092, 35000}, + {2128, 40000}, + {2160, 45000}, + {2196, 50000}, + {2228, 55000}, + {2264, 60000}, + {2300, 65000}, + {2332, 70000}, + {2368, 75000}, + {2400, 80000}, + {2436, 85000}, + {2468, 90000}, + {2500, 95000}, + {2536, 100000}, + {2572, 105000}, + {2604, 110000}, + {2636, 115000}, + {2672, 120000}, + {2704, 125000}, + {TSADCV2_DATA_MASK, 125000}, +}; + static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table, int temp) { @@ -701,6 +750,49 @@ static void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs, regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV); } +static void rk_tsadcv7_initialize(struct regmap *grf, void __iomem *regs, + enum tshut_polarity tshut_polarity) +{ + writel_relaxed(TSADCV5_USER_INTER_PD_SOC, regs + TSADCV2_USER_CON); + writel_relaxed(TSADCV5_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD); + writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, + regs + TSADCV2_HIGHT_INT_DEBOUNCE); + writel_relaxed(TSADCV5_AUTO_PERIOD_HT_TIME, + regs + TSADCV2_AUTO_PERIOD_HT); + writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, + regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); + + if (tshut_polarity == TSHUT_HIGH_ACTIVE) + writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH, + regs + TSADCV2_AUTO_CON); + else + writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, + regs + TSADCV2_AUTO_CON); + + /* + * The general register file will is optional + * and might not be available. + */ + if (!IS_ERR(grf)) { + regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_TSEN); + /* + * RK3568 TRM, section 18.5. requires a delay no less + * than 10us between the rising edge of tsadc_tsen_en + * and the rising edge of tsadc_ana_reg_0/1/2. + */ + udelay(15); + regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG0); + regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG1); + regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG2); + + /* + * RK3568 TRM, section 18.5. requires a delay no less + * than 90us after the rising edge of tsadc_ana_reg_0/1/2. + */ + usleep_range(100, 200); + } +} + static void rk_tsadcv2_irq_ack(void __iomem *regs) { u32 val; @@ -1027,6 +1119,31 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = { }, }; +static const struct rockchip_tsadc_chip rk3568_tsadc_data = { + .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ + .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */ + .chn_num = 2, /* two channels for tsadc */ + + .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ + .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ + .tshut_temp = 95000, + + .initialize = rk_tsadcv7_initialize, + .irq_ack = rk_tsadcv3_irq_ack, + .control = rk_tsadcv3_control, + .get_temp = rk_tsadcv2_get_temp, + .set_alarm_temp = rk_tsadcv2_alarm_temp, + .set_tshut_temp = rk_tsadcv2_tshut_temp, + .set_tshut_mode = rk_tsadcv2_tshut_mode, + + .table = { + .id = rk3568_code_table, + .length = ARRAY_SIZE(rk3568_code_table), + .data_mask = TSADCV2_DATA_MASK, + .mode = ADC_INCREMENT, + }, +}; + static const struct of_device_id of_rockchip_thermal_match[] = { { .compatible = "rockchip,px30-tsadc", .data = (void *)&px30_tsadc_data, @@ -1059,6 +1176,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = { .compatible = "rockchip,rk3399-tsadc", .data = (void *)&rk3399_tsadc_data, }, + { + .compatible = "rockchip,rk3568-tsadc", + .data = (void *)&rk3568_tsadc_data, + }, { /* end */ }, }; MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match); -- cgit v1.2.3-70-g09d2 From 4d57fd9aeaa013a245bf1fade81e2c30a5efd491 Mon Sep 17 00:00:00 2001 From: Chunyan Zhang Date: Wed, 12 May 2021 17:37:52 +0800 Subject: thermal/drivers/sprd: Add missing MODULE_DEVICE_TABLE MODULE_DEVICE_TABLE is used to extract the device information out of the driver and builds a table when being compiled. If using this macro, kernel can find the driver if available when the device is plugged in, and then loads that driver and initializes the device. Fixes: 554fdbaf19b18 ("thermal: sprd: Add Spreadtrum thermal driver support") Signed-off-by: Chunyan Zhang Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210512093752.243168-1-zhang.lyra@gmail.com --- drivers/thermal/sprd_thermal.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c index 3682edb2f466..fe06cccf14b3 100644 --- a/drivers/thermal/sprd_thermal.c +++ b/drivers/thermal/sprd_thermal.c @@ -532,6 +532,7 @@ static const struct of_device_id sprd_thermal_of_match[] = { { .compatible = "sprd,ums512-thermal", .data = &ums512_data }, { }, }; +MODULE_DEVICE_TABLE(of, sprd_thermal_of_match); static const struct dev_pm_ops sprd_thermal_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(sprd_thm_suspend, sprd_thm_resume) -- cgit v1.2.3-70-g09d2 From fb5a6ec80367bcccb659a421850d757a5a81767a Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Sun, 16 May 2021 23:14:40 -0700 Subject: thermal/drivers/int340x: processor_thermal: Export mailbox interface Export the mailbox interface to be used by other modules. Also change command id and response from u8 to u32 data type. Signed-off-by: Srinivas Pandruvada Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210517061441.1921901-2-srinivas.pandruvada@linux.intel.com --- .../thermal/intel/int340x_thermal/processor_thermal_device.h | 2 ++ .../thermal/intel/int340x_thermal/processor_thermal_mbox.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index b9ed64561aaf..3161607424f5 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -79,4 +79,6 @@ void proc_thermal_rfim_remove(struct pci_dev *pdev); int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_mbox_remove(struct pci_dev *pdev); +int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp); + #endif diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c index 990f51f22884..59e93b04f0a9 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c @@ -23,7 +23,7 @@ static DEFINE_MUTEX(mbox_lock); -static int send_mbox_cmd(struct pci_dev *pdev, u8 cmd_id, u32 cmd_data, u8 *cmd_resp) +static int send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp) { struct proc_thermal_device *proc_priv; u32 retries, data; @@ -82,6 +82,12 @@ unlock_mbox: return ret; } +int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp) +{ + return send_mbox_cmd(pdev, cmd_id, cmd_data, cmd_resp); +} +EXPORT_SYMBOL_GPL(processor_thermal_send_mbox_cmd); + /* List of workload types */ static const char * const workload_types[] = { "none", @@ -147,7 +153,7 @@ static ssize_t workload_type_show(struct device *dev, char *buf) { struct pci_dev *pdev = to_pci_dev(dev); - u8 cmd_resp; + u32 cmd_resp; int ret; ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, 0, &cmd_resp); @@ -181,7 +187,7 @@ static bool workload_req_created; int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) { - u8 cmd_resp; + u32 cmd_resp; int ret; /* Check if there is a mailbox support, if fails return success */ -- cgit v1.2.3-70-g09d2 From 5d6fbc96bd36cfec7bbc0578ad3986affdeb70de Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Sun, 16 May 2021 23:14:41 -0700 Subject: thermal/drivers/int340x: processor_thermal: Export additional attributes Export additional attributes: ddr_data_rate (RO) : Show current DDR (Double Data Rate) data rate. rfi_restriction (RW) : Show or set current state for RFI (Radio Frequency Interference) protection. These attributes use mailbox commands to get/set information. Here command codes are: 0x0007: Read RFI restriction 0x0107: Read DDR data rate 0x0008: Write RFI restriction Signed-off-by: Srinivas Pandruvada Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210517061441.1921901-3-srinivas.pandruvada@linux.intel.com --- .../intel/int340x_thermal/processor_thermal_rfim.c | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c index aef993a813e2..2b8a3235d518 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c @@ -190,6 +190,59 @@ static DEVICE_ATTR_RO(ddr_data_rate_point_2); static DEVICE_ATTR_RO(ddr_data_rate_point_3); static DEVICE_ATTR_RW(rfi_disable); +static ssize_t rfi_restriction_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u16 cmd_id = 0x0008; + u32 cmd_resp; + u32 input; + int ret; + + ret = kstrtou32(buf, 10, &input); + if (ret) + return ret; + + ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, input, &cmd_resp); + if (ret) + return ret; + + return count; +} + +static ssize_t rfi_restriction_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + u16 cmd_id = 0x0007; + u32 cmd_resp; + int ret; + + ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, 0, &cmd_resp); + if (ret) + return ret; + + return sprintf(buf, "%u\n", cmd_resp); +} + +static ssize_t ddr_data_rate_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + u16 cmd_id = 0x0107; + u32 cmd_resp; + int ret; + + ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, 0, &cmd_resp); + if (ret) + return ret; + + return sprintf(buf, "%u\n", cmd_resp); +} + +static DEVICE_ATTR_RW(rfi_restriction); +static DEVICE_ATTR_RO(ddr_data_rate); + static struct attribute *dvfs_attrs[] = { &dev_attr_rfi_restriction_run_busy.attr, &dev_attr_rfi_restriction_err_code.attr, @@ -199,6 +252,8 @@ static struct attribute *dvfs_attrs[] = { &dev_attr_ddr_data_rate_point_2.attr, &dev_attr_ddr_data_rate_point_3.attr, &dev_attr_rfi_disable.attr, + &dev_attr_ddr_data_rate.attr, + &dev_attr_rfi_restriction.attr, NULL }; -- cgit v1.2.3-70-g09d2 From a052b5118f13febac1bd901fe0b7a807b9d6b51c Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 17 May 2021 13:10:20 +0800 Subject: thermal/core: Correct function name thermal_zone_device_unregister() Fix the following make W=1 kernel build warning: drivers/thermal/thermal_core.c:1376: warning: expecting prototype for thermal_device_unregister(). Prototype was for thermal_zone_device_unregister() instead Signed-off-by: Yang Yingliang Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210517051020.3463536-1-yangyingliang@huawei.com --- drivers/thermal/thermal_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d20b25f40d19..142dcf5e4a18 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1369,7 +1369,7 @@ free_tz: EXPORT_SYMBOL_GPL(thermal_zone_device_register); /** - * thermal_device_unregister - removes the registered thermal zone device + * thermal_zone_device_unregister - removes the registered thermal zone device * @tz: the thermal zone device to remove */ void thermal_zone_device_unregister(struct thermal_zone_device *tz) -- cgit v1.2.3-70-g09d2 From d7539260cd9ad9c18eaf2a1ff71401abdbdfb5cb Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Sat, 5 Jun 2021 20:02:05 +0800 Subject: thermal/drivers/st: Use devm_platform_get_and_ioremap_resource() Use devm_platform_get_and_ioremap_resource() to simplify code and remove error message which within devm_platform_get_and_ioremap_resource() already. Signed-off-by: Yang Yingliang Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210605120205.2459578-1-yangyingliang@huawei.com --- drivers/thermal/st/st_thermal_memmap.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/st/st_thermal_memmap.c b/drivers/thermal/st/st_thermal_memmap.c index a0114452d11f..d68596c40be9 100644 --- a/drivers/thermal/st/st_thermal_memmap.c +++ b/drivers/thermal/st/st_thermal_memmap.c @@ -119,19 +119,10 @@ static int st_mmap_regmap_init(struct st_thermal_sensor *sensor) { struct device *dev = sensor->dev; struct platform_device *pdev = to_platform_device(dev); - struct resource *res; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "no memory resources defined\n"); - return -ENODEV; - } - - sensor->mmio_base = devm_ioremap_resource(dev, res); - if (IS_ERR(sensor->mmio_base)) { - dev_err(dev, "failed to remap IO\n"); + sensor->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(sensor->mmio_base)) return PTR_ERR(sensor->mmio_base); - } sensor->regmap = devm_regmap_init_mmio(dev, sensor->mmio_base, &st_416mpe_regmap_config); -- cgit v1.2.3-70-g09d2 From 8946187ab57ffd02088e50256c73dd31f49db06d Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Sat, 5 Jun 2021 10:52:11 +0200 Subject: thermal/drivers/rcar_gen3_thermal: Fix coefficient calculations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fixed value of 157 used in the calculations are only correct for M3-W, on other Gen3 SoC it should be 167. The constant can be derived correctly from the static TJ_3 constant and the SoC specific TJ_1 value. Update the calculation be correct on all Gen3 SoCs. Fixes: 4eb39f79ef44 ("thermal: rcar_gen3_thermal: Update value of Tj_1") Reported-by: Yoshihiro Shimoda Signed-off-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Reviewed-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210605085211.564909-1-niklas.soderlund+renesas@ragnatech.se --- drivers/thermal/rcar_gen3_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index e1e412348076..1a60adb1d30a 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -143,7 +143,7 @@ static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_tsc *tsc, * Division is not scaled in BSP and if scaled it might overflow * the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled */ - tsc->tj_t = (FIXPT_INT((ptat[1] - ptat[2]) * 157) + tsc->tj_t = (FIXPT_INT((ptat[1] - ptat[2]) * (ths_tj_1 - TJ_3)) / (ptat[0] - ptat[2])) + FIXPT_INT(TJ_3); tsc->coef.a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]), -- cgit v1.2.3-70-g09d2 From 3ae5950db617d1cc3eb4eb55750fa9d138529b49 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 7 Jun 2021 16:41:20 +0200 Subject: thermal/drivers/rcar_gen3_thermal: Do not shadow rcar_gen3_ths_tj_1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With -Wshadow: drivers/thermal/rcar_gen3_thermal.c: In function ‘rcar_gen3_thermal_probe’: drivers/thermal/rcar_gen3_thermal.c:310:13: warning: declaration of ‘rcar_gen3_ths_tj_1’ shadows a global declaration [-Wshadow] 310 | const int *rcar_gen3_ths_tj_1 = of_device_get_match_data(dev); | ^~~~~~~~~~~~~~~~~~ drivers/thermal/rcar_gen3_thermal.c:246:18: note: shadowed declaration is here 246 | static const int rcar_gen3_ths_tj_1 = 126; | ^~~~~~~~~~~~~~~~~~ To add to the confusion, the local variable has a different type. Fix the shadowing by renaming the local variable to ths_tj_1. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/9ea7e65d0331daba96f9a7925cb3d12d2170efb1.1623076804.git.geert+renesas@glider.be --- drivers/thermal/rcar_gen3_thermal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 1a60adb1d30a..fdf16aa34eb4 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -307,7 +307,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) { struct rcar_gen3_thermal_priv *priv; struct device *dev = &pdev->dev; - const int *rcar_gen3_ths_tj_1 = of_device_get_match_data(dev); + const int *ths_tj_1 = of_device_get_match_data(dev); struct resource *res; struct thermal_zone_device *zone; int ret, i; @@ -352,8 +352,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) priv->tscs[i] = tsc; priv->thermal_init(tsc); - rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i], - *rcar_gen3_ths_tj_1); + rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i], *ths_tj_1); zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, &rcar_gen3_tz_of_ops); -- cgit v1.2.3-70-g09d2 From 3da97620e8d60da4a7eaae46e03e0a494780642d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Jun 2021 21:22:29 +0200 Subject: thermal/drivers/imx_sc: Add missing of_node_put for loop iteration Early exits from for_each_available_child_of_node() should decrement the node reference counter. Reported by Coccinelle: drivers/thermal/imx_sc_thermal.c:93:1-33: WARNING: Function "for_each_available_child_of_node" should have of_node_put() before return around line 97. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Jacky Bai Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210614192230.19248-1-krzysztof.kozlowski@canonical.com --- drivers/thermal/imx_sc_thermal.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/imx_sc_thermal.c b/drivers/thermal/imx_sc_thermal.c index b01d28eca7ee..8d76dbfde6a9 100644 --- a/drivers/thermal/imx_sc_thermal.c +++ b/drivers/thermal/imx_sc_thermal.c @@ -93,6 +93,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev) for_each_available_child_of_node(np, child) { sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL); if (!sensor) { + of_node_put(child); of_node_put(sensor_np); return -ENOMEM; } @@ -104,6 +105,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get valid sensor resource id: %d\n", ret); + of_node_put(child); break; } @@ -114,6 +116,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev) if (IS_ERR(sensor->tzd)) { dev_err(&pdev->dev, "failed to register thermal zone\n"); ret = PTR_ERR(sensor->tzd); + of_node_put(child); break; } -- cgit v1.2.3-70-g09d2 From d8ac5bb4ae653e092d7429a7587b73f1662d6ad7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Jun 2021 21:22:30 +0200 Subject: thermal/drivers/sprd: Add missing of_node_put for loop iteration Early exits from for_each_available_child_of_node() should decrement the node reference counter. Reported by Coccinelle: drivers/thermal/sprd_thermal.c:387:1-23: WARNING: Function "for_each_child_of_node" should have of_node_put() before goto around lines 391. Signed-off-by: Krzysztof Kozlowski Acked-by: Chunyan Zhang Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210614192230.19248-2-krzysztof.kozlowski@canonical.com --- drivers/thermal/sprd_thermal.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c index fe06cccf14b3..fff80fc18002 100644 --- a/drivers/thermal/sprd_thermal.c +++ b/drivers/thermal/sprd_thermal.c @@ -388,7 +388,7 @@ static int sprd_thm_probe(struct platform_device *pdev) sen = devm_kzalloc(&pdev->dev, sizeof(*sen), GFP_KERNEL); if (!sen) { ret = -ENOMEM; - goto disable_clk; + goto of_put; } sen->data = thm; @@ -397,13 +397,13 @@ static int sprd_thm_probe(struct platform_device *pdev) ret = of_property_read_u32(sen_child, "reg", &sen->id); if (ret) { dev_err(&pdev->dev, "get sensor reg failed"); - goto disable_clk; + goto of_put; } ret = sprd_thm_sensor_calibration(sen_child, thm, sen); if (ret) { dev_err(&pdev->dev, "efuse cal analysis failed"); - goto disable_clk; + goto of_put; } sprd_thm_sensor_init(thm, sen); @@ -416,19 +416,20 @@ static int sprd_thm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "register thermal zone failed %d\n", sen->id); ret = PTR_ERR(sen->tzd); - goto disable_clk; + goto of_put; } thm->sensor[sen->id] = sen; } + /* sen_child set to NULL at this point */ ret = sprd_thm_set_ready(thm); if (ret) - goto disable_clk; + goto of_put; ret = sprd_thm_wait_temp_ready(thm); if (ret) - goto disable_clk; + goto of_put; for (i = 0; i < thm->nr_sensors; i++) sprd_thm_toggle_sensor(thm->sensor[i], true); @@ -436,6 +437,8 @@ static int sprd_thm_probe(struct platform_device *pdev) platform_set_drvdata(pdev, thm); return 0; +of_put: + of_node_put(sen_child); disable_clk: clk_disable_unprepare(thm->clk); return ret; -- cgit v1.2.3-70-g09d2 From 5e5c9f9a75fc4532980c2e699caf8a36070a3a2e Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 16 Jun 2021 22:04:13 +0300 Subject: thermal/core/thermal_of: Stop zone device before unregistering it Zone device is enabled after thermal_zone_of_sensor_register() completion, but it's not disabled before senor is unregistered, leaving temperature polling active. This results in accessing a disabled zone device and produces a warning about this problem. Stop zone device before unregistering it in order to fix this "use-after-free" problem. Signed-off-by: Dmitry Osipenko Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210616190417.32214-3-digetx@gmail.com --- drivers/thermal/thermal_of.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 5b76f9a1280d..6379f26a335f 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -559,6 +559,9 @@ void thermal_zone_of_sensor_unregister(struct device *dev, if (!tz) return; + /* stop temperature polling */ + thermal_zone_device_disable(tzd); + mutex_lock(&tzd->lock); tzd->ops->get_temp = NULL; tzd->ops->get_trend = NULL; -- cgit v1.2.3-70-g09d2 From da5e562fbc5676902d9007db4b05af9de7a890d5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Jun 2021 18:34:51 +0300 Subject: thermal/drivers/intel/intel_soc_dts_iosf: Switch to use find_first_zero_bit() Switch to use find_first_zero_bit() instead of open-coded variant. Signed-off-by: Andy Shevchenko Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210618153451.89246-1-andriy.shevchenko@linux.intel.com --- drivers/thermal/intel/intel_soc_dts_iosf.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c index 4f1a2f7c016c..342b0bb5a56d 100644 --- a/drivers/thermal/intel/intel_soc_dts_iosf.c +++ b/drivers/thermal/intel/intel_soc_dts_iosf.c @@ -350,13 +350,14 @@ int intel_soc_dts_iosf_add_read_only_critical_trip( int i, j; for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { - for (j = 0; j < sensors->soc_dts[i].trip_count; ++j) { - if (!(sensors->soc_dts[i].trip_mask & BIT(j))) { - return update_trip_temp(&sensors->soc_dts[i], j, - sensors->tj_max - critical_offset, - THERMAL_TRIP_CRITICAL); - } - } + struct intel_soc_dts_sensor_entry *entry = &sensors->soc_dts[i]; + int temp = sensors->tj_max - critical_offset; + unsigned long count = entry->trip_count; + unsigned long mask = entry->trip_mask; + + j = find_first_zero_bit(&mask, count); + if (j < count) + return update_trip_temp(entry, j, temp, THERMAL_TRIP_CRITICAL); } return -EINVAL; -- cgit v1.2.3-70-g09d2 From 8b2ea897328c3e042ef7c3e80503c802db24a678 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 9 Jun 2021 15:22:30 +0800 Subject: thermal: devfreq_cooling: Fix kernel-doc Fix function name in devfreq_cooling.c comment to remove a warning found by kernel-doc. drivers/thermal/devfreq_cooling.c:479: warning: expecting prototype for devfreq_cooling_em_register_power(). Prototype was for devfreq_cooling_em_register() instead. Reported-by: Abaci Robot Signed-off-by: Yang Li Reviewed-by: Nick Desaulniers Reviewed-by: Nathan Chancellor Reviewed-by: Lukasz Luba Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/1623223350-128104-1-git-send-email-yang.lee@linux.alibaba.com --- drivers/thermal/devfreq_cooling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c index 3a788ac4f525..5a86cffd78f6 100644 --- a/drivers/thermal/devfreq_cooling.c +++ b/drivers/thermal/devfreq_cooling.c @@ -458,7 +458,7 @@ struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df) EXPORT_SYMBOL_GPL(devfreq_cooling_register); /** - * devfreq_cooling_em_register_power() - Register devfreq cooling device with + * devfreq_cooling_em_register() - Register devfreq cooling device with * power information and automatically register Energy Model (EM) * @df: Pointer to devfreq device. * @dfc_power: Pointer to devfreq_cooling_power. -- cgit v1.2.3-70-g09d2 From 8fe145f7ceda7b8909cd471e1e75dd20dfbf41a5 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Tue, 25 May 2021 13:48:10 -0700 Subject: thermal/drivers/int340x/processor_thermal: Split enumeration and processing part Remove enumeration part from the processor_thermal_device to two different modules. One for ACPI and one for PCI: ACPI enumeration: int3401_thermal PCI part: processor_thermal_device_pci_legacy The current processor_thermal_device now just implements interface functions to be used by the ACPI and PCI enumeration module. This is done by: 1. Make functions proc_thermal_add() and proc_thermal_remove() non static and export them for usage in other processor_thermal_device_pci_legacy.c and in int3401_thermal.c. 2. Move the sysfs file creation for TCC offset and power limit attribute group to the proc_thermal_add() from the individual enumeration callbacks for PCI and ACPI. 3. Create new interface functions proc_thermal_mmio_add() and proc_thermal_mmio_remove() which will be called from the processor_thermal_device_pci_legacy module. 4. Export proc_thermal_resume(), so that it can be used by power management callbacks. 5. Remove special check for double enumeration as it never happens. While here, fix some cleanup on error conditions in proc_thermal_add(). No functional changes are expected with this change. Signed-off-by: Srinivas Pandruvada Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210525204811.3793651-2-srinivas.pandruvada@linux.intel.com --- drivers/thermal/intel/int340x_thermal/Makefile | 2 + .../intel/int340x_thermal/int3401_thermal.c | 82 ++++++ .../int340x_thermal/processor_thermal_device.c | 289 +++------------------ .../int340x_thermal/processor_thermal_device.h | 8 +- .../processor_thermal_device_pci_legacy.c | 164 ++++++++++++ 5 files changed, 286 insertions(+), 259 deletions(-) create mode 100644 drivers/thermal/intel/int340x_thermal/int3401_thermal.c create mode 100644 drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/int340x_thermal/Makefile b/drivers/thermal/intel/int340x_thermal/Makefile index 38a2731e503c..aaf02d5deed5 100644 --- a/drivers/thermal/intel/int340x_thermal/Makefile +++ b/drivers/thermal/intel/int340x_thermal/Makefile @@ -4,6 +4,8 @@ obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal_zone.o obj-$(CONFIG_INT340X_THERMAL) += int3402_thermal.o obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device.o +obj-$(CONFIG_INT340X_THERMAL) += int3401_thermal.o +obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device_pci_legacy.o obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o diff --git a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c new file mode 100644 index 000000000000..acebc8ba94e2 --- /dev/null +++ b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * INT3401 processor thermal device + * Copyright (c) 2020, Intel Corporation. + */ +#include +#include +#include +#include +#include + +#include "int340x_thermal_zone.h" +#include "processor_thermal_device.h" + +static const struct acpi_device_id int3401_device_ids[] = { + {"INT3401", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, int3401_device_ids); + +static int int3401_add(struct platform_device *pdev) +{ + struct proc_thermal_device *proc_priv; + int ret; + + proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); + if (!proc_priv) + return -ENOMEM; + + ret = proc_thermal_add(&pdev->dev, proc_priv); + if (ret) + return ret; + + platform_set_drvdata(pdev, proc_priv); + + return ret; +} + +static int int3401_remove(struct platform_device *pdev) +{ + proc_thermal_remove(platform_get_drvdata(pdev)); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int int3401_thermal_resume(struct device *dev) +{ + return proc_thermal_resume(dev); +} +#else +#define int3401_thermal_resume NULL +#endif + +static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, NULL, int3401_thermal_resume); + +static struct platform_driver int3401_driver = { + .probe = int3401_add, + .remove = int3401_remove, + .driver = { + .name = "int3401 thermal", + .acpi_match_table = int3401_device_ids, + .pm = &int3401_proc_thermal_pm, + }, +}; + +static int __init proc_thermal_init(void) +{ + return platform_driver_register(&int3401_driver); +} + +static void __exit proc_thermal_exit(void) +{ + platform_driver_unregister(&int3401_driver); +} + +module_init(proc_thermal_init); +module_exit(proc_thermal_exit); + +MODULE_AUTHOR("Srinivas Pandruvada "); +MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index 9e6f2a895a23..de4fc640deb0 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -3,34 +3,17 @@ * processor_thermal_device.c * Copyright (c) 2014, Intel Corporation. */ +#include #include #include -#include #include -#include -#include -#include #include -#include #include "int340x_thermal_zone.h" #include "processor_thermal_device.h" #include "../intel_soc_dts_iosf.h" #define DRV_NAME "proc_thermal" -enum proc_thermal_emum_mode_type { - PROC_THERMAL_NONE, - PROC_THERMAL_PCI, - PROC_THERMAL_PLATFORM_DEV -}; - -/* - * We can have only one type of enumeration, PCI or Platform, - * not both. So we don't need instance specific data. - */ -static enum proc_thermal_emum_mode_type proc_thermal_emum_mode = - PROC_THERMAL_NONE; - #define POWER_LIMIT_SHOW(index, suffix) \ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \ struct device_attribute *attr, \ @@ -38,11 +21,6 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \ { \ struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); \ \ - if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \ - dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \ - return 0; \ - } \ - \ return sprintf(buf, "%lu\n",\ (unsigned long)proc_dev->power_limits[index].suffix * 1000); \ } @@ -291,11 +269,8 @@ static void proc_thermal_notify(acpi_handle handle, u32 event, void *data) } } - -static int proc_thermal_add(struct device *dev, - struct proc_thermal_device **priv) +int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv) { - struct proc_thermal_device *proc_priv; struct acpi_device *adev; acpi_status status; unsigned long long tmp; @@ -306,13 +281,8 @@ static int proc_thermal_add(struct device *dev, if (!adev) return -ENODEV; - proc_priv = devm_kzalloc(dev, sizeof(*proc_priv), GFP_KERNEL); - if (!proc_priv) - return -ENOMEM; - proc_priv->dev = dev; proc_priv->adev = adev; - *priv = proc_priv; ret = proc_thermal_read_ppcc(proc_priv); if (ret) @@ -338,15 +308,29 @@ static int proc_thermal_add(struct device *dev, if (ret) goto remove_zone; + ret = sysfs_create_file(&dev->kobj, &dev_attr_tcc_offset_degree_celsius.attr); + if (ret) + goto remove_notify; + + ret = sysfs_create_group(&dev->kobj, &power_limit_attribute_group); + if (ret) { + sysfs_remove_file(&dev->kobj, &dev_attr_tcc_offset_degree_celsius.attr); + goto remove_notify; + } + return 0; +remove_notify: + acpi_remove_notify_handler(adev->handle, + ACPI_DEVICE_NOTIFY, proc_thermal_notify); remove_zone: int340x_thermal_zone_remove(proc_priv->int340x_zone); return ret; } +EXPORT_SYMBOL_GPL(proc_thermal_add); -static void proc_thermal_remove(struct proc_thermal_device *proc_priv) +void proc_thermal_remove(struct proc_thermal_device *proc_priv) { acpi_remove_notify_handler(proc_priv->adev->handle, ACPI_DEVICE_NOTIFY, proc_thermal_notify); @@ -355,60 +339,24 @@ static void proc_thermal_remove(struct proc_thermal_device *proc_priv) sysfs_remove_group(&proc_priv->dev->kobj, &power_limit_attribute_group); } +EXPORT_SYMBOL_GPL(proc_thermal_remove); -static int int3401_add(struct platform_device *pdev) +int proc_thermal_resume(struct device *dev) { - struct proc_thermal_device *proc_priv; - int ret; - - if (proc_thermal_emum_mode == PROC_THERMAL_PCI) { - dev_err(&pdev->dev, "error: enumerated as PCI dev\n"); - return -ENODEV; - } - - ret = proc_thermal_add(&pdev->dev, &proc_priv); - if (ret) - return ret; - - platform_set_drvdata(pdev, proc_priv); - proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV; - - dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n"); - - ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr); - if (ret) - return ret; - - ret = sysfs_create_group(&pdev->dev.kobj, &power_limit_attribute_group); - if (ret) - sysfs_remove_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr); + struct proc_thermal_device *proc_dev; - return ret; -} + proc_dev = dev_get_drvdata(dev); + proc_thermal_read_ppcc(proc_dev); -static int int3401_remove(struct platform_device *pdev) -{ - proc_thermal_remove(platform_get_drvdata(pdev)); + tcc_offset_update(tcc_offset_save); return 0; } - -static irqreturn_t proc_thermal_pci_msi_irq(int irq, void *devid) -{ - struct proc_thermal_device *proc_priv; - struct pci_dev *pdev = devid; - - proc_priv = pci_get_drvdata(pdev); - - intel_soc_dts_iosf_interrupt_handler(proc_priv->soc_dts); - - return IRQ_HANDLED; -} +EXPORT_SYMBOL_GPL(proc_thermal_resume); #define MCHBAR 0 -static int proc_thermal_set_mmio_base(struct pci_dev *pdev, - struct proc_thermal_device *proc_priv) +static int proc_thermal_set_mmio_base(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) { int ret; @@ -423,9 +371,9 @@ static int proc_thermal_set_mmio_base(struct pci_dev *pdev, return 0; } -static int proc_thermal_mmio_add(struct pci_dev *pdev, - struct proc_thermal_device *proc_priv, - kernel_ulong_t feature_mask) +int proc_thermal_mmio_add(struct pci_dev *pdev, + struct proc_thermal_device *proc_priv, + kernel_ulong_t feature_mask) { int ret; @@ -471,11 +419,10 @@ err_rem_rapl: return ret; } +EXPORT_SYMBOL_GPL(proc_thermal_mmio_add); -static void proc_thermal_mmio_remove(struct pci_dev *pdev) +void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) { - struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); - if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_RAPL) proc_thermal_rapl_remove(); @@ -486,181 +433,7 @@ static void proc_thermal_mmio_remove(struct pci_dev *pdev) if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MBOX) proc_thermal_mbox_remove(pdev); } - -static int proc_thermal_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - struct proc_thermal_device *proc_priv; - int ret; - - if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { - dev_err(&pdev->dev, "error: enumerated as platform dev\n"); - return -ENODEV; - } - - ret = pcim_enable_device(pdev); - if (ret < 0) { - dev_err(&pdev->dev, "error: could not enable device\n"); - return ret; - } - - ret = proc_thermal_add(&pdev->dev, &proc_priv); - if (ret) - return ret; - - pci_set_drvdata(pdev, proc_priv); - proc_thermal_emum_mode = PROC_THERMAL_PCI; - - if (pdev->device == PCI_DEVICE_ID_INTEL_BSW_THERMAL) { - /* - * Enumerate additional DTS sensors available via IOSF. - * But we are not treating as a failure condition, if - * there are no aux DTSs enabled or fails. This driver - * already exposes sensors, which can be accessed via - * ACPI/MSR. So we don't want to fail for auxiliary DTSs. - */ - proc_priv->soc_dts = intel_soc_dts_iosf_init( - INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0); - - if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) { - ret = pci_enable_msi(pdev); - if (!ret) { - ret = request_threaded_irq(pdev->irq, NULL, - proc_thermal_pci_msi_irq, - IRQF_ONESHOT, "proc_thermal", - pdev); - if (ret) { - intel_soc_dts_iosf_exit( - proc_priv->soc_dts); - pci_disable_msi(pdev); - proc_priv->soc_dts = NULL; - } - } - } else - dev_err(&pdev->dev, "No auxiliary DTSs enabled\n"); - } - - dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n"); - - ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr); - if (ret) - return ret; - - ret = sysfs_create_group(&pdev->dev.kobj, &power_limit_attribute_group); - if (ret) { - sysfs_remove_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr); - return ret; - } - - ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); - if (ret) { - proc_thermal_remove(proc_priv); - return ret; - } - - return 0; -} - -static void proc_thermal_pci_remove(struct pci_dev *pdev) -{ - struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); - - if (proc_priv->soc_dts) { - intel_soc_dts_iosf_exit(proc_priv->soc_dts); - if (pdev->irq) { - free_irq(pdev->irq, pdev); - pci_disable_msi(pdev); - } - } - - proc_thermal_mmio_remove(pdev); - proc_thermal_remove(proc_priv); -} - -#ifdef CONFIG_PM_SLEEP -static int proc_thermal_resume(struct device *dev) -{ - struct proc_thermal_device *proc_dev; - - proc_dev = dev_get_drvdata(dev); - proc_thermal_read_ppcc(proc_dev); - - tcc_offset_update(tcc_offset_save); - - return 0; -} -#else -#define proc_thermal_resume NULL -#endif - -static SIMPLE_DEV_PM_OPS(proc_thermal_pm, NULL, proc_thermal_resume); - -static const struct pci_device_id proc_thermal_pci_ids[] = { - { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, - { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, BSW_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, BXT0_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, BXT1_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, BXTX_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, BXTP_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, CNL_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, CFL_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, GLK_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, HSB_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, - { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) }, - { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, - { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_MBOX) }, - { }, -}; - -MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); - -static struct pci_driver proc_thermal_pci_driver = { - .name = DRV_NAME, - .probe = proc_thermal_pci_probe, - .remove = proc_thermal_pci_remove, - .id_table = proc_thermal_pci_ids, - .driver.pm = &proc_thermal_pm, -}; - -static const struct acpi_device_id int3401_device_ids[] = { - {"INT3401", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, int3401_device_ids); - -static struct platform_driver int3401_driver = { - .probe = int3401_add, - .remove = int3401_remove, - .driver = { - .name = "int3401 thermal", - .acpi_match_table = int3401_device_ids, - .pm = &proc_thermal_pm, - }, -}; - -static int __init proc_thermal_init(void) -{ - int ret; - - ret = platform_driver_register(&int3401_driver); - if (ret) - return ret; - - ret = pci_register_driver(&proc_thermal_pci_driver); - - return ret; -} - -static void __exit proc_thermal_exit(void) -{ - platform_driver_unregister(&int3401_driver); - pci_unregister_driver(&proc_thermal_pci_driver); -} - -module_init(proc_thermal_init); -module_exit(proc_thermal_exit); +EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); MODULE_AUTHOR("Srinivas Pandruvada "); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index 3161607424f5..5e51f1173d00 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -80,5 +80,11 @@ int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc void proc_thermal_mbox_remove(struct pci_dev *pdev); int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp); - +int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv); +void proc_thermal_remove(struct proc_thermal_device *proc_priv); +int proc_thermal_resume(struct device *dev); +int proc_thermal_mmio_add(struct pci_dev *pdev, + struct proc_thermal_device *proc_priv, + kernel_ulong_t feature_mask); +void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); #endif diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c new file mode 100644 index 000000000000..21cf7511d376 --- /dev/null +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * B0D4 processor thermal device + * Copyright (c) 2020, Intel Corporation. + */ + +#include +#include +#include +#include +#include + +#include "int340x_thermal_zone.h" +#include "processor_thermal_device.h" +#include "../intel_soc_dts_iosf.h" + +#define DRV_NAME "proc_thermal" + +static irqreturn_t proc_thermal_pci_msi_irq(int irq, void *devid) +{ + struct proc_thermal_device *proc_priv; + struct pci_dev *pdev = devid; + + proc_priv = pci_get_drvdata(pdev); + + intel_soc_dts_iosf_interrupt_handler(proc_priv->soc_dts); + + return IRQ_HANDLED; +} + +static int proc_thermal_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct proc_thermal_device *proc_priv; + int ret; + + ret = pcim_enable_device(pdev); + if (ret < 0) { + dev_err(&pdev->dev, "error: could not enable device\n"); + return ret; + } + + proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); + if (!proc_priv) + return -ENOMEM; + + ret = proc_thermal_add(&pdev->dev, proc_priv); + if (ret) + return ret; + + pci_set_drvdata(pdev, proc_priv); + + if (pdev->device == PCI_DEVICE_ID_INTEL_BSW_THERMAL) { + /* + * Enumerate additional DTS sensors available via IOSF. + * But we are not treating as a failure condition, if + * there are no aux DTSs enabled or fails. This driver + * already exposes sensors, which can be accessed via + * ACPI/MSR. So we don't want to fail for auxiliary DTSs. + */ + proc_priv->soc_dts = intel_soc_dts_iosf_init( + INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0); + + if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) { + ret = pci_enable_msi(pdev); + if (!ret) { + ret = request_threaded_irq(pdev->irq, NULL, + proc_thermal_pci_msi_irq, + IRQF_ONESHOT, "proc_thermal", + pdev); + if (ret) { + intel_soc_dts_iosf_exit( + proc_priv->soc_dts); + pci_disable_msi(pdev); + proc_priv->soc_dts = NULL; + } + } + } else + dev_err(&pdev->dev, "No auxiliary DTSs enabled\n"); + } else { + + } + + ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); + if (ret) { + proc_thermal_remove(proc_priv); + return ret; + } + + return 0; +} + +static void proc_thermal_pci_remove(struct pci_dev *pdev) +{ + struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); + + if (proc_priv->soc_dts) { + intel_soc_dts_iosf_exit(proc_priv->soc_dts); + if (pdev->irq) { + free_irq(pdev->irq, pdev); + pci_disable_msi(pdev); + } + } + + proc_thermal_mmio_remove(pdev, proc_priv); + proc_thermal_remove(proc_priv); +} + +#ifdef CONFIG_PM_SLEEP +static int proc_thermal_pci_resume(struct device *dev) +{ + return proc_thermal_resume(dev); +} +#else +#define proc_thermal_pci_resume NULL +#endif + +static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume); + +static const struct pci_device_id proc_thermal_pci_ids[] = { + { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, + { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, BSW_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, BXT0_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, BXT1_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, BXTX_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, BXTP_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, CNL_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, CFL_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, GLK_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, HSB_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, + { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) }, + { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, + { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_MBOX) }, + { }, +}; + +MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); + +static struct pci_driver proc_thermal_pci_driver = { + .name = DRV_NAME, + .probe = proc_thermal_pci_probe, + .remove = proc_thermal_pci_remove, + .id_table = proc_thermal_pci_ids, + .driver.pm = &proc_thermal_pci_pm, +}; + +static int __init proc_thermal_init(void) +{ + return pci_register_driver(&proc_thermal_pci_driver); +} + +static void __exit proc_thermal_exit(void) +{ + pci_unregister_driver(&proc_thermal_pci_driver); +} + +module_init(proc_thermal_init); +module_exit(proc_thermal_exit); + +MODULE_AUTHOR("Srinivas Pandruvada "); +MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-70-g09d2 From acd65d5d1cf4a3324c8970ba74632abe069fe23e Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Tue, 25 May 2021 13:48:11 -0700 Subject: thermal/drivers/int340x/processor_thermal: Add PCI MMIO based thermal driver Add a new PCI driver which register a thermal zone and allows to get notification for threshold violation by a RW trip point. These notifications are delivered from the device using MSI based interrupt. The main difference between this new PCI driver and the existing one is that the temperature and trip points directly use PCI MMIO instead of using ACPI methods. This driver registers a thermal zone "TCPU_PCI" in addition to the legacy processor thermal device, which uses ACPI companion device to set name, temperature and trips. This driver is enabled for AlderLake. Signed-off-by: Srinivas Pandruvada Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210525204811.3793651-3-srinivas.pandruvada@linux.intel.com --- drivers/thermal/intel/int340x_thermal/Makefile | 1 + .../int340x_thermal/processor_thermal_device.h | 1 + .../int340x_thermal/processor_thermal_device_pci.c | 371 +++++++++++++++++++++ .../processor_thermal_device_pci_legacy.c | 1 - 4 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/int340x_thermal/Makefile b/drivers/thermal/intel/int340x_thermal/Makefile index aaf02d5deed5..4e852ce4a5d5 100644 --- a/drivers/thermal/intel/int340x_thermal/Makefile +++ b/drivers/thermal/intel/int340x_thermal/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device.o obj-$(CONFIG_INT340X_THERMAL) += int3401_thermal.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device_pci_legacy.o +obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device_pci.o obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index 5e51f1173d00..5a1cfe4864f1 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -44,6 +44,7 @@ struct proc_thermal_device { struct intel_soc_dts_sensors *soc_dts; u32 mmio_feature_mask; void __iomem *mmio_base; + void *priv_data; }; struct rapl_mmio_regs { diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c new file mode 100644 index 000000000000..ad7e2e305abf --- /dev/null +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -0,0 +1,371 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Processor thermal device for newer processors + * Copyright (c) 2020, Intel Corporation. + */ + +#include +#include +#include +#include +#include + +#include "int340x_thermal_zone.h" +#include "processor_thermal_device.h" + +#define DRV_NAME "proc_thermal_pci" + +struct proc_thermal_pci { + struct pci_dev *pdev; + struct proc_thermal_device *proc_priv; + struct thermal_zone_device *tzone; + struct delayed_work work; + int stored_thres; + int no_legacy; +}; + +enum proc_thermal_mmio_type { + PROC_THERMAL_MMIO_TJMAX, + PROC_THERMAL_MMIO_PP0_TEMP, + PROC_THERMAL_MMIO_PP1_TEMP, + PROC_THERMAL_MMIO_PKG_TEMP, + PROC_THERMAL_MMIO_THRES_0, + PROC_THERMAL_MMIO_THRES_1, + PROC_THERMAL_MMIO_INT_ENABLE_0, + PROC_THERMAL_MMIO_INT_ENABLE_1, + PROC_THERMAL_MMIO_INT_STATUS_0, + PROC_THERMAL_MMIO_INT_STATUS_1, + PROC_THERMAL_MMIO_MAX +}; + +struct proc_thermal_mmio_info { + enum proc_thermal_mmio_type mmio_type; + u64 mmio_addr; + u64 shift; + u64 mask; +}; + +static struct proc_thermal_mmio_info proc_thermal_mmio_info[] = { + { PROC_THERMAL_MMIO_TJMAX, 0x599c, 16, 0xff }, + { PROC_THERMAL_MMIO_PP0_TEMP, 0x597c, 0, 0xff }, + { PROC_THERMAL_MMIO_PP1_TEMP, 0x5980, 0, 0xff }, + { PROC_THERMAL_MMIO_PKG_TEMP, 0x5978, 0, 0xff }, + { PROC_THERMAL_MMIO_THRES_0, 0x5820, 8, 0x7F }, + { PROC_THERMAL_MMIO_THRES_1, 0x5820, 16, 0x7F }, + { PROC_THERMAL_MMIO_INT_ENABLE_0, 0x5820, 15, 0x01 }, + { PROC_THERMAL_MMIO_INT_ENABLE_1, 0x5820, 23, 0x01 }, + { PROC_THERMAL_MMIO_INT_STATUS_0, 0x7200, 6, 0x01 }, + { PROC_THERMAL_MMIO_INT_STATUS_1, 0x7200, 8, 0x01 }, +}; + +#define B0D4_THERMAL_NOTIFY_DELAY 1000 +static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY; + +static void proc_thermal_mmio_read(struct proc_thermal_pci *pci_info, + enum proc_thermal_mmio_type type, + u32 *value) +{ + *value = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base + + proc_thermal_mmio_info[type].mmio_addr)); + *value >>= proc_thermal_mmio_info[type].shift; + *value &= proc_thermal_mmio_info[type].mask; +} + +static void proc_thermal_mmio_write(struct proc_thermal_pci *pci_info, + enum proc_thermal_mmio_type type, + u32 value) +{ + u32 current_val; + u32 mask; + + current_val = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base + + proc_thermal_mmio_info[type].mmio_addr)); + mask = proc_thermal_mmio_info[type].mask << proc_thermal_mmio_info[type].shift; + current_val &= ~mask; + + value &= proc_thermal_mmio_info[type].mask; + value <<= proc_thermal_mmio_info[type].shift; + + current_val |= value; + iowrite32(current_val, ((u8 __iomem *)pci_info->proc_priv->mmio_base + + proc_thermal_mmio_info[type].mmio_addr)); +} + +/* + * To avoid sending two many messages to user space, we have 1 second delay. + * On interrupt we are disabling interrupt and enabling after 1 second. + * This workload function is delayed by 1 second. + */ +static void proc_thermal_threshold_work_fn(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct proc_thermal_pci *pci_info = container_of(delayed_work, + struct proc_thermal_pci, work); + struct thermal_zone_device *tzone = pci_info->tzone; + + if (tzone) + thermal_zone_device_update(tzone, THERMAL_TRIP_VIOLATED); + + /* Enable interrupt flag */ + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); +} + +static void pkg_thermal_schedule_work(struct delayed_work *work) +{ + unsigned long ms = msecs_to_jiffies(notify_delay_ms); + + schedule_delayed_work(work, ms); +} + +static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) +{ + struct proc_thermal_pci *pci_info = devid; + u32 status; + + proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); + + /* Disable enable interrupt flag */ + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); + pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); + + pkg_thermal_schedule_work(&pci_info->work); + + return IRQ_HANDLED; +} + +static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) +{ + struct proc_thermal_pci *pci_info = tzd->devdata; + u32 _temp; + + proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_PKG_TEMP, &_temp); + *temp = (unsigned long)_temp * 1000; + + return 0; +} + +static int sys_get_trip_temp(struct thermal_zone_device *tzd, + int trip, int *temp) +{ + struct proc_thermal_pci *pci_info = tzd->devdata; + u32 _temp; + + proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &_temp); + if (!_temp) { + *temp = THERMAL_TEMP_INVALID; + } else { + int tjmax; + + proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); + _temp = tjmax - _temp; + *temp = (unsigned long)_temp * 1000; + } + + return 0; +} + +static int sys_get_trip_type(struct thermal_zone_device *tzd, int trip, + enum thermal_trip_type *type) +{ + *type = THERMAL_TRIP_PASSIVE; + + return 0; +} + +static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) +{ + struct proc_thermal_pci *pci_info = tzd->devdata; + int tjmax, _temp; + + if (temp <= 0) { + cancel_delayed_work_sync(&pci_info->work); + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0); + thermal_zone_device_disable(tzd); + pci_info->stored_thres = 0; + return 0; + } + + proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); + _temp = tjmax - (temp / 1000); + if (_temp < 0) + return -EINVAL; + + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, _temp); + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); + + thermal_zone_device_enable(tzd); + pci_info->stored_thres = temp; + + return 0; +} + +static struct thermal_zone_device_ops tzone_ops = { + .get_temp = sys_get_curr_temp, + .get_trip_temp = sys_get_trip_temp, + .get_trip_type = sys_get_trip_type, + .set_trip_temp = sys_set_trip_temp, +}; + +static struct thermal_zone_params tzone_params = { + .governor_name = "user_space", + .no_hwmon = true, +}; + +static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct proc_thermal_device *proc_priv; + struct proc_thermal_pci *pci_info; + int irq_flag = 0, irq, ret; + + proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); + if (!proc_priv) + return -ENOMEM; + + pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL); + if (!pci_info) + return -ENOMEM; + + pci_info->pdev = pdev; + ret = pcim_enable_device(pdev); + if (ret < 0) { + dev_err(&pdev->dev, "error: could not enable device\n"); + return ret; + } + + pci_set_master(pdev); + + INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn); + + ret = proc_thermal_add(&pdev->dev, proc_priv); + if (ret) { + dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n"); + pci_info->no_legacy = 1; + } + + proc_priv->priv_data = pci_info; + pci_info->proc_priv = proc_priv; + pci_set_drvdata(pdev, proc_priv); + + ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); + if (ret) + goto err_ret_thermal; + + pci_info->tzone = thermal_zone_device_register("TCPU_PCI", 1, 1, pci_info, + &tzone_ops, + &tzone_params, 0, 0); + if (IS_ERR(pci_info->tzone)) + goto err_ret_mmio; + + /* request and enable interrupt */ + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to allocate vectors!\n"); + goto err_ret_tzone; + } + if (!pdev->msi_enabled && !pdev->msix_enabled) + irq_flag = IRQF_SHARED; + + irq = pci_irq_vector(pdev, 0); + ret = devm_request_threaded_irq(&pdev->dev, irq, + proc_thermal_irq_handler, NULL, + irq_flag, KBUILD_MODNAME, pci_info); + if (ret) { + dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq); + goto err_free_vectors; + } + + return 0; + +err_free_vectors: + pci_free_irq_vectors(pdev); +err_ret_tzone: + thermal_zone_device_unregister(pci_info->tzone); +err_ret_mmio: + proc_thermal_mmio_remove(pdev, proc_priv); +err_ret_thermal: + if (!pci_info->no_legacy) + proc_thermal_remove(proc_priv); + pci_disable_device(pdev); + + return ret; +} + +static void proc_thermal_pci_remove(struct pci_dev *pdev) +{ + struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); + struct proc_thermal_pci *pci_info = proc_priv->priv_data; + + cancel_delayed_work_sync(&pci_info->work); + + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0); + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); + + devm_free_irq(&pdev->dev, pdev->irq, pci_info); + pci_free_irq_vectors(pdev); + + thermal_zone_device_unregister(pci_info->tzone); + proc_thermal_mmio_remove(pdev, pci_info->proc_priv); + if (!pci_info->no_legacy) + proc_thermal_remove(proc_priv); + pci_disable_device(pdev); +} + +#ifdef CONFIG_PM_SLEEP +static int proc_thermal_pci_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct proc_thermal_device *proc_priv; + struct proc_thermal_pci *pci_info; + + proc_priv = pci_get_drvdata(pdev); + pci_info = proc_priv->priv_data; + + if (pci_info->stored_thres) { + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, + pci_info->stored_thres / 1000); + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); + } + + if (!pci_info->no_legacy) + return proc_thermal_resume(dev); + + return 0; +} +#else +#define proc_thermal_pci_resume NULL +#endif + +static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume); + +static const struct pci_device_id proc_thermal_pci_ids[] = { + { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, + { }, +}; + +MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); + +static struct pci_driver proc_thermal_pci_driver = { + .name = DRV_NAME, + .probe = proc_thermal_pci_probe, + .remove = proc_thermal_pci_remove, + .id_table = proc_thermal_pci_ids, + .driver.pm = &proc_thermal_pci_pm, +}; + +static int __init proc_thermal_init(void) +{ + return pci_register_driver(&proc_thermal_pci_driver); +} + +static void __exit proc_thermal_exit(void) +{ + pci_unregister_driver(&proc_thermal_pci_driver); +} + +module_init(proc_thermal_init); +module_exit(proc_thermal_exit); + +MODULE_AUTHOR("Srinivas Pandruvada "); +MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c index 21cf7511d376..f5fc1791b11e 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c @@ -118,7 +118,6 @@ static int proc_thermal_pci_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume); static const struct pci_device_id proc_thermal_pci_ids[] = { - { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) }, { PCI_DEVICE_DATA(INTEL, BSW_THERMAL, 0) }, { PCI_DEVICE_DATA(INTEL, BXT0_THERMAL, 0) }, -- cgit v1.2.3-70-g09d2 From 24e21d9f40ec3fb4228e3427454b733316a2a6c6 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 8 Jun 2021 17:45:30 +0200 Subject: thermal/drivers/mediatek: Add sensors-support Add HWMON-support to mediateks thermal driver to allow lm-sensors userspace tools read soc temperature Signed-off-by: Frank Wunderlich Reviewed-by: Matthias Brugger Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210608154530.70074-1-linux@fw-web.de --- drivers/thermal/mtk_thermal.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 97e8678ccf0e..ede94eadddda 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -23,6 +23,8 @@ #include #include +#include "thermal_hwmon.h" + /* AUXADC Registers */ #define AUXADC_CON1_SET_V 0x008 #define AUXADC_CON1_CLR_V 0x00c @@ -1087,6 +1089,10 @@ static int mtk_thermal_probe(struct platform_device *pdev) goto err_disable_clk_peri_therm; } + ret = devm_thermal_add_hwmon_sysfs(tzdev); + if (ret) + dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs"); + return 0; err_disable_clk_peri_therm: -- cgit v1.2.3-70-g09d2 From ad079d981db6a4047b60c576df6430bed36bcd7d Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Jun 2021 11:32:32 -0700 Subject: thermal/drivers/int340x/processor_thermal: Fix warning for return value Fix smatch warnings: drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c:258 proc_thermal_pci_probe() warn: missing error code 'ret' Use PTR_ERR to return failure of thermal_zone_device_register(). Reported-by: kernel test robot Signed-off-by: Srinivas Pandruvada Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210628183232.62877-1-srinivas.pandruvada@linux.intel.com --- drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c index ad7e2e305abf..11dd2e825f4f 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -254,8 +254,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ pci_info->tzone = thermal_zone_device_register("TCPU_PCI", 1, 1, pci_info, &tzone_ops, &tzone_params, 0, 0); - if (IS_ERR(pci_info->tzone)) + if (IS_ERR(pci_info->tzone)) { + ret = PTR_ERR(pci_info->tzone); goto err_ret_mmio; + } /* request and enable interrupt */ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); -- cgit v1.2.3-70-g09d2 From fe6a6de6692e7f7159c1ff42b07ecd737df712b4 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Jun 2021 14:58:03 -0700 Subject: thermal/drivers/int340x/processor_thermal: Fix tcc setting The following fixes are done for tcc sysfs interface: - TCC is 6 bits only from bit 29-24 - TCC of 0 is valid - When BIT(31) is set, this register is read only - Check for invalid tcc value - Error for negative values Fixes: fdf4f2fb8e899 ("drivers: thermal: processor_thermal_device: Export sysfs interface for TCC offset") Signed-off-by: Srinivas Pandruvada Cc: stable@vger.kernel.org Acked-by: Zhang Rui Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20210628215803.75038-1-srinivas.pandruvada@linux.intel.com --- .../intel/int340x_thermal/processor_thermal_device.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index de4fc640deb0..0f0038af2ad4 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -78,24 +78,27 @@ static ssize_t tcc_offset_degree_celsius_show(struct device *dev, if (err) return err; - val = (val >> 24) & 0xff; + val = (val >> 24) & 0x3f; return sprintf(buf, "%d\n", (int)val); } -static int tcc_offset_update(int tcc) +static int tcc_offset_update(unsigned int tcc) { u64 val; int err; - if (!tcc) + if (tcc > 63) return -EINVAL; err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val); if (err) return err; - val &= ~GENMASK_ULL(31, 24); - val |= (tcc & 0xff) << 24; + if (val & BIT(31)) + return -EPERM; + + val &= ~GENMASK_ULL(29, 24); + val |= (tcc & 0x3f) << 24; err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val); if (err) @@ -104,14 +107,15 @@ static int tcc_offset_update(int tcc) return 0; } -static int tcc_offset_save; +static unsigned int tcc_offset_save; static ssize_t tcc_offset_degree_celsius_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + unsigned int tcc; u64 val; - int tcc, err; + int err; err = rdmsrl_safe(MSR_PLATFORM_INFO, &val); if (err) @@ -120,7 +124,7 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev, if (!(val & BIT(30))) return -EACCES; - if (kstrtoint(buf, 0, &tcc)) + if (kstrtouint(buf, 0, &tcc)) return -EINVAL; err = tcc_offset_update(tcc); -- cgit v1.2.3-70-g09d2