From c0f14ec95262cdcf557016f84b87e45f54e0b881 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 9 Mar 2024 14:15:02 +0100 Subject: dt-bindings: thermal: lmh: Add QCM2290 compatible Document the QCM2290 LMH. Signed-off-by: Konrad Dybcio Reviewed-by: Krzysztof Kozlowski Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240308-topic-rb1_lmh-v2-1-bac3914b0fe3@linaro.org --- Documentation/devicetree/bindings/thermal/qcom-lmh.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml b/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml index 5ff72ce5c887..1175bb358382 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml +++ b/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml @@ -17,10 +17,14 @@ description: properties: compatible: - enum: - - qcom,sc8180x-lmh - - qcom,sdm845-lmh - - qcom,sm8150-lmh + oneOf: + - enum: + - qcom,sc8180x-lmh + - qcom,sdm845-lmh + - qcom,sm8150-lmh + - items: + - const: qcom,qcm2290-lmh + - const: qcom,sm8150-lmh reg: items: -- cgit v1.2.3 From d9d3490c48df572edefc0b64655259eefdcbb9be Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 9 Mar 2024 14:15:03 +0100 Subject: thermal/drivers/qcom/lmh: Check for SCM availability at probe Up until now, the necessary scm availability check has not been performed, leading to possible null pointer dereferences (which did happen for me on RB1). Fix that. Fixes: 53bca371cdf7 ("thermal/drivers/qcom: Add support for LMh driver") Cc: Reviewed-by: Dmitry Baryshkov Reviewed-by: Bjorn Andersson Signed-off-by: Konrad Dybcio Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240308-topic-rb1_lmh-v2-2-bac3914b0fe3@linaro.org --- drivers/thermal/qcom/lmh.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/thermal/qcom/lmh.c b/drivers/thermal/qcom/lmh.c index f6edb12ec004..5225b3621a56 100644 --- a/drivers/thermal/qcom/lmh.c +++ b/drivers/thermal/qcom/lmh.c @@ -95,6 +95,9 @@ static int lmh_probe(struct platform_device *pdev) unsigned int enable_alg; u32 node_id; + if (!qcom_scm_is_available()) + return -EPROBE_DEFER; + lmh_data = devm_kzalloc(dev, sizeof(*lmh_data), GFP_KERNEL); if (!lmh_data) return -ENOMEM; -- cgit v1.2.3 From 58b1569244fea51cbf675774fad9423359d76c57 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 20 Mar 2024 11:49:39 +0100 Subject: thermal/drivers/armada: Simplify name sanitization Simplify the code by using the helper we have for doing exactly this. Signed-off-by: Rasmus Villemoes Reviewed-by: Miquel Raynal Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240320104940.65031-1-linux@rasmusvillemoes.dk --- drivers/thermal/armada_thermal.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index f783547ef964..fdcb077cfd54 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -763,7 +763,6 @@ static void armada_set_sane_name(struct platform_device *pdev, struct armada_thermal_priv *priv) { const char *name = dev_name(&pdev->dev); - char *insane_char; if (strlen(name) > THERMAL_NAME_LENGTH) { /* @@ -781,12 +780,8 @@ static void armada_set_sane_name(struct platform_device *pdev, /* Save the name locally */ strscpy(priv->zone_name, name, THERMAL_NAME_LENGTH); - /* Then check there are no '-' or hwmon core will complain */ - do { - insane_char = strpbrk(priv->zone_name, "-"); - if (insane_char) - *insane_char = '_'; - } while (insane_char); + /* Then ensure there are no '-' or hwmon core will complain */ + strreplace(priv->zone_name, '-', '_'); } /* -- cgit v1.2.3 From ff96922d33dfeb3cfe7c4fac051267155722c1ae Mon Sep 17 00:00:00 2001 From: Raphael Gallais-Pou Date: Wed, 20 Mar 2024 22:33:48 +0100 Subject: dt-bindings: thermal: convert st,stih407-thermal to DT schema 'st,passive_colling_temp' does not appear in the device-tree, 'reg' and '#thermal-sensor-cells' are also missing in the device description. Convert st,stih407-thermal binding to DT schema format in order to clean unused 'st,passive_cooling_temp' and add missing properties. Signed-off-by: Raphael Gallais-Pou Reviewed-by: Krzysztof Kozlowski Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240320-thermal-v3-1-700296694c4a@gmail.com --- .../bindings/thermal/st,stih407-thermal.yaml | 58 ++++++++++++++++++++++ .../devicetree/bindings/thermal/st-thermal.txt | 32 ------------ 2 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 Documentation/devicetree/bindings/thermal/st,stih407-thermal.yaml delete mode 100644 Documentation/devicetree/bindings/thermal/st-thermal.txt diff --git a/Documentation/devicetree/bindings/thermal/st,stih407-thermal.yaml b/Documentation/devicetree/bindings/thermal/st,stih407-thermal.yaml new file mode 100644 index 000000000000..9f6fc5c95c55 --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/st,stih407-thermal.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/thermal/st,stih407-thermal.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STi digital thermal sensor (DTS) + +maintainers: + - Patrice Chotard + - Lee Jones + +allOf: + - $ref: thermal-sensor.yaml + +properties: + compatible: + const: st,stih407-thermal + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: thermal + + interrupts: + description: + For thermal sensors for which no interrupt has been defined, a polling + delay of 1000ms will be used to read the temperature from device. + maxItems: 1 + + '#thermal-sensor-cells': + const: 0 + +required: + - compatible + - reg + - clocks + - clock-names + +unevaluatedProperties: false + +examples: + - | + #include + temperature-sensor@91a0000 { + compatible = "st,stih407-thermal"; + reg = <0x91a0000 0x28>; + clock-names = "thermal"; + clocks = <&CLK_SYSIN>; + interrupts = ; + #thermal-sensor-cells = <0>; + }; +... diff --git a/Documentation/devicetree/bindings/thermal/st-thermal.txt b/Documentation/devicetree/bindings/thermal/st-thermal.txt deleted file mode 100644 index a2f939137e35..000000000000 --- a/Documentation/devicetree/bindings/thermal/st-thermal.txt +++ /dev/null @@ -1,32 +0,0 @@ -Binding for Thermal Sensor driver for STMicroelectronics STi series of SoCs. - -Required parameters: -------------------- - -compatible : Should be "st,stih407-thermal" - -clock-names : Should be "thermal". - See: Documentation/devicetree/bindings/resource-names.txt -clocks : Phandle of the clock used by the thermal sensor. - See: Documentation/devicetree/bindings/clock/clock-bindings.txt - -Optional parameters: -------------------- - -reg : For non-sysconf based sensors, this should be the physical base - address and length of the sensor's registers. -interrupts : Standard way to define interrupt number. - NB: For thermal sensor's for which no interrupt has been - defined, a polling delay of 1000ms will be used to read the - temperature from device. - -Example: - - temp0@91a0000 { - compatible = "st,stih407-thermal"; - reg = <0x91a0000 0x28>; - clock-names = "thermal"; - clocks = <&CLK_SYSIN>; - interrupts = ; - st,passive_cooling_temp = <110>; - }; -- cgit v1.2.3 From 34b9a92b6850279145430af181d2d2dedb98cc76 Mon Sep 17 00:00:00 2001 From: Priyansh Jain Date: Thu, 28 Mar 2024 10:32:30 +0530 Subject: thermal/drivers/tsens: Add suspend to RAM support for tsens As part of suspend to RAM, tsens hardware will be turned off. While resume callback, re-initialize tsens hardware. Signed-off-by: Priyansh Jain Acked-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240328050230.31770-1-quic_priyjain@quicinc.com --- drivers/thermal/qcom/tsens-v2.c | 1 + drivers/thermal/qcom/tsens.c | 31 +++++++++++++++++++++++++++++++ drivers/thermal/qcom/tsens.h | 5 +++++ 3 files changed, 37 insertions(+) diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c index 29a61d2d6ca3..0cb7301eca6e 100644 --- a/drivers/thermal/qcom/tsens-v2.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -107,6 +107,7 @@ static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = { static const struct tsens_ops ops_generic_v2 = { .init = init_common, .get_temp = get_temp_tsens_valid, + .resume = tsens_resume_common, }; struct tsens_plat_data data_tsens_v2 = { diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 6d7c16ccb44d..1c9df4f84641 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "../thermal_hwmon.h" #include "tsens.h" @@ -1193,6 +1194,36 @@ static int tsens_register_irq(struct tsens_priv *priv, char *irqname, return ret; } +#ifdef CONFIG_SUSPEND +static int tsens_reinit(struct tsens_priv *priv) +{ + if (tsens_version(priv) >= VER_2_X) { + /* + * Re-enable the watchdog, unmask the bark. + * Disable cycle completion monitoring + */ + if (priv->feat->has_watchdog) { + regmap_field_write(priv->rf[WDOG_BARK_MASK], 0); + regmap_field_write(priv->rf[CC_MON_MASK], 1); + } + + /* Re-enable interrupts */ + tsens_enable_irq(priv); + } + + return 0; +} + +int tsens_resume_common(struct tsens_priv *priv) +{ + if (pm_suspend_target_state == PM_SUSPEND_MEM) + tsens_reinit(priv); + + return 0; +} + +#endif /* !CONFIG_SUSPEND */ + static int tsens_register(struct tsens_priv *priv) { int i, ret; diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index cb637fa289ca..cab39de045b1 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -634,6 +634,11 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mo int init_common(struct tsens_priv *priv); int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp); int get_temp_common(const struct tsens_sensor *s, int *temp); +#ifdef CONFIG_SUSPEND +int tsens_resume_common(struct tsens_priv *priv); +#else +#define tsens_resume_common NULL +#endif /* TSENS target */ extern struct tsens_plat_data data_8960; -- cgit v1.2.3 From 63d96b1253169126a791d6b1b0ef2e708ffb0d75 Mon Sep 17 00:00:00 2001 From: Dmitry Rokosov Date: Thu, 28 Mar 2024 22:13:10 +0300 Subject: dt-bindings: thermal: amlogic: add support for A1 thermal sensor Provide right compatible properties for Amlogic A1 Thermal Sensor controller. A1 family supports only one thermal node - CPU thermal sensor. Signed-off-by: Dmitry Rokosov Acked-by: Conor Dooley Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240328191322.17551-2-ddrokosov@salutedevices.com --- .../devicetree/bindings/thermal/amlogic,thermal.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml b/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml index 20f8f9b3b971..01fccdfc4178 100644 --- a/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml @@ -13,11 +13,13 @@ description: Binding for Amlogic Thermal properties: compatible: - items: - - enum: - - amlogic,g12a-cpu-thermal - - amlogic,g12a-ddr-thermal - - const: amlogic,g12a-thermal + oneOf: + - items: + - enum: + - amlogic,g12a-cpu-thermal + - amlogic,g12a-ddr-thermal + - const: amlogic,g12a-thermal + - const: amlogic,a1-cpu-thermal reg: maxItems: 1 -- cgit v1.2.3 From 7fcd7dfa5ec29afe0b3fe8ad6a5f42c19e71d6be Mon Sep 17 00:00:00 2001 From: Dmitry Rokosov Date: Thu, 28 Mar 2024 22:13:11 +0300 Subject: thermal/drivers/amlogic: Support A1 SoC family Thermal Sensor controller In comparison to other Amlogic chips, there is one key difference. The offset for the sec_ao base, also known as u_efuse_off, is special, while other aspects remain the same. Signed-off-by: Dmitry Rokosov Reviewed-by: Neil Armstrong Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240328191322.17551-3-ddrokosov@salutedevices.com --- drivers/thermal/amlogic_thermal.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/thermal/amlogic_thermal.c b/drivers/thermal/amlogic_thermal.c index df7a5ed55385..cd4776aa805e 100644 --- a/drivers/thermal/amlogic_thermal.c +++ b/drivers/thermal/amlogic_thermal.c @@ -220,6 +220,12 @@ static const struct amlogic_thermal_data amlogic_thermal_g12a_ddr_param = { .regmap_config = &amlogic_thermal_regmap_config_g12a, }; +static const struct amlogic_thermal_data amlogic_thermal_a1_cpu_param = { + .u_efuse_off = 0x114, + .calibration_parameters = &amlogic_thermal_g12a, + .regmap_config = &amlogic_thermal_regmap_config_g12a, +}; + static const struct of_device_id of_amlogic_thermal_match[] = { { .compatible = "amlogic,g12a-ddr-thermal", @@ -229,6 +235,10 @@ static const struct of_device_id of_amlogic_thermal_match[] = { .compatible = "amlogic,g12a-cpu-thermal", .data = &amlogic_thermal_g12a_cpu_param, }, + { + .compatible = "amlogic,a1-cpu-thermal", + .data = &amlogic_thermal_a1_cpu_param, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, of_amlogic_thermal_match); -- cgit v1.2.3 From 566e0ea7d02ff596d7bcd81ca547e91b5074032f Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Wed, 27 Mar 2024 14:30:12 +0100 Subject: thermal/drivers/rcar_gen3: Move Tj_T storage to shared private data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The calculated Tj_T constant is calculated from the PTAT data either read from the first TSC zone on the device if calibration data is fused, or from fallback values in the driver itself. The value calculated is shared among all TSC zones. Move the Tj_T constant to the shared private data structure instead of duplicating it in each TSC private data. This requires adding a pointer to the shared data to the TSC private data structure. This back pointer make it easier to further rework the temperature conversion logic. Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240327133013.3982199-2-niklas.soderlund+renesas@ragnatech.se --- drivers/thermal/rcar_gen3_thermal.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index a764cb1115a5..7c1ca912b9b1 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -81,10 +81,10 @@ struct rcar_thermal_info { }; struct rcar_gen3_thermal_tsc { + struct rcar_gen3_thermal_priv *priv; void __iomem *base; struct thermal_zone_device *zone; struct equation_coefs coef; - int tj_t; int thcode[3]; }; @@ -93,6 +93,7 @@ struct rcar_gen3_thermal_priv { struct thermal_zone_device_ops ops; unsigned int num_tscs; int ptat[3]; + int tj_t; const struct rcar_thermal_info *info; }; @@ -136,26 +137,32 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc, /* no idea where these constants come from */ #define TJ_3 -41 -static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_priv *priv, - struct rcar_gen3_thermal_tsc *tsc, - int ths_tj_1) +static void rcar_gen3_thermal_shared_coefs(struct rcar_gen3_thermal_priv *priv) +{ + int tj1 = priv->info->ths_tj_1; + + priv->tj_t = (FIXPT_INT((priv->ptat[1] - priv->ptat[2]) * (tj1 - TJ_3)) + / (priv->ptat[0] - priv->ptat[2])) + FIXPT_INT(TJ_3); +} + +static void rcar_gen3_thermal_tsc_coefs(struct rcar_gen3_thermal_priv *priv, + struct rcar_gen3_thermal_tsc *tsc) { + int tj1 = priv->info->ths_tj_1; + /* TODO: Find documentation and document constant calculation formula */ /* * 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((priv->ptat[1] - priv->ptat[2]) * (ths_tj_1 - TJ_3)) - / (priv->ptat[0] - priv->ptat[2])) + FIXPT_INT(TJ_3); - tsc->coef.a1 = FIXPT_DIV(FIXPT_INT(tsc->thcode[1] - tsc->thcode[2]), - tsc->tj_t - FIXPT_INT(TJ_3)); + priv->tj_t - FIXPT_INT(TJ_3)); tsc->coef.b1 = FIXPT_INT(tsc->thcode[2]) - tsc->coef.a1 * TJ_3; tsc->coef.a2 = FIXPT_DIV(FIXPT_INT(tsc->thcode[1] - tsc->thcode[0]), - tsc->tj_t - FIXPT_INT(ths_tj_1)); - tsc->coef.b2 = FIXPT_INT(tsc->thcode[0]) - tsc->coef.a2 * ths_tj_1; + priv->tj_t - FIXPT_INT(tj1)); + tsc->coef.b2 = FIXPT_INT(tsc->thcode[0]) - tsc->coef.a2 * tj1; } static int rcar_gen3_thermal_round(int temp) @@ -196,10 +203,11 @@ static int rcar_gen3_thermal_get_temp(struct thermal_zone_device *tz, int *temp) static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc, int mcelsius) { + struct rcar_gen3_thermal_priv *priv = tsc->priv; int celsius, val; celsius = DIV_ROUND_CLOSEST(mcelsius, 1000); - if (celsius <= INT_FIXPT(tsc->tj_t)) + if (celsius <= INT_FIXPT(priv->tj_t)) val = celsius * tsc->coef.a1 + tsc->coef.b1; else val = celsius * tsc->coef.a2 + tsc->coef.b2; @@ -516,6 +524,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) goto error_unregister; } + tsc->priv = priv; tsc->base = devm_ioremap_resource(dev, res); if (IS_ERR(tsc->base)) { ret = PTR_ERR(tsc->base); @@ -530,11 +539,13 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) if (!rcar_gen3_thermal_read_fuses(priv)) dev_info(dev, "No calibration values fused, fallback to driver values\n"); + rcar_gen3_thermal_shared_coefs(priv); + for (i = 0; i < priv->num_tscs; i++) { struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; rcar_gen3_thermal_init(priv, tsc); - rcar_gen3_thermal_calc_coefs(priv, tsc, priv->info->ths_tj_1); + rcar_gen3_thermal_tsc_coefs(priv, tsc); zone = devm_thermal_of_zone_register(dev, i, tsc, &priv->ops); if (IS_ERR(zone)) { -- cgit v1.2.3 From 63d23fb78140a882e268201ff730453cd8b4f8e8 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Wed, 27 Mar 2024 14:30:13 +0100 Subject: thermal/drivers/rcar_gen3: Update temperature approximation calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initial driver used a formula to approximate the temperature and register values reversed engineered from an out-of-tree BSP driver. This was needed as the datasheet at the time did not contain any information on how to do this. Later Gen3 (Rev 2.30) and Gen4 (all) now contains this information. Update the approximation formula to use the datasheet's information instead of the reversed-engineered one. On an idle M3-N without fused calibration values for PTAT and THCODE the old formula reports, zone0: 52000 zone1: 53000 zone2: 52500 While the new formula under the same circumstances reports, zone0: 52500 zone1: 54000 zone2: 54000 Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240327133013.3982199-3-niklas.soderlund+renesas@ragnatech.se --- drivers/thermal/rcar_gen3_thermal.c | 156 ++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 7c1ca912b9b1..02494fa142c3 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -65,26 +65,29 @@ #define TSC_MAX_NUM 5 -/* Structure for thermal temperature calculation */ -struct equation_coefs { - int a1; - int b1; - int a2; - int b2; -}; - struct rcar_gen3_thermal_priv; struct rcar_thermal_info { - int ths_tj_1; + int scale; + int adj_below; + int adj_above; void (*read_fuses)(struct rcar_gen3_thermal_priv *priv); }; +struct equation_set_coef { + int a; + int b; +}; + struct rcar_gen3_thermal_tsc { struct rcar_gen3_thermal_priv *priv; void __iomem *base; struct thermal_zone_device *zone; - struct equation_coefs coef; + /* Different coefficients are used depending on a threshold. */ + struct { + struct equation_set_coef below; + struct equation_set_coef above; + } coef; int thcode[3]; }; @@ -112,90 +115,75 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc, /* * Linear approximation for temperature * - * [reg] = [temp] * a + b => [temp] = ([reg] - b) / a + * [temp] = ((thadj - [reg]) * a) / b + adj + * [reg] = thadj - ([temp] - adj) * b / a * * The constants a and b are calculated using two triplets of int values PTAT * and THCODE. PTAT and THCODE can either be read from hardware or use hard - * coded values from driver. The formula to calculate a and b are taken from - * BSP and sparsely documented and understood. + * coded values from the driver. The formula to calculate a and b are taken from + * the datasheet. Different calculations are needed for a and b depending on + * if the input variables ([temp] or [reg]) are above or below a threshold. The + * threshold is also calculated from PTAT and THCODE using formulas from the + * datasheet. + * + * The constant thadj is one of the THCODE values, which one to use depends on + * the threshold and input value. * - * Examining the linear formula and the formula used to calculate constants a - * and b while knowing that the span for PTAT and THCODE values are between - * 0x000 and 0xfff the largest integer possible is 0xfff * 0xfff == 0xffe001. - * Integer also needs to be signed so that leaves 7 bits for binary - * fixed point scaling. + * The constants adj is taken verbatim from the datasheet. Two values exists, + * which one to use depends on the input value and the calculated threshold. + * Furthermore different SoC models supported by the driver have different sets + * of values. The values for each model are stored in the device match data. */ -#define FIXPT_SHIFT 7 -#define FIXPT_INT(_x) ((_x) << FIXPT_SHIFT) -#define INT_FIXPT(_x) ((_x) >> FIXPT_SHIFT) -#define FIXPT_DIV(_a, _b) DIV_ROUND_CLOSEST(((_a) << FIXPT_SHIFT), (_b)) -#define FIXPT_TO_MCELSIUS(_x) ((_x) * 1000 >> FIXPT_SHIFT) - -#define RCAR3_THERMAL_GRAN 500 /* mili Celsius */ - -/* no idea where these constants come from */ -#define TJ_3 -41 - static void rcar_gen3_thermal_shared_coefs(struct rcar_gen3_thermal_priv *priv) { - int tj1 = priv->info->ths_tj_1; - - priv->tj_t = (FIXPT_INT((priv->ptat[1] - priv->ptat[2]) * (tj1 - TJ_3)) - / (priv->ptat[0] - priv->ptat[2])) + FIXPT_INT(TJ_3); + priv->tj_t = + DIV_ROUND_CLOSEST((priv->ptat[1] - priv->ptat[2]) * priv->info->scale, + priv->ptat[0] - priv->ptat[2]) + + priv->info->adj_below; } - static void rcar_gen3_thermal_tsc_coefs(struct rcar_gen3_thermal_priv *priv, struct rcar_gen3_thermal_tsc *tsc) { - int tj1 = priv->info->ths_tj_1; - - /* TODO: Find documentation and document constant calculation formula */ - - /* - * Division is not scaled in BSP and if scaled it might overflow - * the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled - */ - tsc->coef.a1 = FIXPT_DIV(FIXPT_INT(tsc->thcode[1] - tsc->thcode[2]), - priv->tj_t - FIXPT_INT(TJ_3)); - tsc->coef.b1 = FIXPT_INT(tsc->thcode[2]) - tsc->coef.a1 * TJ_3; - - tsc->coef.a2 = FIXPT_DIV(FIXPT_INT(tsc->thcode[1] - tsc->thcode[0]), - priv->tj_t - FIXPT_INT(tj1)); - tsc->coef.b2 = FIXPT_INT(tsc->thcode[0]) - tsc->coef.a2 * tj1; -} - -static int rcar_gen3_thermal_round(int temp) -{ - int result, round_offs; + tsc->coef.below.a = priv->info->scale * (priv->ptat[2] - priv->ptat[1]); + tsc->coef.above.a = priv->info->scale * (priv->ptat[0] - priv->ptat[1]); - round_offs = temp >= 0 ? RCAR3_THERMAL_GRAN / 2 : - -RCAR3_THERMAL_GRAN / 2; - result = (temp + round_offs) / RCAR3_THERMAL_GRAN; - return result * RCAR3_THERMAL_GRAN; + tsc->coef.below.b = (priv->ptat[2] - priv->ptat[0]) * (tsc->thcode[2] - tsc->thcode[1]); + tsc->coef.above.b = (priv->ptat[0] - priv->ptat[2]) * (tsc->thcode[1] - tsc->thcode[0]); } static int rcar_gen3_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { struct rcar_gen3_thermal_tsc *tsc = thermal_zone_device_priv(tz); - int mcelsius, val; - int reg; + struct rcar_gen3_thermal_priv *priv = tsc->priv; + const struct equation_set_coef *coef; + int adj, decicelsius, reg, thcode; /* Read register and convert to mili Celsius */ reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK; - if (reg <= tsc->thcode[1]) - val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, - tsc->coef.a1); - else - val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b2, - tsc->coef.a2); - mcelsius = FIXPT_TO_MCELSIUS(val); + if (reg < tsc->thcode[1]) { + adj = priv->info->adj_below; + coef = &tsc->coef.below; + thcode = tsc->thcode[2]; + } else { + adj = priv->info->adj_above; + coef = &tsc->coef.above; + thcode = tsc->thcode[0]; + } + + /* + * The dividend can't be grown as it might overflow, instead shorten the + * divisor to convert to decidegree Celsius. If we convert after the + * division precision is lost as we will scale up from whole degrees + * Celsius. + */ + decicelsius = DIV_ROUND_CLOSEST(coef->a * (thcode - reg), coef->b / 10); /* Guaranteed operating range is -40C to 125C. */ - /* Round value to device granularity setting */ - *temp = rcar_gen3_thermal_round(mcelsius); + /* Reporting is done in millidegree Celsius */ + *temp = decicelsius * 100 + adj * 1000; return 0; } @@ -204,15 +192,21 @@ static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc, int mcelsius) { struct rcar_gen3_thermal_priv *priv = tsc->priv; - int celsius, val; + const struct equation_set_coef *coef; + int adj, celsius, thcode; celsius = DIV_ROUND_CLOSEST(mcelsius, 1000); - if (celsius <= INT_FIXPT(priv->tj_t)) - val = celsius * tsc->coef.a1 + tsc->coef.b1; - else - val = celsius * tsc->coef.a2 + tsc->coef.b2; + if (celsius < priv->tj_t) { + coef = &tsc->coef.below; + adj = priv->info->adj_below; + thcode = tsc->thcode[2]; + } else { + coef = &tsc->coef.above; + adj = priv->info->adj_above; + thcode = tsc->thcode[0]; + } - return INT_FIXPT(val); + return thcode - DIV_ROUND_CLOSEST((celsius - adj) * coef->b, coef->a); } static int rcar_gen3_thermal_set_trips(struct thermal_zone_device *tz, int low, int high) @@ -377,17 +371,23 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv, } static const struct rcar_thermal_info rcar_m3w_thermal_info = { - .ths_tj_1 = 116, + .scale = 157, + .adj_below = -41, + .adj_above = 116, .read_fuses = rcar_gen3_thermal_read_fuses_gen3, }; static const struct rcar_thermal_info rcar_gen3_thermal_info = { - .ths_tj_1 = 126, + .scale = 167, + .adj_below = -41, + .adj_above = 126, .read_fuses = rcar_gen3_thermal_read_fuses_gen3, }; static const struct rcar_thermal_info rcar_gen4_thermal_info = { - .ths_tj_1 = 126, + .scale = 167, + .adj_below = -41, + .adj_above = 126, .read_fuses = rcar_gen3_thermal_read_fuses_gen4, }; -- cgit v1.2.3 From 7954c92ede882b0dfd52a5db90291a4151b44c1a Mon Sep 17 00:00:00 2001 From: Hsin-Te Yuan Date: Tue, 16 Apr 2024 07:35:47 +0000 Subject: thermal/drivers/mediatek/lvts_thermal: Add coeff for mt8192 In order for lvts_raw_to_temp to function properly on mt8192, temperature coefficients for mt8192 need to be added. Fixes: 288732242db4 ("thermal/drivers/mediatek/lvts_thermal: Add mt8192 support") Signed-off-by: Hsin-Te Yuan Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240416-lvts_thermal-v2-1-f8a36882cc53@chromium.org --- drivers/thermal/mediatek/lvts_thermal.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index fd4bd650c77a..4e5c213a8922 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -1530,11 +1530,15 @@ static const struct lvts_data mt7988_lvts_ap_data = { static const struct lvts_data mt8192_lvts_mcu_data = { .lvts_ctrl = mt8192_lvts_mcu_data_ctrl, .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT8195, + .temp_offset = LVTS_COEFF_B_MT8195, }; static const struct lvts_data mt8192_lvts_ap_data = { .lvts_ctrl = mt8192_lvts_ap_data_ctrl, .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_ap_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT8195, + .temp_offset = LVTS_COEFF_B_MT8195, }; static const struct lvts_data mt8195_lvts_mcu_data = { -- cgit v1.2.3 From d998ddc86a27c92140b9f7984ff41e3d1d07a48f Mon Sep 17 00:00:00 2001 From: Aleksandr Mishin Date: Thu, 11 Apr 2024 14:40:21 +0300 Subject: thermal/drivers/tsens: Fix null pointer dereference compute_intercept_slope() is called from calibrate_8960() (in tsens-8960.c) as compute_intercept_slope(priv, p1, NULL, ONE_PT_CALIB) which lead to null pointer dereference (if DEBUG or DYNAMIC_DEBUG set). Fix this bug by adding null pointer check. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: dfc1193d4dbd ("thermal/drivers/tsens: Replace custom 8960 apis with generic apis") Signed-off-by: Aleksandr Mishin Reviewed-by: Konrad Dybcio Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240411114021.12203-1-amishin@t-argos.ru --- drivers/thermal/qcom/tsens.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 1c9df4f84641..e76e23026dc8 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -265,7 +265,7 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1, for (i = 0; i < priv->num_sensors; i++) { dev_dbg(priv->dev, "%s: sensor%d - data_point1:%#x data_point2:%#x\n", - __func__, i, p1[i], p2[i]); + __func__, i, p1[i], p2 ? p2[i] : 0); if (!priv->sensor[i].slope) priv->sensor[i].slope = SLOPE_DEFAULT; -- cgit v1.2.3 From 0a0c8db8843c5d5e22e2ee275c35d6ecd0659414 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 9 Apr 2024 21:56:34 +0200 Subject: thermal/drivers/qcom: Remove some unused fields in struct qpnp_tm_chip In "struct qpnp_tm_chip", the 'prev_stage' field is unused. Remove it. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Reviewed-by: Bjorn Andersson Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/d1c3a3c455f485dae46290e3488daf1dcc1d355a.1712687589.git.christophe.jaillet@wanadoo.fr --- drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c index 78c5cfe6a0c0..3cd74f6cac8f 100644 --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c @@ -74,7 +74,6 @@ struct qpnp_tm_chip { long temp; unsigned int thresh; unsigned int stage; - unsigned int prev_stage; unsigned int base; /* protects .thresh, .stage and chip registers */ struct mutex lock; -- cgit v1.2.3 From 61fad0a90685d3aaafb05fb6abc1fe39fbb90320 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 9 Apr 2024 21:56:43 +0200 Subject: thermal/drivers/k3_bandgap: Remove some unused fields in struct k3_bandgap In "struct k3_bandgap", the 'conf' field is unused. Remove it. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/206d39bed9ec6df9b4d80b1fc064e499389fc7fc.1712687420.git.christophe.jaillet@wanadoo.fr --- drivers/thermal/k3_bandgap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/thermal/k3_bandgap.c b/drivers/thermal/k3_bandgap.c index e88192d2afea..2a703770fc91 100644 --- a/drivers/thermal/k3_bandgap.c +++ b/drivers/thermal/k3_bandgap.c @@ -78,7 +78,6 @@ static const int k3_adc_to_temp[] = { struct k3_bandgap { void __iomem *base; - const struct k3_bandgap_data *conf; }; /* common data structures */ -- cgit v1.2.3 From 8c25958f71d8c173b81cb422a44c5743beb76af7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:35 -0400 Subject: thermal/drivers/mediatek/lvts_thermal: Retrieve all calibration bytes Calibration values are 24-bit wide. Those values so far appear to span only 16 bits but let's not push our luck. Found while looking at the original Mediatek driver code. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-2-nico@fluxnic.net --- drivers/thermal/mediatek/lvts_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 4e5c213a8922..d26662608b4c 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -679,7 +679,7 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) memcpy(&lvts_ctrl->calibration[i], - efuse_calibration + lvts_ctrl_data->cal_offset[i], 2); + efuse_calibration + lvts_ctrl_data->cal_offset[i], 3); return 0; } -- cgit v1.2.3 From 62194e637d16ac9b61eec0bfe6d5f662efcddbe7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:36 -0400 Subject: thermal/drivers/mediatek/lvts_thermal: Move comment Move efuse data interpretation inside lvts_golden_temp_init() alongside the actual code retrieving wanted value. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-3-nico@fluxnic.net --- drivers/thermal/mediatek/lvts_thermal.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index d26662608b4c..040116228850 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -734,11 +734,15 @@ static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td return 0; } -static int lvts_golden_temp_init(struct device *dev, u32 *value, int temp_offset) +static int lvts_golden_temp_init(struct device *dev, u8 *calib, int temp_offset) { u32 gt; - gt = (*value) >> 24; + /* + * The golden temp information is contained in the 4th byte (index = 3) + * of efuse data. + */ + gt = calib[3]; if (gt && gt < LVTS_GOLDEN_TEMP_MAX) golden_temp = gt; @@ -762,11 +766,7 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, if (ret) return ret; - /* - * The golden temp information is contained in the first chunk - * of efuse data. - */ - ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib, lvts_data->temp_offset); + ret = lvts_golden_temp_init(dev, lvts_td->calib, lvts_data->temp_offset); if (ret) return ret; -- cgit v1.2.3 From 554bca31308ab8234bac505d0b86d9082b549a40 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:37 -0400 Subject: thermal/drivers/mediatek/lvts_thermal: Remove .hw_tshut_temp All the .hw_tshut_temp instances are initialized with the same value. Let's remove those and use a common definition instead. If ever a different value must be used in the future then an override parameter could be added back. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-4-nico@fluxnic.net --- drivers/thermal/mediatek/lvts_thermal.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 040116228850..08cf379d433b 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -91,9 +91,7 @@ #define LVTS_MSR_READ_TIMEOUT_US 400 #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) -#define LVTS_HW_SHUTDOWN_MT7988 105000 -#define LVTS_HW_SHUTDOWN_MT8192 105000 -#define LVTS_HW_SHUTDOWN_MT8195 105000 +#define LVTS_HW_TSHUT_TEMP 105000 #define LVTS_MINIMUM_THRESHOLD 20000 @@ -107,7 +105,6 @@ struct lvts_sensor_data { struct lvts_ctrl_data { struct lvts_sensor_data lvts_sensor[LVTS_SENSOR_MAX]; int cal_offset[LVTS_SENSOR_MAX]; - int hw_tshut_temp; int num_lvts_sensor; int offset; int mode; @@ -801,7 +798,7 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, * after initializing the calibration. */ lvts_ctrl[i].hw_tshut_raw_temp = - lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp, + lvts_temp_to_raw(LVTS_HW_TSHUT_TEMP, lvts_data->temp_factor); lvts_ctrl[i].low_thresh = INT_MIN; @@ -1311,7 +1308,6 @@ static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 4, .offset = 0x0, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988, }, { .cal_offset = { 0x14, 0x18, 0x1c, 0x20 }, @@ -1323,7 +1319,6 @@ static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 4, .offset = 0x100, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988, } }; @@ -1368,7 +1363,6 @@ static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x0, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, .mode = LVTS_MSR_FILTERED_MODE, }, { @@ -1379,7 +1373,6 @@ static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x100, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, .mode = LVTS_MSR_FILTERED_MODE, }, { @@ -1392,7 +1385,6 @@ static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { }, .num_lvts_sensor = 4, .offset = 0x200, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, .mode = LVTS_MSR_FILTERED_MODE, } }; @@ -1406,7 +1398,6 @@ static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x0, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, }, { .cal_offset = { 0x2c, 0x30 }, @@ -1416,7 +1407,6 @@ static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x100, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, }, { .cal_offset = { 0x34, 0x38 }, @@ -1426,7 +1416,6 @@ static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x200, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, }, { .cal_offset = { 0x3c, 0x40, 0x44 }, @@ -1437,7 +1426,6 @@ static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 3, .offset = 0x300, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, } }; @@ -1450,7 +1438,6 @@ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x0, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, }, { .cal_offset = { 0x0d, 0x10 }, @@ -1460,7 +1447,6 @@ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x100, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, }, { .cal_offset = { 0x16, 0x19, 0x1c, 0x1f }, @@ -1472,7 +1458,6 @@ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { }, .num_lvts_sensor = 4, .offset = 0x200, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, } }; @@ -1485,7 +1470,6 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x0, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, }, { .cal_offset = { 0x2e, 0x31 }, @@ -1495,7 +1479,6 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x100, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, }, { .cal_offset = { 0x37, 0x3a, 0x3d }, @@ -1506,7 +1489,6 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 3, .offset = 0x200, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, }, { .cal_offset = { 0x43, 0x46 }, @@ -1516,7 +1498,6 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { }, .num_lvts_sensor = 2, .offset = 0x300, - .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, } }; -- cgit v1.2.3 From 5b3367e28a2c47d74bd566b96854ef0de3caa6d7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:38 -0400 Subject: thermal/drivers/mediatek/lvts_thermal: Use offsets for every calibration byte Current code assumes calibration values are always stored contiguously in host endian order. A future patch will prove this wrong. Let's specify the offset for each calibration byte instead. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-5-nico@fluxnic.net --- drivers/thermal/mediatek/lvts_thermal.c | 164 +++++++++++++++++++------------- 1 file changed, 99 insertions(+), 65 deletions(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 08cf379d433b..9e6ed8bf6d9a 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -100,6 +100,7 @@ static int golden_temp_offset; struct lvts_sensor_data { int dt_id; + u8 cal_offsets[3]; }; struct lvts_ctrl_data { @@ -665,8 +666,9 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, * <-----ap--tc#3-----> <-----sensor#7-----> <-----sensor#8-----> * 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 | 0x48 * - * The data description gives the offset of the calibration data in - * this bytes stream for each sensor. + * Note: In some cases, values don't strictly follow a little endian ordering. + * The data description gives byte offsets constituting each calibration value + * for each sensor. */ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, const struct lvts_ctrl_data *lvts_ctrl_data, @@ -674,9 +676,15 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl { int i; - for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) - memcpy(&lvts_ctrl->calibration[i], - efuse_calibration + lvts_ctrl_data->cal_offset[i], 3); + for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) { + const struct lvts_sensor_data *sensor = + &lvts_ctrl_data->lvts_sensor[i]; + + lvts_ctrl->calibration[i] = + (efuse_calibration[sensor->cal_offsets[0]] << 0) + + (efuse_calibration[sensor->cal_offsets[1]] << 8) + + (efuse_calibration[sensor->cal_offsets[2]] << 16); + } return 0; } @@ -1299,23 +1307,29 @@ static void lvts_remove(struct platform_device *pdev) static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { { - .cal_offset = { 0x00, 0x04, 0x08, 0x0c }, .lvts_sensor = { - { .dt_id = MT7988_CPU_0 }, - { .dt_id = MT7988_CPU_1 }, - { .dt_id = MT7988_ETH2P5G_0 }, - { .dt_id = MT7988_ETH2P5G_1 } + { .dt_id = MT7988_CPU_0, + .cal_offsets = { 0x00, 0x01, 0x02 } }, + { .dt_id = MT7988_CPU_1, + .cal_offsets = { 0x04, 0x05, 0x06 } }, + { .dt_id = MT7988_ETH2P5G_0, + .cal_offsets = { 0x08, 0x09, 0x0a } }, + { .dt_id = MT7988_ETH2P5G_1, + .cal_offsets = { 0x0c, 0x0d, 0x0e } } }, .num_lvts_sensor = 4, .offset = 0x0, }, { - .cal_offset = { 0x14, 0x18, 0x1c, 0x20 }, .lvts_sensor = { - { .dt_id = MT7988_TOPS_0}, - { .dt_id = MT7988_TOPS_1}, - { .dt_id = MT7988_ETHWARP_0}, - { .dt_id = MT7988_ETHWARP_1} + { .dt_id = MT7988_TOPS_0, + .cal_offsets = { 0x14, 0x15, 0x16 } }, + { .dt_id = MT7988_TOPS_1, + .cal_offsets = { 0x18, 0x19, 0x1a } }, + { .dt_id = MT7988_ETHWARP_0, + .cal_offsets = { 0x1c, 0x1d, 0x1e } }, + { .dt_id = MT7988_ETHWARP_1, + .cal_offsets = { 0x20, 0x21, 0x22 } } }, .num_lvts_sensor = 4, .offset = 0x100, @@ -1356,32 +1370,37 @@ static int lvts_resume(struct device *dev) static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { { - .cal_offset = { 0x04, 0x08 }, .lvts_sensor = { - { .dt_id = MT8192_MCU_BIG_CPU0 }, - { .dt_id = MT8192_MCU_BIG_CPU1 } + { .dt_id = MT8192_MCU_BIG_CPU0, + .cal_offsets = { 0x04, 0x05, 0x06 } }, + { .dt_id = MT8192_MCU_BIG_CPU1, + .cal_offsets = { 0x08, 0x09, 0x0a } } }, .num_lvts_sensor = 2, .offset = 0x0, .mode = LVTS_MSR_FILTERED_MODE, }, { - .cal_offset = { 0x0c, 0x10 }, .lvts_sensor = { - { .dt_id = MT8192_MCU_BIG_CPU2 }, - { .dt_id = MT8192_MCU_BIG_CPU3 } + { .dt_id = MT8192_MCU_BIG_CPU2, + .cal_offsets = { 0x0c, 0x0d, 0x0e } }, + { .dt_id = MT8192_MCU_BIG_CPU3, + .cal_offsets = { 0x10, 0x11, 0x12 } } }, .num_lvts_sensor = 2, .offset = 0x100, .mode = LVTS_MSR_FILTERED_MODE, }, { - .cal_offset = { 0x14, 0x18, 0x1c, 0x20 }, .lvts_sensor = { - { .dt_id = MT8192_MCU_LITTLE_CPU0 }, - { .dt_id = MT8192_MCU_LITTLE_CPU1 }, - { .dt_id = MT8192_MCU_LITTLE_CPU2 }, - { .dt_id = MT8192_MCU_LITTLE_CPU3 } + { .dt_id = MT8192_MCU_LITTLE_CPU0, + .cal_offsets = { 0x14, 0x15, 0x16 } }, + { .dt_id = MT8192_MCU_LITTLE_CPU1, + .cal_offsets = { 0x18, 0x19, 0x1a } }, + { .dt_id = MT8192_MCU_LITTLE_CPU2, + .cal_offsets = { 0x1c, 0x1d, 0x1e } }, + { .dt_id = MT8192_MCU_LITTLE_CPU3, + .cal_offsets = { 0x20, 0x21, 0x22 } } }, .num_lvts_sensor = 4, .offset = 0x200, @@ -1390,39 +1409,44 @@ static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { }; static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { - { - .cal_offset = { 0x24, 0x28 }, + { .lvts_sensor = { - { .dt_id = MT8192_AP_VPU0 }, - { .dt_id = MT8192_AP_VPU1 } + { .dt_id = MT8192_AP_VPU0, + .cal_offsets = { 0x24, 0x25, 0x26 } }, + { .dt_id = MT8192_AP_VPU1, + .cal_offsets = { 0x28, 0x29, 0x2a } } }, .num_lvts_sensor = 2, .offset = 0x0, }, { - .cal_offset = { 0x2c, 0x30 }, .lvts_sensor = { - { .dt_id = MT8192_AP_GPU0 }, - { .dt_id = MT8192_AP_GPU1 } + { .dt_id = MT8192_AP_GPU0, + .cal_offsets = { 0x2c, 0x2d, 0x2e } }, + { .dt_id = MT8192_AP_GPU1, + .cal_offsets = { 0x30, 0x31, 0x32 } } }, .num_lvts_sensor = 2, .offset = 0x100, }, { - .cal_offset = { 0x34, 0x38 }, .lvts_sensor = { - { .dt_id = MT8192_AP_INFRA }, - { .dt_id = MT8192_AP_CAM }, + { .dt_id = MT8192_AP_INFRA, + .cal_offsets = { 0x34, 0x35, 0x36 } }, + { .dt_id = MT8192_AP_CAM, + .cal_offsets = { 0x38, 0x39, 0x3a } }, }, .num_lvts_sensor = 2, .offset = 0x200, }, { - .cal_offset = { 0x3c, 0x40, 0x44 }, .lvts_sensor = { - { .dt_id = MT8192_AP_MD0 }, - { .dt_id = MT8192_AP_MD1 }, - { .dt_id = MT8192_AP_MD2 } + { .dt_id = MT8192_AP_MD0, + .cal_offsets = { 0x3c, 0x3d, 0x3e } }, + { .dt_id = MT8192_AP_MD1, + .cal_offsets = { 0x40, 0x41, 0x42 } }, + { .dt_id = MT8192_AP_MD2, + .cal_offsets = { 0x44, 0x45, 0x46 } } }, .num_lvts_sensor = 3, .offset = 0x300, @@ -1431,30 +1455,35 @@ static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { { - .cal_offset = { 0x04, 0x07 }, .lvts_sensor = { - { .dt_id = MT8195_MCU_BIG_CPU0 }, - { .dt_id = MT8195_MCU_BIG_CPU1 } + { .dt_id = MT8195_MCU_BIG_CPU0, + .cal_offsets = { 0x04, 0x05, 0x06 } }, + { .dt_id = MT8195_MCU_BIG_CPU1, + .cal_offsets = { 0x07, 0x08, 0x09 } } }, .num_lvts_sensor = 2, .offset = 0x0, }, { - .cal_offset = { 0x0d, 0x10 }, .lvts_sensor = { - { .dt_id = MT8195_MCU_BIG_CPU2 }, - { .dt_id = MT8195_MCU_BIG_CPU3 } + { .dt_id = MT8195_MCU_BIG_CPU2, + .cal_offsets = { 0x0d, 0x0e, 0x0f } }, + { .dt_id = MT8195_MCU_BIG_CPU3, + .cal_offsets = { 0x10, 0x11, 0x12 } } }, .num_lvts_sensor = 2, .offset = 0x100, }, { - .cal_offset = { 0x16, 0x19, 0x1c, 0x1f }, .lvts_sensor = { - { .dt_id = MT8195_MCU_LITTLE_CPU0 }, - { .dt_id = MT8195_MCU_LITTLE_CPU1 }, - { .dt_id = MT8195_MCU_LITTLE_CPU2 }, - { .dt_id = MT8195_MCU_LITTLE_CPU3 } + { .dt_id = MT8195_MCU_LITTLE_CPU0, + .cal_offsets = { 0x16, 0x17, 0x18 } }, + { .dt_id = MT8195_MCU_LITTLE_CPU1, + .cal_offsets = { 0x19, 0x1a, 0x1b } }, + { .dt_id = MT8195_MCU_LITTLE_CPU2, + .cal_offsets = { 0x1c, 0x1d, 0x1e } }, + { .dt_id = MT8195_MCU_LITTLE_CPU3, + .cal_offsets = { 0x1f, 0x20, 0x21 } } }, .num_lvts_sensor = 4, .offset = 0x200, @@ -1462,39 +1491,44 @@ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { }; static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { - { - .cal_offset = { 0x25, 0x28 }, + { .lvts_sensor = { - { .dt_id = MT8195_AP_VPU0 }, - { .dt_id = MT8195_AP_VPU1 } + { .dt_id = MT8195_AP_VPU0, + .cal_offsets = { 0x25, 0x26, 0x27 } }, + { .dt_id = MT8195_AP_VPU1, + .cal_offsets = { 0x28, 0x29, 0x2a } } }, .num_lvts_sensor = 2, .offset = 0x0, }, { - .cal_offset = { 0x2e, 0x31 }, .lvts_sensor = { - { .dt_id = MT8195_AP_GPU0 }, - { .dt_id = MT8195_AP_GPU1 } + { .dt_id = MT8195_AP_GPU0, + .cal_offsets = { 0x2e, 0x2f, 0x30 } }, + { .dt_id = MT8195_AP_GPU1, + .cal_offsets = { 0x31, 0x32, 0x33 } } }, .num_lvts_sensor = 2, .offset = 0x100, }, { - .cal_offset = { 0x37, 0x3a, 0x3d }, .lvts_sensor = { - { .dt_id = MT8195_AP_VDEC }, - { .dt_id = MT8195_AP_IMG }, - { .dt_id = MT8195_AP_INFRA }, + { .dt_id = MT8195_AP_VDEC, + .cal_offsets = { 0x37, 0x38, 0x39 } }, + { .dt_id = MT8195_AP_IMG, + .cal_offsets = { 0x3a, 0x3b, 0x3c } }, + { .dt_id = MT8195_AP_INFRA, + .cal_offsets = { 0x3d, 0x3e, 0x3f } } }, .num_lvts_sensor = 3, .offset = 0x200, }, { - .cal_offset = { 0x43, 0x46 }, .lvts_sensor = { - { .dt_id = MT8195_AP_CAM0 }, - { .dt_id = MT8195_AP_CAM1 } + { .dt_id = MT8195_AP_CAM0, + .cal_offsets = { 0x43, 0x44, 0x45 } }, + { .dt_id = MT8195_AP_CAM1, + .cal_offsets = { 0x46, 0x47, 0x48 } } }, .num_lvts_sensor = 2, .offset = 0x300, -- cgit v1.2.3 From 2cc0b1a2169b0f4af83cc5a52a1693c8ab2e2f1d Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:39 -0400 Subject: thermal/drivers/mediatek/lvts_thermal: Guard against efuse data buffer overflow We don't want to silently fetch garbage past the actual buffer. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-6-nico@fluxnic.net --- drivers/thermal/mediatek/lvts_thermal.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 9e6ed8bf6d9a..146799462338 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -672,7 +672,8 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, */ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, const struct lvts_ctrl_data *lvts_ctrl_data, - u8 *efuse_calibration) + u8 *efuse_calibration, + size_t calib_len) { int i; @@ -680,6 +681,11 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl const struct lvts_sensor_data *sensor = &lvts_ctrl_data->lvts_sensor[i]; + if (sensor->cal_offsets[0] >= calib_len || + sensor->cal_offsets[1] >= calib_len || + sensor->cal_offsets[2] >= calib_len) + return -EINVAL; + lvts_ctrl->calibration[i] = (efuse_calibration[sensor->cal_offsets[0]] << 0) + (efuse_calibration[sensor->cal_offsets[1]] << 8) + @@ -791,7 +797,8 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, ret = lvts_calibration_init(dev, &lvts_ctrl[i], &lvts_data->lvts_ctrl[i], - lvts_td->calib); + lvts_td->calib, + lvts_td->calib_len); if (ret) return ret; -- cgit v1.2.3 From a2ca202350f97bced8dac4cbfbb3cbf855973e57 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:40 -0400 Subject: dt-bindings: thermal: mediatek: Add LVTS thermal controller definition for MT8186 Add LVTS thermal controller definition for MT8186. Signed-off-by: Nicolas Pitre Acked-by: Krzysztof Kozlowski Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-7-nico@fluxnic.net --- .../devicetree/bindings/thermal/mediatek,lvts-thermal.yaml | 2 ++ include/dt-bindings/thermal/mediatek,lvts-thermal.h | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml index e6665af52ee6..4173bae53032 100644 --- a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml @@ -19,6 +19,7 @@ properties: compatible: enum: - mediatek,mt7988-lvts-ap + - mediatek,mt8186-lvts - mediatek,mt8192-lvts-ap - mediatek,mt8192-lvts-mcu - mediatek,mt8195-lvts-ap @@ -75,6 +76,7 @@ allOf: compatible: contains: enum: + - mediatek,mt8186-lvts - mediatek,mt8195-lvts-ap - mediatek,mt8195-lvts-mcu then: diff --git a/include/dt-bindings/thermal/mediatek,lvts-thermal.h b/include/dt-bindings/thermal/mediatek,lvts-thermal.h index 997e2f55128a..433d298826d3 100644 --- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h +++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h @@ -16,6 +16,16 @@ #define MT7988_ETHWARP_0 6 #define MT7988_ETHWARP_1 7 +#define MT8186_LITTLE_CPU0 0 +#define MT8186_LITTLE_CPU1 1 +#define MT8186_LITTLE_CPU2 2 +#define MT8186_CAM 3 +#define MT8186_BIG_CPU0 4 +#define MT8186_BIG_CPU1 5 +#define MT8186_NNA 6 +#define MT8186_ADSP 7 +#define MT8186_MFG 8 + #define MT8195_MCU_BIG_CPU0 0 #define MT8195_MCU_BIG_CPU1 1 #define MT8195_MCU_BIG_CPU2 2 -- cgit v1.2.3 From a4c1ab2f4c6c94edfc6481edf37e141079e24f1d Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:42 -0400 Subject: thermal/drivers/mediatek/lvts_thermal: Add MT8186 support Various values extracted from the vendor's kernel driver. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-9-nico@fluxnic.net --- drivers/thermal/mediatek/lvts_thermal.c | 61 +++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 146799462338..6f711aec0d0f 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -1375,6 +1375,59 @@ static int lvts_resume(struct device *dev) return 0; } +/* + * The MT8186 calibration data is stored as packed 3-byte little-endian + * values using a weird layout that makes sense only when viewed as a 32-bit + * hexadecimal word dump. Let's suppose SxBy where x = sensor number and + * y = byte number where the LSB is y=0. We then have: + * + * [S0B2-S0B1-S0B0-S1B2] [S1B1-S1B0-S2B2-S2B1] [S2B0-S3B2-S3B1-S3B0] + * + * However, when considering a byte stream, those appear as follows: + * + * [S1B2] [S0B0[ [S0B1] [S0B2] [S2B1] [S2B2] [S1B0] [S1B1] [S3B0] [S3B1] [S3B2] [S2B0] + * + * Hence the rather confusing offsets provided below. + */ +static const struct lvts_ctrl_data mt8186_lvts_data_ctrl[] = { + { + .lvts_sensor = { + { .dt_id = MT8186_LITTLE_CPU0, + .cal_offsets = { 5, 6, 7 } }, + { .dt_id = MT8186_LITTLE_CPU1, + .cal_offsets = { 10, 11, 4 } }, + { .dt_id = MT8186_LITTLE_CPU2, + .cal_offsets = { 15, 8, 9 } }, + { .dt_id = MT8186_CAM, + .cal_offsets = { 12, 13, 14 } } + }, + .num_lvts_sensor = 4, + .offset = 0x0, + }, + { + .lvts_sensor = { + { .dt_id = MT8186_BIG_CPU0, + .cal_offsets = { 22, 23, 16 } }, + { .dt_id = MT8186_BIG_CPU1, + .cal_offsets = { 27, 20, 21 } } + }, + .num_lvts_sensor = 2, + .offset = 0x100, + }, + { + .lvts_sensor = { + { .dt_id = MT8186_NNA, + .cal_offsets = { 29, 30, 31 } }, + { .dt_id = MT8186_ADSP, + .cal_offsets = { 34, 35, 28 } }, + { .dt_id = MT8186_MFG, + .cal_offsets = { 39, 32, 33 } } + }, + .num_lvts_sensor = 3, + .offset = 0x200, + } +}; + static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { { .lvts_sensor = { @@ -1549,6 +1602,13 @@ static const struct lvts_data mt7988_lvts_ap_data = { .temp_offset = LVTS_COEFF_B_MT7988, }; +static const struct lvts_data mt8186_lvts_data = { + .lvts_ctrl = mt8186_lvts_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8186_lvts_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT7988, + .temp_offset = LVTS_COEFF_B_MT7988, +}; + static const struct lvts_data mt8192_lvts_mcu_data = { .lvts_ctrl = mt8192_lvts_mcu_data_ctrl, .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl), @@ -1579,6 +1639,7 @@ static const struct lvts_data mt8195_lvts_ap_data = { static const struct of_device_id lvts_of_match[] = { { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data }, + { .compatible = "mediatek,mt8186-lvts", .data = &mt8186_lvts_data }, { .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data }, { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data }, { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, -- cgit v1.2.3 From 684cbb49f9ceed6be0f33dac9d62089e7cd1c032 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:44 -0400 Subject: thermal/drivers/mediatek/lvts_thermal: Provision for gt variable location The golden temperature calibration value in nvram is not always the 3rd byte. A future commit will prove this assumption wrong. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-11-nico@fluxnic.net --- drivers/thermal/mediatek/lvts_thermal.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 6f711aec0d0f..34f5a8150430 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -116,6 +116,7 @@ struct lvts_data { int num_lvts_ctrl; int temp_factor; int temp_offset; + int gt_calib_bit_offset; }; struct lvts_sensor { @@ -745,20 +746,21 @@ static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td return 0; } -static int lvts_golden_temp_init(struct device *dev, u8 *calib, int temp_offset) +static int lvts_golden_temp_init(struct device *dev, u8 *calib, + const struct lvts_data *lvts_data) { u32 gt; /* - * The golden temp information is contained in the 4th byte (index = 3) - * of efuse data. + * The golden temp information is contained in the first 32-bit + * word of efuse data at a specific bit offset. */ - gt = calib[3]; + gt = (((u32 *)calib)[0] >> lvts_data->gt_calib_bit_offset) & 0xff; if (gt && gt < LVTS_GOLDEN_TEMP_MAX) golden_temp = gt; - golden_temp_offset = golden_temp * 500 + temp_offset; + golden_temp_offset = golden_temp * 500 + lvts_data->temp_offset; return 0; } @@ -777,7 +779,7 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, if (ret) return ret; - ret = lvts_golden_temp_init(dev, lvts_td->calib, lvts_data->temp_offset); + ret = lvts_golden_temp_init(dev, lvts_td->calib, lvts_data); if (ret) return ret; @@ -1600,6 +1602,7 @@ static const struct lvts_data mt7988_lvts_ap_data = { .num_lvts_ctrl = ARRAY_SIZE(mt7988_lvts_ap_data_ctrl), .temp_factor = LVTS_COEFF_A_MT7988, .temp_offset = LVTS_COEFF_B_MT7988, + .gt_calib_bit_offset = 24, }; static const struct lvts_data mt8186_lvts_data = { @@ -1607,6 +1610,7 @@ static const struct lvts_data mt8186_lvts_data = { .num_lvts_ctrl = ARRAY_SIZE(mt8186_lvts_data_ctrl), .temp_factor = LVTS_COEFF_A_MT7988, .temp_offset = LVTS_COEFF_B_MT7988, + .gt_calib_bit_offset = 24, }; static const struct lvts_data mt8192_lvts_mcu_data = { @@ -1614,6 +1618,7 @@ static const struct lvts_data mt8192_lvts_mcu_data = { .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl), .temp_factor = LVTS_COEFF_A_MT8195, .temp_offset = LVTS_COEFF_B_MT8195, + .gt_calib_bit_offset = 24, }; static const struct lvts_data mt8192_lvts_ap_data = { @@ -1621,6 +1626,7 @@ static const struct lvts_data mt8192_lvts_ap_data = { .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_ap_data_ctrl), .temp_factor = LVTS_COEFF_A_MT8195, .temp_offset = LVTS_COEFF_B_MT8195, + .gt_calib_bit_offset = 24, }; static const struct lvts_data mt8195_lvts_mcu_data = { @@ -1628,6 +1634,7 @@ static const struct lvts_data mt8195_lvts_mcu_data = { .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), .temp_factor = LVTS_COEFF_A_MT8195, .temp_offset = LVTS_COEFF_B_MT8195, + .gt_calib_bit_offset = 24, }; static const struct lvts_data mt8195_lvts_ap_data = { @@ -1635,6 +1642,7 @@ static const struct lvts_data mt8195_lvts_ap_data = { .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_ap_data_ctrl), .temp_factor = LVTS_COEFF_A_MT8195, .temp_offset = LVTS_COEFF_B_MT8195, + .gt_calib_bit_offset = 24, }; static const struct of_device_id lvts_of_match[] = { -- cgit v1.2.3 From 11e6f4c3144743b2b2c26a5cd58ae3696379b3ab Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:45 -0400 Subject: thermal/drivers/mediatek/lvts_thermal: Allow early empty sensor slots Some systems don't always populate sensor controller slots starting at slot 0. Use a bitmap instead of a count to indicate valid sensor slots. Also create a pretty iterator for that. About that iterator: it causes checkpatch to complain with "ERROR: Macros with multiple statements should be enclosed in a do - while loop". However this is not possible here. And many similar iterators do exist using the same form in the tree already. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-12-nico@fluxnic.net --- drivers/thermal/mediatek/lvts_thermal.c | 63 +++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 34f5a8150430..ced4fa8d9425 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -107,10 +107,23 @@ struct lvts_ctrl_data { struct lvts_sensor_data lvts_sensor[LVTS_SENSOR_MAX]; int cal_offset[LVTS_SENSOR_MAX]; int num_lvts_sensor; + u8 valid_sensor_mask; int offset; int mode; }; +#define VALID_SENSOR_MAP(s0, s1, s2, s3) \ + .valid_sensor_mask = (((s0) ? BIT(0) : 0) | \ + ((s1) ? BIT(1) : 0) | \ + ((s2) ? BIT(2) : 0) | \ + ((s3) ? BIT(3) : 0)) + +#define lvts_for_each_valid_sensor(i, lvts_ctrl_data) \ + for ((i) = 0; (i) < LVTS_SENSOR_MAX; (i)++) \ + if (!((lvts_ctrl_data)->valid_sensor_mask & BIT(i))) \ + continue; \ + else + struct lvts_data { const struct lvts_ctrl_data *lvts_ctrl; int num_lvts_ctrl; @@ -134,7 +147,6 @@ struct lvts_ctrl { const struct lvts_data *lvts_data; u32 calibration[LVTS_SENSOR_MAX]; u32 hw_tshut_raw_temp; - int num_lvts_sensor; int mode; void __iomem *base; int low_thresh; @@ -346,7 +358,7 @@ static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high) if (high > lvts_ctrl->high_thresh) return true; - for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) + lvts_for_each_valid_sensor(i, lvts_ctrl->lvts_data->lvts_ctrl) if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) return false; @@ -550,6 +562,7 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, const struct lvts_ctrl_data *lvts_ctrl_data) { struct lvts_sensor *lvts_sensor = lvts_ctrl->sensors; + void __iomem *msr_regs[] = { LVTS_MSR0(lvts_ctrl->base), LVTS_MSR1(lvts_ctrl->base), @@ -566,7 +579,7 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, int i; - for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) { + lvts_for_each_valid_sensor(i, lvts_ctrl_data) { int dt_id = lvts_ctrl_data->lvts_sensor[i].dt_id; @@ -606,8 +619,6 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, lvts_sensor[i].high_thresh = INT_MIN; }; - lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor; - return 0; } @@ -678,7 +689,7 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl { int i; - for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) { + lvts_for_each_valid_sensor(i, lvts_ctrl_data) { const struct lvts_sensor_data *sensor = &lvts_ctrl_data->lvts_sensor[i]; @@ -1103,7 +1114,7 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl) u32 *sensor_bitmap = lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE ? sensor_imm_bitmap : sensor_filt_bitmap; - for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) { + lvts_for_each_valid_sensor(i, lvts_ctrl->lvts_data->lvts_ctrl) { int dt_id = lvts_sensors[i].dt_id; @@ -1326,7 +1337,7 @@ static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { { .dt_id = MT7988_ETH2P5G_1, .cal_offsets = { 0x0c, 0x0d, 0x0e } } }, - .num_lvts_sensor = 4, + VALID_SENSOR_MAP(1, 1, 1, 1), .offset = 0x0, }, { @@ -1340,7 +1351,7 @@ static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { { .dt_id = MT7988_ETHWARP_1, .cal_offsets = { 0x20, 0x21, 0x22 } } }, - .num_lvts_sensor = 4, + VALID_SENSOR_MAP(1, 1, 1, 1), .offset = 0x100, } }; @@ -1403,7 +1414,7 @@ static const struct lvts_ctrl_data mt8186_lvts_data_ctrl[] = { { .dt_id = MT8186_CAM, .cal_offsets = { 12, 13, 14 } } }, - .num_lvts_sensor = 4, + VALID_SENSOR_MAP(1, 1, 1, 1), .offset = 0x0, }, { @@ -1413,7 +1424,7 @@ static const struct lvts_ctrl_data mt8186_lvts_data_ctrl[] = { { .dt_id = MT8186_BIG_CPU1, .cal_offsets = { 27, 20, 21 } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x100, }, { @@ -1425,7 +1436,7 @@ static const struct lvts_ctrl_data mt8186_lvts_data_ctrl[] = { { .dt_id = MT8186_MFG, .cal_offsets = { 39, 32, 33 } } }, - .num_lvts_sensor = 3, + VALID_SENSOR_MAP(1, 1, 1, 0), .offset = 0x200, } }; @@ -1438,7 +1449,7 @@ static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { { .dt_id = MT8192_MCU_BIG_CPU1, .cal_offsets = { 0x08, 0x09, 0x0a } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x0, .mode = LVTS_MSR_FILTERED_MODE, }, @@ -1449,7 +1460,7 @@ static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { { .dt_id = MT8192_MCU_BIG_CPU3, .cal_offsets = { 0x10, 0x11, 0x12 } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x100, .mode = LVTS_MSR_FILTERED_MODE, }, @@ -1464,7 +1475,7 @@ static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { { .dt_id = MT8192_MCU_LITTLE_CPU3, .cal_offsets = { 0x20, 0x21, 0x22 } } }, - .num_lvts_sensor = 4, + VALID_SENSOR_MAP(1, 1, 1, 1), .offset = 0x200, .mode = LVTS_MSR_FILTERED_MODE, } @@ -1478,7 +1489,7 @@ static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { { .dt_id = MT8192_AP_VPU1, .cal_offsets = { 0x28, 0x29, 0x2a } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x0, }, { @@ -1488,7 +1499,7 @@ static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { { .dt_id = MT8192_AP_GPU1, .cal_offsets = { 0x30, 0x31, 0x32 } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x100, }, { @@ -1498,7 +1509,7 @@ static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { { .dt_id = MT8192_AP_CAM, .cal_offsets = { 0x38, 0x39, 0x3a } }, }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x200, }, { @@ -1510,7 +1521,7 @@ static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { { .dt_id = MT8192_AP_MD2, .cal_offsets = { 0x44, 0x45, 0x46 } } }, - .num_lvts_sensor = 3, + VALID_SENSOR_MAP(1, 1, 1, 0), .offset = 0x300, } }; @@ -1523,7 +1534,7 @@ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { { .dt_id = MT8195_MCU_BIG_CPU1, .cal_offsets = { 0x07, 0x08, 0x09 } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x0, }, { @@ -1533,7 +1544,7 @@ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { { .dt_id = MT8195_MCU_BIG_CPU3, .cal_offsets = { 0x10, 0x11, 0x12 } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x100, }, { @@ -1547,7 +1558,7 @@ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { { .dt_id = MT8195_MCU_LITTLE_CPU3, .cal_offsets = { 0x1f, 0x20, 0x21 } } }, - .num_lvts_sensor = 4, + VALID_SENSOR_MAP(1, 1, 1, 1), .offset = 0x200, } }; @@ -1560,7 +1571,7 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { { .dt_id = MT8195_AP_VPU1, .cal_offsets = { 0x28, 0x29, 0x2a } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x0, }, { @@ -1570,7 +1581,7 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { { .dt_id = MT8195_AP_GPU1, .cal_offsets = { 0x31, 0x32, 0x33 } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x100, }, { @@ -1582,7 +1593,7 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { { .dt_id = MT8195_AP_INFRA, .cal_offsets = { 0x3d, 0x3e, 0x3f } } }, - .num_lvts_sensor = 3, + VALID_SENSOR_MAP(1, 1, 1, 0), .offset = 0x200, }, { @@ -1592,7 +1603,7 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { { .dt_id = MT8195_AP_CAM1, .cal_offsets = { 0x46, 0x47, 0x48 } } }, - .num_lvts_sensor = 2, + VALID_SENSOR_MAP(1, 1, 0, 0), .offset = 0x300, } }; -- cgit v1.2.3 From 78c88534e5e1f8c5334c380b626c6ee91b62161b Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:46 -0400 Subject: dt-bindings: thermal: mediatek: Add LVTS thermal controller definition for MT8188 Add LVTS thermal controller definition for MT8188. Signed-off-by: Nicolas Pitre Reviewed-by: Rob Herring Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-13-nico@fluxnic.net --- .../bindings/thermal/mediatek,lvts-thermal.yaml | 4 ++++ include/dt-bindings/thermal/mediatek,lvts-thermal.h | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml index 4173bae53032..331cf4e662e3 100644 --- a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml @@ -20,6 +20,8 @@ properties: enum: - mediatek,mt7988-lvts-ap - mediatek,mt8186-lvts + - mediatek,mt8188-lvts-ap + - mediatek,mt8188-lvts-mcu - mediatek,mt8192-lvts-ap - mediatek,mt8192-lvts-mcu - mediatek,mt8195-lvts-ap @@ -61,6 +63,8 @@ allOf: compatible: contains: enum: + - mediatek,mt8188-lvts-ap + - mediatek,mt8188-lvts-mcu - mediatek,mt8192-lvts-ap - mediatek,mt8192-lvts-mcu then: diff --git a/include/dt-bindings/thermal/mediatek,lvts-thermal.h b/include/dt-bindings/thermal/mediatek,lvts-thermal.h index 433d298826d3..bf95309d2525 100644 --- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h +++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h @@ -26,6 +26,22 @@ #define MT8186_ADSP 7 #define MT8186_MFG 8 +#define MT8188_MCU_LITTLE_CPU0 0 +#define MT8188_MCU_LITTLE_CPU1 1 +#define MT8188_MCU_LITTLE_CPU2 2 +#define MT8188_MCU_LITTLE_CPU3 3 +#define MT8188_MCU_BIG_CPU0 4 +#define MT8188_MCU_BIG_CPU1 5 + +#define MT8188_AP_APU 0 +#define MT8188_AP_GPU1 1 +#define MT8188_AP_GPU2 2 +#define MT8188_AP_SOC1 3 +#define MT8188_AP_SOC2 4 +#define MT8188_AP_SOC3 5 +#define MT8188_AP_CAM1 6 +#define MT8188_AP_CAM2 7 + #define MT8195_MCU_BIG_CPU0 0 #define MT8195_MCU_BIG_CPU1 1 #define MT8195_MCU_BIG_CPU2 2 -- cgit v1.2.3 From f4745f546e6077e3ed2bab90e931154519e96ae0 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 1 Apr 2024 23:25:48 -0400 Subject: thermal/drivers/mediatek/lvts_thermal: Add MT8188 support Various values extracted from the vendor's kernel driver. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240402032729.2736685-15-nico@fluxnic.net --- drivers/thermal/mediatek/lvts_thermal.c | 96 +++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index ced4fa8d9425..86b2f44355ac 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -1441,6 +1441,84 @@ static const struct lvts_ctrl_data mt8186_lvts_data_ctrl[] = { } }; +static const struct lvts_ctrl_data mt8188_lvts_mcu_data_ctrl[] = { + { + .lvts_sensor = { + { .dt_id = MT8188_MCU_LITTLE_CPU0, + .cal_offsets = { 22, 23, 24 } }, + { .dt_id = MT8188_MCU_LITTLE_CPU1, + .cal_offsets = { 25, 26, 27 } }, + { .dt_id = MT8188_MCU_LITTLE_CPU2, + .cal_offsets = { 28, 29, 30 } }, + { .dt_id = MT8188_MCU_LITTLE_CPU3, + .cal_offsets = { 31, 32, 33 } }, + }, + VALID_SENSOR_MAP(1, 1, 1, 1), + .offset = 0x0, + .mode = LVTS_MSR_FILTERED_MODE, + }, + { + .lvts_sensor = { + { .dt_id = MT8188_MCU_BIG_CPU0, + .cal_offsets = { 34, 35, 36 } }, + { .dt_id = MT8188_MCU_BIG_CPU1, + .cal_offsets = { 37, 38, 39 } }, + }, + VALID_SENSOR_MAP(1, 1, 0, 0), + .offset = 0x100, + .mode = LVTS_MSR_FILTERED_MODE, + } +}; + +static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = { + { + .lvts_sensor = { + + { /* unused */ }, + { .dt_id = MT8188_AP_APU, + .cal_offsets = { 40, 41, 42 } }, + }, + VALID_SENSOR_MAP(0, 1, 0, 0), + .offset = 0x0, + .mode = LVTS_MSR_FILTERED_MODE, + }, + { + .lvts_sensor = { + { .dt_id = MT8188_AP_GPU1, + .cal_offsets = { 43, 44, 45 } }, + { .dt_id = MT8188_AP_GPU2, + .cal_offsets = { 46, 47, 48 } }, + { .dt_id = MT8188_AP_SOC1, + .cal_offsets = { 49, 50, 51 } }, + }, + VALID_SENSOR_MAP(1, 1, 1, 0), + .offset = 0x100, + .mode = LVTS_MSR_FILTERED_MODE, + }, + { + .lvts_sensor = { + { .dt_id = MT8188_AP_SOC2, + .cal_offsets = { 52, 53, 54 } }, + { .dt_id = MT8188_AP_SOC3, + .cal_offsets = { 55, 56, 57 } }, + }, + VALID_SENSOR_MAP(1, 1, 0, 0), + .offset = 0x200, + .mode = LVTS_MSR_FILTERED_MODE, + }, + { + .lvts_sensor = { + { .dt_id = MT8188_AP_CAM1, + .cal_offsets = { 58, 59, 60 } }, + { .dt_id = MT8188_AP_CAM2, + .cal_offsets = { 61, 62, 63 } }, + }, + VALID_SENSOR_MAP(1, 1, 0, 0), + .offset = 0x300, + .mode = LVTS_MSR_FILTERED_MODE, + } +}; + static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { { .lvts_sensor = { @@ -1624,6 +1702,22 @@ static const struct lvts_data mt8186_lvts_data = { .gt_calib_bit_offset = 24, }; +static const struct lvts_data mt8188_lvts_mcu_data = { + .lvts_ctrl = mt8188_lvts_mcu_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8188_lvts_mcu_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT8195, + .temp_offset = LVTS_COEFF_B_MT8195, + .gt_calib_bit_offset = 20, +}; + +static const struct lvts_data mt8188_lvts_ap_data = { + .lvts_ctrl = mt8188_lvts_ap_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8188_lvts_ap_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT8195, + .temp_offset = LVTS_COEFF_B_MT8195, + .gt_calib_bit_offset = 20, +}; + static const struct lvts_data mt8192_lvts_mcu_data = { .lvts_ctrl = mt8192_lvts_mcu_data_ctrl, .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl), @@ -1659,6 +1753,8 @@ static const struct lvts_data mt8195_lvts_ap_data = { static const struct of_device_id lvts_of_match[] = { { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data }, { .compatible = "mediatek,mt8186-lvts", .data = &mt8186_lvts_data }, + { .compatible = "mediatek,mt8188-lvts-mcu", .data = &mt8188_lvts_mcu_data }, + { .compatible = "mediatek,mt8188-lvts-ap", .data = &mt8188_lvts_ap_data }, { .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data }, { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data }, { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, -- cgit v1.2.3 From 6ef6d5ff5eddb3457eef8d78d7b8b451be19b5c3 Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Tue, 23 Apr 2024 09:59:00 +0800 Subject: thermal/drivers/loongson2: Trivial code style adjustment Here are some minor code style adjustment. Such as fix whitespace code style; align function call arguments to opening parenthesis. Signed-off-by: Binbin Zhou Acked-by: Huacai Chen Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/ccca50f2ad3fd8c84fcbfcb1f875427ea7f637a0.1713837379.git.zhoubinbin@loongson.cn --- drivers/thermal/loongson2_thermal.c | 65 +++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c index 0f475fe46bc9..5c9cf45a3719 100644 --- a/drivers/thermal/loongson2_thermal.c +++ b/drivers/thermal/loongson2_thermal.c @@ -14,47 +14,51 @@ #include #include #include + #include "thermal_hwmon.h" -#define LOONGSON2_MAX_SENSOR_SEL_NUM 3 +#define LOONGSON2_MAX_SENSOR_SEL_NUM 3 -#define LOONGSON2_THSENS_CTRL_HI_REG 0x0 -#define LOONGSON2_THSENS_CTRL_LOW_REG 0x8 -#define LOONGSON2_THSENS_STATUS_REG 0x10 -#define LOONGSON2_THSENS_OUT_REG 0x14 +#define LOONGSON2_THSENS_CTRL_HI_REG 0x0 +#define LOONGSON2_THSENS_CTRL_LOW_REG 0x8 +#define LOONGSON2_THSENS_STATUS_REG 0x10 +#define LOONGSON2_THSENS_OUT_REG 0x14 -#define LOONGSON2_THSENS_INT_LO BIT(0) -#define LOONGSON2_THSENS_INT_HIGH BIT(1) -#define LOONGSON2_THSENS_OUT_MASK 0xFF +#define LOONGSON2_THSENS_INT_LO BIT(0) +#define LOONGSON2_THSENS_INT_HIGH BIT(1) +#define LOONGSON2_THSENS_INT_EN (LOONGSON2_THSENS_INT_LO | \ + LOONGSON2_THSENS_INT_HIGH) +#define LOONGSON2_THSENS_OUT_MASK 0xFF struct loongson2_thermal_chip_data { - unsigned int thermal_sensor_sel; + unsigned int thermal_sensor_sel; }; struct loongson2_thermal_data { - void __iomem *regs; + void __iomem *regs; const struct loongson2_thermal_chip_data *chip_data; }; -static int loongson2_thermal_set(struct loongson2_thermal_data *data, - int low, int high, bool enable) +static void loongson2_set_ctrl_regs(struct loongson2_thermal_data *data, + int ctrl_data, bool low, bool enable) { - u64 reg_ctrl = 0; - int reg_off = data->chip_data->thermal_sensor_sel * 2; - - low = clamp(-40, low, high); - high = clamp(125, low, high); + int reg_ctrl = 0; + int reg_off = data->chip_data->thermal_sensor_sel * 2; + int ctrl_reg = low ? LOONGSON2_THSENS_CTRL_LOW_REG : LOONGSON2_THSENS_CTRL_HI_REG; - low += HECTO; - high += HECTO; - - reg_ctrl = low; + reg_ctrl = ctrl_data + HECTO; reg_ctrl |= enable ? 0x100 : 0; - writew(reg_ctrl, data->regs + LOONGSON2_THSENS_CTRL_LOW_REG + reg_off); + writew(reg_ctrl, data->regs + ctrl_reg + reg_off); +} - reg_ctrl = high; - reg_ctrl |= enable ? 0x100 : 0; - writew(reg_ctrl, data->regs + LOONGSON2_THSENS_CTRL_HI_REG + reg_off); +static int loongson2_thermal_set(struct loongson2_thermal_data *data, + int low, int high, bool enable) +{ + /* Set low temperature threshold */ + loongson2_set_ctrl_regs(data, clamp(-40, low, high), true, enable); + + /* Set high temperature threshold */ + loongson2_set_ctrl_regs(data, clamp(125, low, high), false, enable); return 0; } @@ -75,8 +79,7 @@ static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev) struct thermal_zone_device *tzd = dev; struct loongson2_thermal_data *data = thermal_zone_device_priv(tzd); - writeb(LOONGSON2_THSENS_INT_LO | LOONGSON2_THSENS_INT_HIGH, data->regs + - LOONGSON2_THSENS_STATUS_REG); + writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); thermal_zone_device_update(tzd, THERMAL_EVENT_UNSPECIFIED); @@ -116,14 +119,13 @@ static int loongson2_thermal_probe(struct platform_device *pdev) if (irq < 0) return irq; - writeb(LOONGSON2_THSENS_INT_LO | LOONGSON2_THSENS_INT_HIGH, data->regs + - LOONGSON2_THSENS_STATUS_REG); + writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); loongson2_thermal_set(data, 0, 0, false); for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) { tzd = devm_thermal_of_zone_register(dev, i, data, - &loongson2_of_thermal_ops); + &loongson2_of_thermal_ops); if (!IS_ERR(tzd)) break; @@ -135,7 +137,7 @@ static int loongson2_thermal_probe(struct platform_device *pdev) } ret = devm_request_threaded_irq(dev, irq, NULL, loongson2_thermal_irq_thread, - IRQF_ONESHOT, "loongson2_thermal", tzd); + IRQF_ONESHOT, "loongson2_thermal", tzd); if (ret < 0) return dev_err_probe(dev, ret, "failed to request alarm irq\n"); @@ -167,4 +169,5 @@ static struct platform_driver loongson2_thermal_driver = { module_platform_driver(loongson2_thermal_driver); MODULE_DESCRIPTION("Loongson2 thermal driver"); +MODULE_AUTHOR("Loongson Technology Corporation Limited"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 25c7d8472f6e90390931e93f59135478af3e5d86 Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Tue, 23 Apr 2024 09:59:01 +0800 Subject: dt-bindings: thermal: loongson,ls2k-thermal: Add Loongson-2K0500 compatible The thermal on the Loongson-2K0500 shares the design with the Loongson-2K1000. Define corresponding compatible string, having the loongson,ls2k1000-thermal as a fallback. Signed-off-by: Binbin Zhou Acked-by: Rob Herring Acked-by: Huacai Chen Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/26524a63abd2d032e4c45efe6ce3fedb46841768.1713837379.git.zhoubinbin@loongson.cn --- Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml index b634f57cd011..9748a479dcd4 100644 --- a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml @@ -20,6 +20,7 @@ properties: - loongson,ls2k1000-thermal - items: - enum: + - loongson,ls2k0500-thermal - loongson,ls2k2000-thermal - const: loongson,ls2k1000-thermal -- cgit v1.2.3 From c8c4353685778e75e186103411e9d01a4a3f2b90 Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Tue, 23 Apr 2024 09:59:02 +0800 Subject: dt-bindings: thermal: loongson,ls2k-thermal: Fix incorrect compatible definition The temperature output register of the Loongson-2K2000 is defined in the chip configuration domain, which is different from the Loongson-2K1000, so it can't be fallbacked. We need to use two groups of registers to describe it: the first group is the high and low temperature threshold setting register; the second group is the temperature output register. It is true that this fix will cause ABI corruption, but it is necessary otherwise the Loongson-2K2000 temperature sensor will not work properly. Fixes: 72684d99a854 ("thermal: dt-bindings: add loongson-2 thermal") Cc: Yinbo Zhu Signed-off-by: Binbin Zhou Reviewed-by: Krzysztof Kozlowski Acked-by: Huacai Chen Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/5198999d679f1a1c3457385acb9fadfc85da1f1e.1713837379.git.zhoubinbin@loongson.cn --- .../bindings/thermal/loongson,ls2k-thermal.yaml | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml index 9748a479dcd4..ca81c8afba79 100644 --- a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml @@ -18,14 +18,15 @@ properties: oneOf: - enum: - loongson,ls2k1000-thermal + - loongson,ls2k2000-thermal - items: - enum: - loongson,ls2k0500-thermal - - loongson,ls2k2000-thermal - const: loongson,ls2k1000-thermal reg: - maxItems: 1 + minItems: 1 + maxItems: 2 interrupts: maxItems: 1 @@ -39,6 +40,24 @@ required: - interrupts - '#thermal-sensor-cells' +if: + properties: + compatible: + contains: + enum: + - loongson,ls2k2000-thermal + +then: + properties: + reg: + minItems: 2 + maxItems: 2 + +else: + properties: + reg: + maxItems: 1 + unevaluatedProperties: false examples: -- cgit v1.2.3 From 734b5def91b594d3aa1147d60c45eded139ce2eb Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Tue, 23 Apr 2024 09:59:26 +0800 Subject: thermal/drivers/loongson2: Add Loongson-2K2000 support The Loongson-2K2000 and Loongson-2K1000 have similar thermal sensors, except that the temperature is read differently. In particular, the temperature output registers of the Loongson-2K2000 are defined in the chip configuration domain and are read in a different way. Signed-off-by: Binbin Zhou Acked-by: Huacai Chen Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/fdbfdcc3231a36a4ee0bcf1377ddcbd6f8c944b5.1713837379.git.zhoubinbin@loongson.cn --- drivers/thermal/loongson2_thermal.c | 64 +++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c index 5c9cf45a3719..2d6b75b0539f 100644 --- a/drivers/thermal/loongson2_thermal.c +++ b/drivers/thermal/loongson2_thermal.c @@ -30,12 +30,20 @@ LOONGSON2_THSENS_INT_HIGH) #define LOONGSON2_THSENS_OUT_MASK 0xFF +/* + * This flag is used to indicate the temperature reading + * method of the Loongson-2K2000 + */ +#define LS2K2000_THSENS_OUT_FLAG BIT(0) + struct loongson2_thermal_chip_data { unsigned int thermal_sensor_sel; + unsigned int flags; }; struct loongson2_thermal_data { - void __iomem *regs; + void __iomem *ctrl_reg; + void __iomem *temp_reg; const struct loongson2_thermal_chip_data *chip_data; }; @@ -48,7 +56,7 @@ static void loongson2_set_ctrl_regs(struct loongson2_thermal_data *data, reg_ctrl = ctrl_data + HECTO; reg_ctrl |= enable ? 0x100 : 0; - writew(reg_ctrl, data->regs + ctrl_reg + reg_off); + writew(reg_ctrl, data->ctrl_reg + ctrl_reg + reg_off); } static int loongson2_thermal_set(struct loongson2_thermal_data *data, @@ -63,13 +71,24 @@ static int loongson2_thermal_set(struct loongson2_thermal_data *data, return 0; } -static int loongson2_thermal_get_temp(struct thermal_zone_device *tz, int *temp) +static int loongson2_2k1000_get_temp(struct thermal_zone_device *tz, int *temp) +{ + int val; + struct loongson2_thermal_data *data = thermal_zone_device_priv(tz); + + val = readl(data->ctrl_reg + LOONGSON2_THSENS_OUT_REG); + *temp = ((val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; + + return 0; +} + +static int loongson2_2k2000_get_temp(struct thermal_zone_device *tz, int *temp) { - u32 reg_val; + int val; struct loongson2_thermal_data *data = thermal_zone_device_priv(tz); - reg_val = readl(data->regs + LOONGSON2_THSENS_OUT_REG); - *temp = ((reg_val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; + val = readl(data->temp_reg); + *temp = ((val & 0xffff) * 820 / 0x4000 - 311) * KILO; return 0; } @@ -79,7 +98,7 @@ static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev) struct thermal_zone_device *tzd = dev; struct loongson2_thermal_data *data = thermal_zone_device_priv(tzd); - writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); + writeb(LOONGSON2_THSENS_INT_EN, data->ctrl_reg + LOONGSON2_THSENS_STATUS_REG); thermal_zone_device_update(tzd, THERMAL_EVENT_UNSPECIFIED); @@ -93,8 +112,8 @@ static int loongson2_thermal_set_trips(struct thermal_zone_device *tz, int low, return loongson2_thermal_set(data, low/MILLI, high/MILLI, true); } -static const struct thermal_zone_device_ops loongson2_of_thermal_ops = { - .get_temp = loongson2_thermal_get_temp, +static struct thermal_zone_device_ops loongson2_of_thermal_ops = { + .get_temp = loongson2_2k1000_get_temp, .set_trips = loongson2_thermal_set_trips, }; @@ -111,15 +130,24 @@ static int loongson2_thermal_probe(struct platform_device *pdev) data->chip_data = device_get_match_data(dev); - data->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(data->regs)) - return PTR_ERR(data->regs); + data->ctrl_reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(data->ctrl_reg)) + return PTR_ERR(data->ctrl_reg); + + /* The temperature output register is separate for Loongson-2K2000 */ + if (data->chip_data->flags & LS2K2000_THSENS_OUT_FLAG) { + data->temp_reg = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(data->temp_reg)) + return PTR_ERR(data->temp_reg); + + loongson2_of_thermal_ops.get_temp = loongson2_2k2000_get_temp; + } irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - writeb(LOONGSON2_THSENS_INT_EN, data->regs + LOONGSON2_THSENS_STATUS_REG); + writeb(LOONGSON2_THSENS_INT_EN, data->ctrl_reg + LOONGSON2_THSENS_STATUS_REG); loongson2_thermal_set(data, 0, 0, false); @@ -148,6 +176,12 @@ static int loongson2_thermal_probe(struct platform_device *pdev) static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = { .thermal_sensor_sel = 0, + .flags = 0, +}; + +static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k2000_data = { + .thermal_sensor_sel = 0, + .flags = LS2K2000_THSENS_OUT_FLAG, }; static const struct of_device_id of_loongson2_thermal_match[] = { @@ -155,6 +189,10 @@ static const struct of_device_id of_loongson2_thermal_match[] = { .compatible = "loongson,ls2k1000-thermal", .data = &loongson2_thermal_ls2k1000_data, }, + { + .compatible = "loongson,ls2k2000-thermal", + .data = &loongson2_thermal_ls2k2000_data, + }, { /* end */ } }; MODULE_DEVICE_TABLE(of, of_loongson2_thermal_match); -- cgit v1.2.3