diff options
-rw-r--r-- | Documentation/devicetree/bindings/thermal/qcom-tsens.txt | 31 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/msm8996.dtsi | 14 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/sdm845.dtsi | 186 | ||||
-rw-r--r-- | drivers/thermal/qcom/Makefile | 2 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-8996.c | 84 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-common.c | 29 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-v2.c | 77 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens.c | 3 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens.h | 8 |
9 files changed, 330 insertions, 104 deletions
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt index 06195e8f35e2..1d9e8cf61018 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt @@ -1,18 +1,28 @@ * QCOM SoC Temperature Sensor (TSENS) Required properties: -- compatible : - - "qcom,msm8916-tsens" : For 8916 Family of SoCs - - "qcom,msm8974-tsens" : For 8974 Family of SoCs - - "qcom,msm8996-tsens" : For 8996 Family of SoCs +- compatible: + Must be one of the following: + - "qcom,msm8916-tsens" (MSM8916) + - "qcom,msm8974-tsens" (MSM8974) + - "qcom,msm8996-tsens" (MSM8996) + - "qcom,msm8998-tsens", "qcom,tsens-v2" (MSM8998) + - "qcom,sdm845-tsens", "qcom,tsens-v2" (SDM845) + The generic "qcom,tsens-v2" property must be used as a fallback for any SoC + with version 2 of the TSENS IP. MSM8996 is the only exception because the + generic property did not exist when support was added. + +- reg: Address range of the thermal registers. + New platforms containing v2.x.y of the TSENS IP must specify the SROT and TM + register spaces separately, with order being TM before SROT. + See Example 2, below. -- reg: Address range of the thermal registers - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description. - #qcom,sensors: Number of sensors in tsens block - Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify nvmem cells -Example: +Example 1 (legacy support before a fallback tsens-v2 property was introduced): tsens: thermal-sensor@900000 { compatible = "qcom,msm8916-tsens"; reg = <0x4a8000 0x2000>; @@ -20,3 +30,12 @@ tsens: thermal-sensor@900000 { nvmem-cell-names = "caldata", "calsel"; #thermal-sensor-cells = <1>; }; + +Example 2 (for any platform containing v2 of the TSENS IP): +tsens0: thermal-sensor@c263000 { + compatible = "qcom,sdm845-tsens", "qcom,tsens-v2"; + reg = <0xc263000 0x1ff>, /* TM */ + <0xc222000 0x1ff>; /* SROT */ + #qcom,sensors = <13>; + #thermal-sensor-cells = <1>; + }; diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index bd7633dff2e5..c2dca3a30091 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -965,9 +965,19 @@ status = "disabled"; }; - tsens0: thermal-sensor@4a8000 { + tsens0: thermal-sensor@4a9000 { compatible = "qcom,msm8996-tsens"; - reg = <0x4a8000 0x2000>; + reg = <0x4a9000 0x1000>, /* TM */ + <0x4a8000 0x1000>; /* SROT */ + #qcom,sensors = <13>; + #thermal-sensor-cells = <1>; + }; + + tsens1: thermal-sensor@4ad000 { + compatible = "qcom,msm8996-tsens"; + reg = <0x4ad000 0x1000>, /* TM */ + <0x4ac000 0x1000>; /* SROT */ + #qcom,sensors = <8>; #thermal-sensor-cells = <1>; }; diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index accd522f28c7..26600c0f0b7f 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1527,6 +1527,22 @@ }; }; + tsens0: thermal-sensor@c263000 { + compatible = "qcom,sdm845-tsens", "qcom,tsens-v2"; + reg = <0xc263000 0x1ff>, /* TM */ + <0xc222000 0x1ff>; /* SROT */ + #qcom,sensors = <13>; + #thermal-sensor-cells = <1>; + }; + + tsens1: thermal-sensor@c265000 { + compatible = "qcom,sdm845-tsens", "qcom,tsens-v2"; + reg = <0xc265000 0x1ff>, /* TM */ + <0xc223000 0x1ff>; /* SROT */ + #qcom,sensors = <8>; + #thermal-sensor-cells = <1>; + }; + spmi_bus: spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xc440000 0x1100>, @@ -1741,4 +1757,174 @@ status = "disabled"; }; }; + + thermal-zones { + cpu0-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 1>; + + trips { + cpu_alert0: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit0: trip1 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 2>; + + trips { + cpu_alert1: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit1: trip1 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 3>; + + trips { + cpu_alert2: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit2: trip1 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 4>; + + trips { + cpu_alert3: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit3: trip1 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu4-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 7>; + + trips { + cpu_alert4: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit4: trip1 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu5-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 8>; + + trips { + cpu_alert5: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit5: trip1 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu6-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 9>; + + trips { + cpu_alert6: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit6: trip1 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu7-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 10>; + + trips { + cpu_alert7: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit7: trip1 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; }; diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile index 2cc2193637e7..a821929ede0b 100644 --- a/drivers/thermal/qcom/Makefile +++ b/drivers/thermal/qcom/Makefile @@ -1,2 +1,2 @@ obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o -qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o +qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o diff --git a/drivers/thermal/qcom/tsens-8996.c b/drivers/thermal/qcom/tsens-8996.c deleted file mode 100644 index e1f77818d8fa..000000000000 --- a/drivers/thermal/qcom/tsens-8996.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/platform_device.h> -#include <linux/regmap.h> -#include "tsens.h" - -#define STATUS_OFFSET 0x10a0 -#define LAST_TEMP_MASK 0xfff -#define STATUS_VALID_BIT BIT(21) -#define CODE_SIGN_BIT BIT(11) - -static int get_temp_8996(struct tsens_device *tmdev, int id, int *temp) -{ - struct tsens_sensor *s = &tmdev->sensor[id]; - u32 code; - unsigned int sensor_addr; - int last_temp = 0, last_temp2 = 0, last_temp3 = 0, ret; - - sensor_addr = STATUS_OFFSET + s->hw_id * 4; - ret = regmap_read(tmdev->map, sensor_addr, &code); - if (ret) - return ret; - last_temp = code & LAST_TEMP_MASK; - if (code & STATUS_VALID_BIT) - goto done; - - /* Try a second time */ - ret = regmap_read(tmdev->map, sensor_addr, &code); - if (ret) - return ret; - if (code & STATUS_VALID_BIT) { - last_temp = code & LAST_TEMP_MASK; - goto done; - } else { - last_temp2 = code & LAST_TEMP_MASK; - } - - /* Try a third/last time */ - ret = regmap_read(tmdev->map, sensor_addr, &code); - if (ret) - return ret; - if (code & STATUS_VALID_BIT) { - last_temp = code & LAST_TEMP_MASK; - goto done; - } else { - last_temp3 = code & LAST_TEMP_MASK; - } - - if (last_temp == last_temp2) - last_temp = last_temp2; - else if (last_temp2 == last_temp3) - last_temp = last_temp3; -done: - /* Code sign bit is the sign extension for a negative value */ - if (last_temp & CODE_SIGN_BIT) - last_temp |= ~CODE_SIGN_BIT; - - /* Temperatures are in deciCelicius */ - *temp = last_temp * 100; - - return 0; -} - -static const struct tsens_ops ops_8996 = { - .init = init_common, - .get_temp = get_temp_8996, -}; - -const struct tsens_data data_8996 = { - .num_sensors = 13, - .ops = &ops_8996, -}; diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c index b1449ad67fc0..6207d8d92351 100644 --- a/drivers/thermal/qcom/tsens-common.c +++ b/drivers/thermal/qcom/tsens-common.c @@ -16,6 +16,7 @@ #include <linux/io.h> #include <linux/nvmem-consumer.h> #include <linux/of_address.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include "tsens.h" @@ -103,11 +104,11 @@ int get_temp_common(struct tsens_device *tmdev, int id, int *temp) { struct tsens_sensor *s = &tmdev->sensor[id]; u32 code; - unsigned int sensor_addr; + unsigned int status_reg; int last_temp = 0, ret; - sensor_addr = S0_ST_ADDR + s->hw_id * SN_ADDR_OFFSET; - ret = regmap_read(tmdev->map, sensor_addr, &code); + status_reg = S0_ST_ADDR + s->hw_id * SN_ADDR_OFFSET; + ret = regmap_read(tmdev->map, status_reg, &code); if (ret) return ret; last_temp = code & SN_ST_TEMP_MASK; @@ -126,16 +127,28 @@ static const struct regmap_config tsens_config = { int __init init_common(struct tsens_device *tmdev) { void __iomem *base; + struct resource *res; + struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node); - base = of_iomap(tmdev->dev->of_node, 0); - if (!base) + if (!op) return -EINVAL; + /* The driver only uses the TM register address space for now */ + if (op->num_resources > 1) { + tmdev->tm_offset = 0; + } else { + /* old DTs where SROT and TM were in a contiguous 2K block */ + tmdev->tm_offset = 0x1000; + } + + res = platform_get_resource(op, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&op->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + tmdev->map = devm_regmap_init_mmio(tmdev->dev, base, &tsens_config); - if (IS_ERR(tmdev->map)) { - iounmap(base); + if (IS_ERR(tmdev->map)) return PTR_ERR(tmdev->map); - } return 0; } diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c new file mode 100644 index 000000000000..44da02f594ac --- /dev/null +++ b/drivers/thermal/qcom/tsens-v2.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2018, Linaro Limited + */ + +#include <linux/regmap.h> +#include <linux/bitops.h> +#include "tsens.h" + +#define STATUS_OFFSET 0xa0 +#define LAST_TEMP_MASK 0xfff +#define STATUS_VALID_BIT BIT(21) + +static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp) +{ + struct tsens_sensor *s = &tmdev->sensor[id]; + u32 code; + unsigned int status_reg; + u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0; + int ret; + + status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4; + ret = regmap_read(tmdev->map, status_reg, &code); + if (ret) + return ret; + last_temp = code & LAST_TEMP_MASK; + if (code & STATUS_VALID_BIT) + goto done; + + /* Try a second time */ + ret = regmap_read(tmdev->map, status_reg, &code); + if (ret) + return ret; + if (code & STATUS_VALID_BIT) { + last_temp = code & LAST_TEMP_MASK; + goto done; + } else { + last_temp2 = code & LAST_TEMP_MASK; + } + + /* Try a third/last time */ + ret = regmap_read(tmdev->map, status_reg, &code); + if (ret) + return ret; + if (code & STATUS_VALID_BIT) { + last_temp = code & LAST_TEMP_MASK; + goto done; + } else { + last_temp3 = code & LAST_TEMP_MASK; + } + + if (last_temp == last_temp2) + last_temp = last_temp2; + else if (last_temp2 == last_temp3) + last_temp = last_temp3; +done: + /* Convert temperature from deciCelsius to milliCelsius */ + *temp = sign_extend32(last_temp, fls(LAST_TEMP_MASK) - 1) * 100; + + return 0; +} + +static const struct tsens_ops ops_generic_v2 = { + .init = init_common, + .get_temp = get_temp_tsens_v2, +}; + +const struct tsens_data data_tsens_v2 = { + .ops = &ops_generic_v2, +}; + +/* Kept around for backward compatibility with old msm8996.dtsi */ +const struct tsens_data data_8996 = { + .num_sensors = 13, + .ops = &ops_generic_v2, +}; diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 3440166c2ae9..a2c9bfae3d86 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -72,6 +72,9 @@ static const struct of_device_id tsens_table[] = { }, { .compatible = "qcom,msm8996-tsens", .data = &data_8996, + }, { + .compatible = "qcom,tsens-v2", + .data = &data_tsens_v2, }, {} }; diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 911c1978892b..14331eb45a86 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -77,9 +77,8 @@ struct tsens_device { struct device *dev; u32 num_sensors; struct regmap *map; - struct regmap_field *status_field; + u32 tm_offset; struct tsens_context ctx; - bool trdy; const struct tsens_ops *ops; struct tsens_sensor sensor[0]; }; @@ -89,6 +88,9 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32); int init_common(struct tsens_device *); int get_temp_common(struct tsens_device *, int, int *); -extern const struct tsens_data data_8916, data_8974, data_8960, data_8996; +/* TSENS v1 targets */ +extern const struct tsens_data data_8916, data_8974, data_8960; +/* TSENS v2 targets */ +extern const struct tsens_data data_8996, data_tsens_v2; #endif /* __QCOM_TSENS_H__ */ |