* [PATCH v6 1/4] dt-bindings: thermal: mediatek: add binding documentation for MT8365 SoC
2022-10-19 14:17 [PATCH v6 0/4] thermal: mediatek: Add support for MT8365 SoC Amjad Ouled-Ameur
@ 2022-10-19 14:17 ` Amjad Ouled-Ameur
2022-10-19 14:17 ` [PATCH v6 2/4] thermal: mediatek: control buffer enablement tweaks Amjad Ouled-Ameur
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Amjad Ouled-Ameur @ 2022-10-19 14:17 UTC (permalink / raw)
To: Krzysztof Kozlowski, Zhang Rui, Amit Kucheria, Rob Herring,
Rafael J. Wysocki, Daniel Lezcano
Cc: Fabien Parent, linux-mediatek, Rob Herring,
Markus Schneider-Pargmann, linux-arm-kernel, linux-pm,
AngeloGioacchino Del Regno, Michael Kao, Hsin-Yi Wang,
Amjad Ouled-Ameur, linux-kernel, devicetree, Matthias Brugger
From: Fabien Parent <fparent@baylibre.com>
Add the binding documentation for the thermal support on MT8365 SoC.
Signed-off-by: Fabien Parent <fparent@baylibre.com>
Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/thermal/mediatek-thermal.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
index 5c7e7bdd029a..ba4ebffeade4 100644
--- a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
@@ -14,6 +14,7 @@ Required properties:
- "mediatek,mt2712-thermal" : For MT2712 family of SoCs
- "mediatek,mt7622-thermal" : For MT7622 SoC
- "mediatek,mt8183-thermal" : For MT8183 family of SoCs
+ - "mediatek,mt8365-thermal" : For MT8365 family of SoCs
- "mediatek,mt8516-thermal", "mediatek,mt2701-thermal : For MT8516 family of SoCs
- reg: Address range of the thermal controller
- interrupts: IRQ for the thermal controller
--
b4 0.10.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v6 2/4] thermal: mediatek: control buffer enablement tweaks
2022-10-19 14:17 [PATCH v6 0/4] thermal: mediatek: Add support for MT8365 SoC Amjad Ouled-Ameur
2022-10-19 14:17 ` [PATCH v6 1/4] dt-bindings: thermal: mediatek: add binding documentation " Amjad Ouled-Ameur
@ 2022-10-19 14:17 ` Amjad Ouled-Ameur
2022-10-19 14:17 ` [PATCH v6 3/4] thermal: mediatek: add support for MT8365 SoC Amjad Ouled-Ameur
2022-10-19 14:17 ` [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors Amjad Ouled-Ameur
3 siblings, 0 replies; 10+ messages in thread
From: Amjad Ouled-Ameur @ 2022-10-19 14:17 UTC (permalink / raw)
To: Krzysztof Kozlowski, Zhang Rui, Amit Kucheria, Rob Herring,
Rafael J. Wysocki, Daniel Lezcano
Cc: Fabien Parent, linux-mediatek, Rob Herring,
Markus Schneider-Pargmann, linux-arm-kernel, linux-pm,
AngeloGioacchino Del Regno, Michael Kao, Hsin-Yi Wang,
Amjad Ouled-Ameur, linux-kernel, devicetree, Matthias Brugger
From: Markus Schneider-Pargmann <msp@baylibre.com>
Add logic in order to be able to turn on the control buffer on MT8365.
This change now allows to have control buffer support for MTK_THERMAL_V1,
and it allows to define the register offset, and mask used to enable it.
Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
Signed-off-by: Fabien Parent <fparent@baylibre.com>
Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/thermal/mtk_thermal.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index 8440692e3890..d8ddceb75372 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -271,6 +271,9 @@ struct mtk_thermal_data {
bool need_switch_bank;
struct thermal_bank_cfg bank_data[MAX_NUM_ZONES];
enum mtk_thermal_version version;
+ u32 apmixed_buffer_ctl_reg;
+ u32 apmixed_buffer_ctl_mask;
+ u32 apmixed_buffer_ctl_set;
};
struct mtk_thermal {
@@ -514,6 +517,9 @@ static const struct mtk_thermal_data mt7622_thermal_data = {
.adcpnp = mt7622_adcpnp,
.sensor_mux_values = mt7622_mux_values,
.version = MTK_THERMAL_V2,
+ .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON1,
+ .apmixed_buffer_ctl_mask = GENMASK(31, 6) | BIT(3),
+ .apmixed_buffer_ctl_set = BIT(0),
};
/*
@@ -963,14 +969,18 @@ static const struct of_device_id mtk_thermal_of_match[] = {
};
MODULE_DEVICE_TABLE(of, mtk_thermal_of_match);
-static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base)
+static void mtk_thermal_turn_on_buffer(struct mtk_thermal *mt,
+ void __iomem *apmixed_base)
{
- int tmp;
+ u32 tmp;
+
+ if (!mt->conf->apmixed_buffer_ctl_reg)
+ return;
- tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1);
- tmp &= ~(0x37);
- tmp |= 0x1;
- writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1);
+ tmp = readl(apmixed_base + mt->conf->apmixed_buffer_ctl_reg);
+ tmp &= mt->conf->apmixed_buffer_ctl_mask;
+ tmp |= mt->conf->apmixed_buffer_ctl_set;
+ writel(tmp, apmixed_base + mt->conf->apmixed_buffer_ctl_reg);
udelay(200);
}
@@ -1070,8 +1080,9 @@ static int mtk_thermal_probe(struct platform_device *pdev)
goto err_disable_clk_auxadc;
}
+ mtk_thermal_turn_on_buffer(mt, apmixed_base);
+
if (mt->conf->version == MTK_THERMAL_V2) {
- mtk_thermal_turn_on_buffer(apmixed_base);
mtk_thermal_release_periodic_ts(mt, auxadc_base);
}
--
b4 0.10.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v6 3/4] thermal: mediatek: add support for MT8365 SoC
2022-10-19 14:17 [PATCH v6 0/4] thermal: mediatek: Add support for MT8365 SoC Amjad Ouled-Ameur
2022-10-19 14:17 ` [PATCH v6 1/4] dt-bindings: thermal: mediatek: add binding documentation " Amjad Ouled-Ameur
2022-10-19 14:17 ` [PATCH v6 2/4] thermal: mediatek: control buffer enablement tweaks Amjad Ouled-Ameur
@ 2022-10-19 14:17 ` Amjad Ouled-Ameur
2022-10-19 14:17 ` [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors Amjad Ouled-Ameur
3 siblings, 0 replies; 10+ messages in thread
From: Amjad Ouled-Ameur @ 2022-10-19 14:17 UTC (permalink / raw)
To: Krzysztof Kozlowski, Zhang Rui, Amit Kucheria, Rob Herring,
Rafael J. Wysocki, Daniel Lezcano
Cc: Fabien Parent, linux-mediatek, Rob Herring,
Markus Schneider-Pargmann, linux-arm-kernel, linux-pm,
AngeloGioacchino Del Regno, Michael Kao, Hsin-Yi Wang,
Amjad Ouled-Ameur, linux-kernel, devicetree, Matthias Brugger
From: Fabien Parent <fparent@baylibre.com>
MT8365 is similar to the other SoCs supported by the driver. It has only
one bank and 3 actual sensors that can be multiplexed. There is another
one sensor that does not have usable data.
Signed-off-by: Fabien Parent <fparent@baylibre.com>
Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/thermal/mtk_thermal.c | 68 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index d8ddceb75372..3a5df1440822 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -31,6 +31,7 @@
#define AUXADC_CON2_V 0x010
#define AUXADC_DATA(channel) (0x14 + (channel) * 4)
+#define APMIXED_SYS_TS_CON0 0x600
#define APMIXED_SYS_TS_CON1 0x604
/* Thermal Controller Registers */
@@ -245,6 +246,17 @@ enum mtk_thermal_version {
/* The calibration coefficient of sensor */
#define MT8183_CALIBRATION 153
+/* MT8365 */
+#define MT8365_TEMP_AUXADC_CHANNEL 11
+#define MT8365_CALIBRATION 164
+#define MT8365_NUM_CONTROLLER 1
+#define MT8365_NUM_BANKS 1
+#define MT8365_NUM_SENSORS 3
+#define MT8365_NUM_SENSORS_PER_ZONE 3
+#define MT8365_TS1 0
+#define MT8365_TS2 1
+#define MT8365_TS3 2
+
struct mtk_thermal;
struct thermal_bank_cfg {
@@ -389,6 +401,24 @@ static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, };
static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 };
static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, };
+/* MT8365 thermal sensor data */
+static const int mt8365_bank_data[MT8365_NUM_SENSORS] = {
+ MT8365_TS1, MT8365_TS2, MT8365_TS3
+};
+
+static const int mt8365_msr[MT8365_NUM_SENSORS_PER_ZONE] = {
+ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2
+};
+
+static const int mt8365_adcpnp[MT8365_NUM_SENSORS_PER_ZONE] = {
+ TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2
+};
+
+static const int mt8365_mux_values[MT8365_NUM_SENSORS] = { 0, 1, 2 };
+static const int mt8365_tc_offset[MT8365_NUM_CONTROLLER] = { 0 };
+
+static const int mt8365_vts_index[MT8365_NUM_SENSORS] = { VTS1, VTS2, VTS3 };
+
/*
* The MT8173 thermal controller has four banks. Each bank can read up to
* four temperature sensors simultaneously. The MT8173 has a total of 5
@@ -463,6 +493,40 @@ static const struct mtk_thermal_data mt2701_thermal_data = {
.version = MTK_THERMAL_V1,
};
+/*
+ * The MT8365 thermal controller has one bank, which can read up to
+ * four temperature sensors simultaneously. The MT8365 has a total of 3
+ * temperature sensors.
+ *
+ * The thermal core only gets the maximum temperature of this one bank,
+ * so the bank concept wouldn't be necessary here. However, the SVS (Smart
+ * Voltage Scaling) unit makes its decisions based on the same bank
+ * data.
+ */
+static const struct mtk_thermal_data mt8365_thermal_data = {
+ .auxadc_channel = MT8365_TEMP_AUXADC_CHANNEL,
+ .num_banks = MT8365_NUM_BANKS,
+ .num_sensors = MT8365_NUM_SENSORS,
+ .vts_index = mt8365_vts_index,
+ .cali_val = MT8365_CALIBRATION,
+ .num_controller = MT8365_NUM_CONTROLLER,
+ .controller_offset = mt8365_tc_offset,
+ .need_switch_bank = false,
+ .bank_data = {
+ {
+ .num_sensors = MT8365_NUM_SENSORS,
+ .sensors = mt8365_bank_data
+ },
+ },
+ .msr = mt8365_msr,
+ .adcpnp = mt8365_adcpnp,
+ .sensor_mux_values = mt8365_mux_values,
+ .version = MTK_THERMAL_V1,
+ .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON0,
+ .apmixed_buffer_ctl_mask = (u32) ~GENMASK(29, 28),
+ .apmixed_buffer_ctl_set = 0,
+};
+
/*
* The MT2712 thermal controller has one bank, which can read up to
* four temperature sensors simultaneously. The MT2712 has a total of 4
@@ -964,6 +1028,10 @@ static const struct of_device_id mtk_thermal_of_match[] = {
{
.compatible = "mediatek,mt8183-thermal",
.data = (void *)&mt8183_thermal_data,
+ },
+ {
+ .compatible = "mediatek,mt8365-thermal",
+ .data = (void *)&mt8365_thermal_data,
}, {
},
};
--
b4 0.10.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors
2022-10-19 14:17 [PATCH v6 0/4] thermal: mediatek: Add support for MT8365 SoC Amjad Ouled-Ameur
` (2 preceding siblings ...)
2022-10-19 14:17 ` [PATCH v6 3/4] thermal: mediatek: add support for MT8365 SoC Amjad Ouled-Ameur
@ 2022-10-19 14:17 ` Amjad Ouled-Ameur
2022-10-22 17:03 ` Daniel Lezcano
2022-11-15 10:49 ` Pin-yen Lin
3 siblings, 2 replies; 10+ messages in thread
From: Amjad Ouled-Ameur @ 2022-10-19 14:17 UTC (permalink / raw)
To: Krzysztof Kozlowski, Zhang Rui, Amit Kucheria, Rob Herring,
Rafael J. Wysocki, Daniel Lezcano
Cc: Fabien Parent, linux-mediatek, Rob Herring,
Markus Schneider-Pargmann, linux-arm-kernel, linux-pm,
AngeloGioacchino Del Regno, Michael Kao, Hsin-Yi Wang,
Amjad Ouled-Ameur, linux-kernel, devicetree, Matthias Brugger
Provide thermal zone to read thermal sensor in the SoC. We can read all the
thermal sensors value in the SoC by the node /sys/class/thermal/
In mtk_thermal_bank_temperature, return -EAGAIN instead of -EACCESS
on the first read of sensor that often are bogus values.
This can avoid following warning on boot:
thermal thermal_zone6: failed to read out thermal zone (-13)
Signed-off-by: Michael Kao <michael.kao@mediatek.com>
Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/thermal/mtk_thermal.c | 104 ++++++++++++++++++++++++++++++++----------
1 file changed, 79 insertions(+), 25 deletions(-)
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index 3a5df1440822..311ad611fdab 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -259,6 +259,11 @@ enum mtk_thermal_version {
struct mtk_thermal;
+struct mtk_thermal_zone {
+ struct mtk_thermal *mt;
+ int id;
+};
+
struct thermal_bank_cfg {
unsigned int num_sensors;
const int *sensors;
@@ -307,6 +312,8 @@ struct mtk_thermal {
const struct mtk_thermal_data *conf;
struct mtk_thermal_bank banks[MAX_NUM_ZONES];
+
+ int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
};
/* MT8183 thermal sensor data */
@@ -709,6 +716,29 @@ static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
mutex_unlock(&mt->lock);
}
+static int _get_sensor_temp(struct mtk_thermal *mt, int id)
+{
+ u32 raw;
+ int temp;
+
+ const struct mtk_thermal_data *conf = mt->conf;
+
+ raw = readl(mt->thermal_base + conf->msr[id]);
+
+ temp = mt->raw_to_mcelsius(mt, id, raw);
+
+ /*
+ * The first read of a sensor often contains very high bogus
+ * temperature value. Filter these out so that the system does
+ * not immediately shut down.
+ */
+
+ if (temp > 200000)
+ return -EAGAIN;
+ else
+ return temp;
+}
+
/**
* mtk_thermal_bank_temperature - get the temperature of a bank
* @bank: The bank
@@ -721,26 +751,9 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
struct mtk_thermal *mt = bank->mt;
const struct mtk_thermal_data *conf = mt->conf;
int i, temp = INT_MIN, max = INT_MIN;
- u32 raw;
for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
- raw = readl(mt->thermal_base + conf->msr[i]);
-
- if (mt->conf->version == MTK_THERMAL_V1) {
- temp = raw_to_mcelsius_v1(
- mt, conf->bank_data[bank->id].sensors[i], raw);
- } else {
- temp = raw_to_mcelsius_v2(
- mt, conf->bank_data[bank->id].sensors[i], raw);
- }
-
- /*
- * The first read of a sensor often contains very high bogus
- * temperature value. Filter these out so that the system does
- * not immediately shut down.
- */
- if (temp > 200000)
- temp = 0;
+ temp = _get_sensor_temp(mt, i);
if (temp > max)
max = temp;
@@ -749,9 +762,10 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
return max;
}
-static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
+static int mtk_read_temp(struct thermal_zone_device *tzdev, int *temperature)
{
- struct mtk_thermal *mt = tz->devdata;
+ struct mtk_thermal_zone *tz = tzdev->devdata;
+ struct mtk_thermal *mt = tz->mt;
int i;
int tempmax = INT_MIN;
@@ -770,10 +784,28 @@ static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
return 0;
}
+static int mtk_read_sensor_temp(struct thermal_zone_device *tzdev, int *temperature)
+{
+ struct mtk_thermal_zone *tz = tzdev->devdata;
+ struct mtk_thermal *mt = tz->mt;
+ int id = tz->id - 1;
+
+ if (id < 0)
+ return -EACCES;
+
+ *temperature = _get_sensor_temp(mt, id);
+
+ return 0;
+}
+
static const struct thermal_zone_device_ops mtk_thermal_ops = {
.get_temp = mtk_read_temp,
};
+static const struct thermal_zone_device_ops mtk_thermal_sensor_ops = {
+ .get_temp = mtk_read_sensor_temp,
+};
+
static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
u32 apmixed_phys_base, u32 auxadc_phys_base,
int ctrl_id)
@@ -1072,6 +1104,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
u64 auxadc_phys_base, apmixed_phys_base;
struct thermal_zone_device *tzdev;
void __iomem *apmixed_base, *auxadc_base;
+ struct mtk_thermal_zone *tz;
mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
if (!mt)
@@ -1150,6 +1183,9 @@ static int mtk_thermal_probe(struct platform_device *pdev)
mtk_thermal_turn_on_buffer(mt, apmixed_base);
+ mt->raw_to_mcelsius = (mt->conf->version == MTK_THERMAL_V1) ?
+ raw_to_mcelsius_v1 : raw_to_mcelsius_v2;
+
if (mt->conf->version == MTK_THERMAL_V2) {
mtk_thermal_release_periodic_ts(mt, auxadc_base);
}
@@ -1161,11 +1197,29 @@ static int mtk_thermal_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mt);
- tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
- &mtk_thermal_ops);
- if (IS_ERR(tzdev)) {
- ret = PTR_ERR(tzdev);
- goto err_disable_clk_peri_therm;
+ for (i = 0; i < mt->conf->num_sensors + 1; i++) {
+ tz = devm_kmalloc(&pdev->dev, sizeof(*tz), GFP_KERNEL);
+ if (!tz)
+ return -ENOMEM;
+
+ tz->mt = mt;
+ tz->id = i;
+
+ tzdev = devm_thermal_of_zone_register(&pdev->dev, i, tz, (i == 0) ?
+ &mtk_thermal_ops :
+ &mtk_thermal_sensor_ops);
+
+ if (IS_ERR(tzdev)) {
+ if (PTR_ERR(tzdev) == -ENODEV) {
+ dev_warn(&pdev->dev,
+ "sensor %d not registered in thermal zone in dt\n", i);
+ continue;
+ }
+ if (PTR_ERR(tzdev) == -EACCES) {
+ ret = PTR_ERR(tzdev);
+ goto err_disable_clk_peri_therm;
+ }
+ }
}
ret = devm_thermal_add_hwmon_sysfs(tzdev);
--
b4 0.10.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors
2022-10-19 14:17 ` [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors Amjad Ouled-Ameur
@ 2022-10-22 17:03 ` Daniel Lezcano
2022-11-03 14:26 ` Amjad Ouled-Ameur
2022-11-15 10:49 ` Pin-yen Lin
1 sibling, 1 reply; 10+ messages in thread
From: Daniel Lezcano @ 2022-10-22 17:03 UTC (permalink / raw)
To: Amjad Ouled-Ameur, Krzysztof Kozlowski, Zhang Rui, Amit Kucheria,
Rob Herring, Rafael J. Wysocki
Cc: Fabien Parent, linux-mediatek, Rob Herring,
Markus Schneider-Pargmann, linux-arm-kernel, linux-pm,
AngeloGioacchino Del Regno, Michael Kao, Hsin-Yi Wang,
linux-kernel, devicetree, Matthias Brugger
On 19/10/2022 16:17, Amjad Ouled-Ameur wrote:
> Provide thermal zone to read thermal sensor in the SoC. We can read all the
> thermal sensors value in the SoC by the node /sys/class/thermal/
>
> In mtk_thermal_bank_temperature, return -EAGAIN instead of -EACCESS
> on the first read of sensor that often are bogus values.
> This can avoid following warning on boot:
>
> thermal thermal_zone6: failed to read out thermal zone (-13)
>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
> Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Overall the series looks good to me, however there is a couple of things
to fix. See below
> ---
> drivers/thermal/mtk_thermal.c | 104 ++++++++++++++++++++++++++++++++----------
> 1 file changed, 79 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
> index 3a5df1440822..311ad611fdab 100644
> --- a/drivers/thermal/mtk_thermal.c
> +++ b/drivers/thermal/mtk_thermal.c
> @@ -259,6 +259,11 @@ enum mtk_thermal_version {
>
> struct mtk_thermal;
>
> +struct mtk_thermal_zone {
> + struct mtk_thermal *mt;
> + int id;
> +};
Do you really need to create a new structure for that ?
> struct thermal_bank_cfg {
> unsigned int num_sensors;
> const int *sensors;
> @@ -307,6 +312,8 @@ struct mtk_thermal {
>
> const struct mtk_thermal_data *conf;
> struct mtk_thermal_bank banks[MAX_NUM_ZONES];
> +
> + int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
> };
>
> /* MT8183 thermal sensor data */
> @@ -709,6 +716,29 @@ static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
> mutex_unlock(&mt->lock);
> }
>
> +static int _get_sensor_temp(struct mtk_thermal *mt, int id)
> +{
> + u32 raw;
> + int temp;
> +
> + const struct mtk_thermal_data *conf = mt->conf;
> +
> + raw = readl(mt->thermal_base + conf->msr[id]);
> +
> + temp = mt->raw_to_mcelsius(mt, id, raw);
> +
> + /*
> + * The first read of a sensor often contains very high bogus
> + * temperature value. Filter these out so that the system does
> + * not immediately shut down.
> + */
> +
> + if (temp > 200000)
> + return -EAGAIN;
> + else
> + return temp;
> +}
> +
> /**
> * mtk_thermal_bank_temperature - get the temperature of a bank
> * @bank: The bank
> @@ -721,26 +751,9 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
> struct mtk_thermal *mt = bank->mt;
> const struct mtk_thermal_data *conf = mt->conf;
> int i, temp = INT_MIN, max = INT_MIN;
> - u32 raw;
>
> for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
> - raw = readl(mt->thermal_base + conf->msr[i]);
> -
> - if (mt->conf->version == MTK_THERMAL_V1) {
> - temp = raw_to_mcelsius_v1(
> - mt, conf->bank_data[bank->id].sensors[i], raw);
> - } else {
> - temp = raw_to_mcelsius_v2(
> - mt, conf->bank_data[bank->id].sensors[i], raw);
> - }
> -
> - /*
> - * The first read of a sensor often contains very high bogus
> - * temperature value. Filter these out so that the system does
> - * not immediately shut down.
> - */
> - if (temp > 200000)
> - temp = 0;
> + temp = _get_sensor_temp(mt, i);
>
> if (temp > max)
> max = temp;
> @@ -749,9 +762,10 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
> return max;
> }
>
> -static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
> +static int mtk_read_temp(struct thermal_zone_device *tzdev, int *temperature)
> {
> - struct mtk_thermal *mt = tz->devdata;
> + struct mtk_thermal_zone *tz = tzdev->devdata;
> + struct mtk_thermal *mt = tz->mt;
> int i;
> int tempmax = INT_MIN;
>
> @@ -770,10 +784,28 @@ static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
> return 0;
> }
>
> +static int mtk_read_sensor_temp(struct thermal_zone_device *tzdev, int *temperature)
> +{
> + struct mtk_thermal_zone *tz = tzdev->devdata;
> + struct mtk_thermal *mt = tz->mt;
> + int id = tz->id - 1;
> +
> + if (id < 0)
> + return -EACCES;
> +
> + *temperature = _get_sensor_temp(mt, id);
> +
> + return 0;
> +}
> +
> static const struct thermal_zone_device_ops mtk_thermal_ops = {
> .get_temp = mtk_read_temp,
> };
>
> +static const struct thermal_zone_device_ops mtk_thermal_sensor_ops = {
> + .get_temp = mtk_read_sensor_temp,
> +};
> +
> static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
> u32 apmixed_phys_base, u32 auxadc_phys_base,
> int ctrl_id)
> @@ -1072,6 +1104,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
> u64 auxadc_phys_base, apmixed_phys_base;
> struct thermal_zone_device *tzdev;
> void __iomem *apmixed_base, *auxadc_base;
> + struct mtk_thermal_zone *tz;
>
> mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
> if (!mt)
> @@ -1150,6 +1183,9 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>
> mtk_thermal_turn_on_buffer(mt, apmixed_base);
>
> + mt->raw_to_mcelsius = (mt->conf->version == MTK_THERMAL_V1) ?
> + raw_to_mcelsius_v1 : raw_to_mcelsius_v2;
> +
> if (mt->conf->version == MTK_THERMAL_V2) {
> mtk_thermal_release_periodic_ts(mt, auxadc_base);
> }
> @@ -1161,11 +1197,29 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, mt);
>
> - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
> - &mtk_thermal_ops);
> - if (IS_ERR(tzdev)) {
> - ret = PTR_ERR(tzdev);
> - goto err_disable_clk_peri_therm;
> + for (i = 0; i < mt->conf->num_sensors + 1; i++) {
> + tz = devm_kmalloc(&pdev->dev, sizeof(*tz), GFP_KERNEL);
> + if (!tz)
> + return -ENOMEM;
> +
> + tz->mt = mt;
> + tz->id = i;
> +
> + tzdev = devm_thermal_of_zone_register(&pdev->dev, i, tz, (i == 0) ?
> + &mtk_thermal_ops :
> + &mtk_thermal_sensor_ops);
We want to prevent the aggregation from the different sensors within a
driver. I know there is already a function doing that for the previous
sensor version but that is something we don't want to continue.
Using mtk_thermal_ops tries to overcome this.
Also, the userspace needs to know to which device a thermal zone is
related to. Here all the thermal zones have the same name so the
userspace does not know if it is the GPU, the CPU, the chassis, the NPU, ...
> +
> + if (IS_ERR(tzdev)) {
> + if (PTR_ERR(tzdev) == -ENODEV) {
> + dev_warn(&pdev->dev,
> + "sensor %d not registered in thermal zone in dt\n", i);
ENODEV is not considered an error, so the warning can be removed
> + continue;
> + }
> + if (PTR_ERR(tzdev) == -EACCES) {
When devm_thermal_of_zone_register() returns -EACCES ?
> + ret = PTR_ERR(tzdev);
> + goto err_disable_clk_peri_therm;
> + }
> + }
> }
>
> ret = devm_thermal_add_hwmon_sysfs(tzdev);
>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors
2022-10-22 17:03 ` Daniel Lezcano
@ 2022-11-03 14:26 ` Amjad Ouled-Ameur
2022-11-14 20:36 ` Amjad Ouled-Ameur
0 siblings, 1 reply; 10+ messages in thread
From: Amjad Ouled-Ameur @ 2022-11-03 14:26 UTC (permalink / raw)
To: Daniel Lezcano, Krzysztof Kozlowski, Zhang Rui, Amit Kucheria,
Rob Herring, Rafael J. Wysocki
Cc: Fabien Parent, linux-mediatek, Rob Herring,
Markus Schneider-Pargmann, linux-arm-kernel, linux-pm,
AngeloGioacchino Del Regno, Michael Kao, Hsin-Yi Wang,
linux-kernel, devicetree, Matthias Brugger
Hi Daniel,
Thank you for the review.
On 10/22/22 19:03, Daniel Lezcano wrote:
> On 19/10/2022 16:17, Amjad Ouled-Ameur wrote:
>> Provide thermal zone to read thermal sensor in the SoC. We can read all the
>> thermal sensors value in the SoC by the node /sys/class/thermal/
>>
>> In mtk_thermal_bank_temperature, return -EAGAIN instead of -EACCESS
>> on the first read of sensor that often are bogus values.
>> This can avoid following warning on boot:
>>
>> thermal thermal_zone6: failed to read out thermal zone (-13)
>>
>> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
>> Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
>> Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
>> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>
> Overall the series looks good to me, however there is a couple of things to fix. See below
>
>> ---
>> drivers/thermal/mtk_thermal.c | 104 ++++++++++++++++++++++++++++++++----------
>> 1 file changed, 79 insertions(+), 25 deletions(-)
>>
>> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
>> index 3a5df1440822..311ad611fdab 100644
>> --- a/drivers/thermal/mtk_thermal.c
>> +++ b/drivers/thermal/mtk_thermal.c
>> @@ -259,6 +259,11 @@ enum mtk_thermal_version {
>> struct mtk_thermal;
>> +struct mtk_thermal_zone {
>> + struct mtk_thermal *mt;
>> + int id;
>> +};
>
> Do you really need to create a new structure for that ?
We need to store the sensor index in the private data, along with mtk_thermal.
Aside from having this new structure, I don't see how .get_temp() can tell which
sensor index to read.
>
>> struct thermal_bank_cfg {
>> unsigned int num_sensors;
>> const int *sensors;
>> @@ -307,6 +312,8 @@ struct mtk_thermal {
>> const struct mtk_thermal_data *conf;
>> struct mtk_thermal_bank banks[MAX_NUM_ZONES];
>> +
>> + int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
>> };
>> /* MT8183 thermal sensor data */
>> @@ -709,6 +716,29 @@ static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
>> mutex_unlock(&mt->lock);
>> }
>> +static int _get_sensor_temp(struct mtk_thermal *mt, int id)
>> +{
>> + u32 raw;
>> + int temp;
>> +
>> + const struct mtk_thermal_data *conf = mt->conf;
>> +
>> + raw = readl(mt->thermal_base + conf->msr[id]);
>> +
>> + temp = mt->raw_to_mcelsius(mt, id, raw);
>> +
>> + /*
>> + * The first read of a sensor often contains very high bogus
>> + * temperature value. Filter these out so that the system does
>> + * not immediately shut down.
>> + */
>> +
>> + if (temp > 200000)
>> + return -EAGAIN;
>> + else
>> + return temp;
>> +}
>> +
>> /**
>> * mtk_thermal_bank_temperature - get the temperature of a bank
>> * @bank: The bank
>> @@ -721,26 +751,9 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
>> struct mtk_thermal *mt = bank->mt;
>> const struct mtk_thermal_data *conf = mt->conf;
>> int i, temp = INT_MIN, max = INT_MIN;
>> - u32 raw;
>> for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
>> - raw = readl(mt->thermal_base + conf->msr[i]);
>> -
>> - if (mt->conf->version == MTK_THERMAL_V1) {
>> - temp = raw_to_mcelsius_v1(
>> - mt, conf->bank_data[bank->id].sensors[i], raw);
>> - } else {
>> - temp = raw_to_mcelsius_v2(
>> - mt, conf->bank_data[bank->id].sensors[i], raw);
>> - }
>> -
>> - /*
>> - * The first read of a sensor often contains very high bogus
>> - * temperature value. Filter these out so that the system does
>> - * not immediately shut down.
>> - */
>> - if (temp > 200000)
>> - temp = 0;
>> + temp = _get_sensor_temp(mt, i);
>> if (temp > max)
>> max = temp;
>> @@ -749,9 +762,10 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
>> return max;
>> }
>> -static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
>> +static int mtk_read_temp(struct thermal_zone_device *tzdev, int *temperature)
>> {
>> - struct mtk_thermal *mt = tz->devdata;
>> + struct mtk_thermal_zone *tz = tzdev->devdata;
>> + struct mtk_thermal *mt = tz->mt;
>> int i;
>> int tempmax = INT_MIN;
>> @@ -770,10 +784,28 @@ static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
>> return 0;
>> }
>> +static int mtk_read_sensor_temp(struct thermal_zone_device *tzdev, int *temperature)
>> +{
>> + struct mtk_thermal_zone *tz = tzdev->devdata;
>> + struct mtk_thermal *mt = tz->mt;
>> + int id = tz->id - 1;
>> +
>> + if (id < 0)
>> + return -EACCES;
>> +
>> + *temperature = _get_sensor_temp(mt, id);
>> +
>> + return 0;
>> +}
>> +
>> static const struct thermal_zone_device_ops mtk_thermal_ops = {
>> .get_temp = mtk_read_temp,
>> };
>> +static const struct thermal_zone_device_ops mtk_thermal_sensor_ops = {
>> + .get_temp = mtk_read_sensor_temp,
>> +};
>> +
>> static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
>> u32 apmixed_phys_base, u32 auxadc_phys_base,
>> int ctrl_id)
>> @@ -1072,6 +1104,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>> u64 auxadc_phys_base, apmixed_phys_base;
>> struct thermal_zone_device *tzdev;
>> void __iomem *apmixed_base, *auxadc_base;
>> + struct mtk_thermal_zone *tz;
>> mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
>> if (!mt)
>> @@ -1150,6 +1183,9 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>> mtk_thermal_turn_on_buffer(mt, apmixed_base);
>> + mt->raw_to_mcelsius = (mt->conf->version == MTK_THERMAL_V1) ?
>> + raw_to_mcelsius_v1 : raw_to_mcelsius_v2;
>> +
>> if (mt->conf->version == MTK_THERMAL_V2) {
>> mtk_thermal_release_periodic_ts(mt, auxadc_base);
>> }
>> @@ -1161,11 +1197,29 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>> platform_set_drvdata(pdev, mt);
>> - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
>> - &mtk_thermal_ops);
>> - if (IS_ERR(tzdev)) {
>> - ret = PTR_ERR(tzdev);
>> - goto err_disable_clk_peri_therm;
>> + for (i = 0; i < mt->conf->num_sensors + 1; i++) {
>> + tz = devm_kmalloc(&pdev->dev, sizeof(*tz), GFP_KERNEL);
>> + if (!tz)
>> + return -ENOMEM;
>> +
>> + tz->mt = mt;
>> + tz->id = i;
>> +
>> + tzdev = devm_thermal_of_zone_register(&pdev->dev, i, tz, (i == 0) ?
>> + &mtk_thermal_ops :
>> + &mtk_thermal_sensor_ops);
>
> We want to prevent the aggregation from the different sensors within a driver. I know there is already a function doing that for the previous sensor version but that is something we don't want to continue.
>
> Using mtk_thermal_ops tries to overcome this.
>
So would it be more proper to have to distinct thermal drivers for each sensor ? Or relatively to the above implementation,
I think it might be better to have only one thermal_zone_device_ops, with storing the right get_temp callback in mtk_thermal_zone structure.
> Also, the userspace needs to know to which device a thermal zone is related to. Here all the thermal zones have the same name so the userspace does not know if it is the GPU, the CPU, the chassis, the NPU, ...
Which names are you referring to ? In case it is "sys/class/thermal/*/type", it is based on DT thermal nodes, the first sensor is marked as CPU-related,
The others are used for debugging purposes only.
>
>
>> +
>> + if (IS_ERR(tzdev)) {
>> + if (PTR_ERR(tzdev) == -ENODEV) {
>> + dev_warn(&pdev->dev,
>> + "sensor %d not registered in thermal zone in dt\n", i);
>
> ENODEV is not considered an error, so the warning can be removed
Agreed, will drop this.
>
>> + continue;
>> + }
>> + if (PTR_ERR(tzdev) == -EACCES) {
>
> When devm_thermal_of_zone_register() returns -EACCES ?
Right, I verified the code, -EACCES is never returned by devm_thermal_of_zone_register().
Regards,
Amjad
>
>> + ret = PTR_ERR(tzdev);
>> + goto err_disable_clk_peri_therm;
>> + }
>> + }
>> }
>> ret = devm_thermal_add_hwmon_sysfs(tzdev);
>>
>
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors
2022-11-03 14:26 ` Amjad Ouled-Ameur
@ 2022-11-14 20:36 ` Amjad Ouled-Ameur
0 siblings, 0 replies; 10+ messages in thread
From: Amjad Ouled-Ameur @ 2022-11-14 20:36 UTC (permalink / raw)
To: Daniel Lezcano, Krzysztof Kozlowski, Zhang Rui, Amit Kucheria,
Rob Herring, Rafael J. Wysocki
Cc: Fabien Parent, linux-mediatek, Rob Herring,
Markus Schneider-Pargmann, linux-arm-kernel, linux-pm,
AngeloGioacchino Del Regno, Michael Kao, Hsin-Yi Wang,
linux-kernel, devicetree, Matthias Brugger
Hi Daniel,
Do you have any feedback about my comments on your review before I send V7 ?
Regards,
Amjad
On 11/3/22 15:26, Amjad Ouled-Ameur wrote:
> Hi Daniel,
>
> Thank you for the review.
>
> On 10/22/22 19:03, Daniel Lezcano wrote:
>> On 19/10/2022 16:17, Amjad Ouled-Ameur wrote:
>>> Provide thermal zone to read thermal sensor in the SoC. We can read all the
>>> thermal sensors value in the SoC by the node /sys/class/thermal/
>>>
>>> In mtk_thermal_bank_temperature, return -EAGAIN instead of -EACCESS
>>> on the first read of sensor that often are bogus values.
>>> This can avoid following warning on boot:
>>>
>>> thermal thermal_zone6: failed to read out thermal zone (-13)
>>>
>>> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
>>> Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
>>> Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
>>> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>>
>> Overall the series looks good to me, however there is a couple of things to fix. See below
>>
>>> ---
>>> drivers/thermal/mtk_thermal.c | 104 ++++++++++++++++++++++++++++++++----------
>>> 1 file changed, 79 insertions(+), 25 deletions(-)
>>>
>>> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
>>> index 3a5df1440822..311ad611fdab 100644
>>> --- a/drivers/thermal/mtk_thermal.c
>>> +++ b/drivers/thermal/mtk_thermal.c
>>> @@ -259,6 +259,11 @@ enum mtk_thermal_version {
>>> struct mtk_thermal;
>>> +struct mtk_thermal_zone {
>>> + struct mtk_thermal *mt;
>>> + int id;
>>> +};
>>
>> Do you really need to create a new structure for that ?
>
> We need to store the sensor index in the private data, along with mtk_thermal.
>
> Aside from having this new structure, I don't see how .get_temp() can tell which
>
> sensor index to read.
>
>>
>>> struct thermal_bank_cfg {
>>> unsigned int num_sensors;
>>> const int *sensors;
>>> @@ -307,6 +312,8 @@ struct mtk_thermal {
>>> const struct mtk_thermal_data *conf;
>>> struct mtk_thermal_bank banks[MAX_NUM_ZONES];
>>> +
>>> + int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
>>> };
>>> /* MT8183 thermal sensor data */
>>> @@ -709,6 +716,29 @@ static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
>>> mutex_unlock(&mt->lock);
>>> }
>>> +static int _get_sensor_temp(struct mtk_thermal *mt, int id)
>>> +{
>>> + u32 raw;
>>> + int temp;
>>> +
>>> + const struct mtk_thermal_data *conf = mt->conf;
>>> +
>>> + raw = readl(mt->thermal_base + conf->msr[id]);
>>> +
>>> + temp = mt->raw_to_mcelsius(mt, id, raw);
>>> +
>>> + /*
>>> + * The first read of a sensor often contains very high bogus
>>> + * temperature value. Filter these out so that the system does
>>> + * not immediately shut down.
>>> + */
>>> +
>>> + if (temp > 200000)
>>> + return -EAGAIN;
>>> + else
>>> + return temp;
>>> +}
>>> +
>>> /**
>>> * mtk_thermal_bank_temperature - get the temperature of a bank
>>> * @bank: The bank
>>> @@ -721,26 +751,9 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
>>> struct mtk_thermal *mt = bank->mt;
>>> const struct mtk_thermal_data *conf = mt->conf;
>>> int i, temp = INT_MIN, max = INT_MIN;
>>> - u32 raw;
>>> for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
>>> - raw = readl(mt->thermal_base + conf->msr[i]);
>>> -
>>> - if (mt->conf->version == MTK_THERMAL_V1) {
>>> - temp = raw_to_mcelsius_v1(
>>> - mt, conf->bank_data[bank->id].sensors[i], raw);
>>> - } else {
>>> - temp = raw_to_mcelsius_v2(
>>> - mt, conf->bank_data[bank->id].sensors[i], raw);
>>> - }
>>> -
>>> - /*
>>> - * The first read of a sensor often contains very high bogus
>>> - * temperature value. Filter these out so that the system does
>>> - * not immediately shut down.
>>> - */
>>> - if (temp > 200000)
>>> - temp = 0;
>>> + temp = _get_sensor_temp(mt, i);
>>> if (temp > max)
>>> max = temp;
>>> @@ -749,9 +762,10 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
>>> return max;
>>> }
>>> -static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
>>> +static int mtk_read_temp(struct thermal_zone_device *tzdev, int *temperature)
>>> {
>>> - struct mtk_thermal *mt = tz->devdata;
>>> + struct mtk_thermal_zone *tz = tzdev->devdata;
>>> + struct mtk_thermal *mt = tz->mt;
>>> int i;
>>> int tempmax = INT_MIN;
>>> @@ -770,10 +784,28 @@ static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
>>> return 0;
>>> }
>>> +static int mtk_read_sensor_temp(struct thermal_zone_device *tzdev, int *temperature)
>>> +{
>>> + struct mtk_thermal_zone *tz = tzdev->devdata;
>>> + struct mtk_thermal *mt = tz->mt;
>>> + int id = tz->id - 1;
>>> +
>>> + if (id < 0)
>>> + return -EACCES;
>>> +
>>> + *temperature = _get_sensor_temp(mt, id);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct thermal_zone_device_ops mtk_thermal_ops = {
>>> .get_temp = mtk_read_temp,
>>> };
>>> +static const struct thermal_zone_device_ops mtk_thermal_sensor_ops = {
>>> + .get_temp = mtk_read_sensor_temp,
>>> +};
>>> +
>>> static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
>>> u32 apmixed_phys_base, u32 auxadc_phys_base,
>>> int ctrl_id)
>>> @@ -1072,6 +1104,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>>> u64 auxadc_phys_base, apmixed_phys_base;
>>> struct thermal_zone_device *tzdev;
>>> void __iomem *apmixed_base, *auxadc_base;
>>> + struct mtk_thermal_zone *tz;
>>> mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
>>> if (!mt)
>>> @@ -1150,6 +1183,9 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>>> mtk_thermal_turn_on_buffer(mt, apmixed_base);
>>> + mt->raw_to_mcelsius = (mt->conf->version == MTK_THERMAL_V1) ?
>>> + raw_to_mcelsius_v1 : raw_to_mcelsius_v2;
>>> +
>>> if (mt->conf->version == MTK_THERMAL_V2) {
>>> mtk_thermal_release_periodic_ts(mt, auxadc_base);
>>> }
>>> @@ -1161,11 +1197,29 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>>> platform_set_drvdata(pdev, mt);
>>> - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
>>> - &mtk_thermal_ops);
>>> - if (IS_ERR(tzdev)) {
>>> - ret = PTR_ERR(tzdev);
>>> - goto err_disable_clk_peri_therm;
>>> + for (i = 0; i < mt->conf->num_sensors + 1; i++) {
>>> + tz = devm_kmalloc(&pdev->dev, sizeof(*tz), GFP_KERNEL);
>>> + if (!tz)
>>> + return -ENOMEM;
>>> +
>>> + tz->mt = mt;
>>> + tz->id = i;
>>> +
>>> + tzdev = devm_thermal_of_zone_register(&pdev->dev, i, tz, (i == 0) ?
>>> + &mtk_thermal_ops :
>>> + &mtk_thermal_sensor_ops);
>>
>> We want to prevent the aggregation from the different sensors within a driver. I know there is already a function doing that for the previous sensor version but that is something we don't want to continue.
>>
>> Using mtk_thermal_ops tries to overcome this.
>>
> So would it be more proper to have to distinct thermal drivers for each sensor ? Or relatively to the above implementation,
>
> I think it might be better to have only one thermal_zone_device_ops, with storing the right get_temp callback in mtk_thermal_zone structure.
>
>
>> Also, the userspace needs to know to which device a thermal zone is related to. Here all the thermal zones have the same name so the userspace does not know if it is the GPU, the CPU, the chassis, the NPU, ...
>
> Which names are you referring to ? In case it is "sys/class/thermal/*/type", it is based on DT thermal nodes, the first sensor is marked as CPU-related,
>
> The others are used for debugging purposes only.
>
>>
>>
>>> +
>>> + if (IS_ERR(tzdev)) {
>>> + if (PTR_ERR(tzdev) == -ENODEV) {
>>> + dev_warn(&pdev->dev,
>>> + "sensor %d not registered in thermal zone in dt\n", i);
>>
>> ENODEV is not considered an error, so the warning can be removed
> Agreed, will drop this.
>>
>>> + continue;
>>> + }
>>> + if (PTR_ERR(tzdev) == -EACCES) {
>>
>> When devm_thermal_of_zone_register() returns -EACCES ?
>
> Right, I verified the code, -EACCES is never returned by devm_thermal_of_zone_register().
>
>
> Regards,
>
> Amjad
>
>>
>>> + ret = PTR_ERR(tzdev);
>>> + goto err_disable_clk_peri_therm;
>>> + }
>>> + }
>>> }
>>> ret = devm_thermal_add_hwmon_sysfs(tzdev);
>>>
>>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors
2022-10-19 14:17 ` [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors Amjad Ouled-Ameur
2022-10-22 17:03 ` Daniel Lezcano
@ 2022-11-15 10:49 ` Pin-yen Lin
2022-11-15 13:46 ` Amjad Ouled-Ameur
1 sibling, 1 reply; 10+ messages in thread
From: Pin-yen Lin @ 2022-11-15 10:49 UTC (permalink / raw)
To: Amjad Ouled-Ameur
Cc: Krzysztof Kozlowski, Zhang Rui, Amit Kucheria, Rob Herring,
Rafael J. Wysocki, Daniel Lezcano, Fabien Parent, linux-mediatek,
Rob Herring, Markus Schneider-Pargmann, linux-arm-kernel,
linux-pm, AngeloGioacchino Del Regno, Michael Kao, Hsin-Yi Wang,
linux-kernel, devicetree, Matthias Brugger
Hi Amjad,
On Wed, Oct 19, 2022 at 10:17 PM Amjad Ouled-Ameur
<aouledameur@baylibre.com> wrote:
>
> Provide thermal zone to read thermal sensor in the SoC. We can read all the
> thermal sensors value in the SoC by the node /sys/class/thermal/
>
> In mtk_thermal_bank_temperature, return -EAGAIN instead of -EACCESS
> on the first read of sensor that often are bogus values.
> This can avoid following warning on boot:
>
> thermal thermal_zone6: failed to read out thermal zone (-13)
>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
> Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
> drivers/thermal/mtk_thermal.c | 104 ++++++++++++++++++++++++++++++++----------
> 1 file changed, 79 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
> index 3a5df1440822..311ad611fdab 100644
> --- a/drivers/thermal/mtk_thermal.c
> +++ b/drivers/thermal/mtk_thermal.c
> @@ -259,6 +259,11 @@ enum mtk_thermal_version {
>
> struct mtk_thermal;
>
> +struct mtk_thermal_zone {
> + struct mtk_thermal *mt;
> + int id;
> +};
> +
> struct thermal_bank_cfg {
> unsigned int num_sensors;
> const int *sensors;
> @@ -307,6 +312,8 @@ struct mtk_thermal {
>
> const struct mtk_thermal_data *conf;
> struct mtk_thermal_bank banks[MAX_NUM_ZONES];
> +
> + int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
> };
>
> /* MT8183 thermal sensor data */
> @@ -709,6 +716,29 @@ static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
> mutex_unlock(&mt->lock);
> }
>
> +static int _get_sensor_temp(struct mtk_thermal *mt, int id)
> +{
> + u32 raw;
> + int temp;
> +
> + const struct mtk_thermal_data *conf = mt->conf;
> +
> + raw = readl(mt->thermal_base + conf->msr[id]);
> +
> + temp = mt->raw_to_mcelsius(mt, id, raw);
> +
> + /*
> + * The first read of a sensor often contains very high bogus
> + * temperature value. Filter these out so that the system does
> + * not immediately shut down.
> + */
> +
> + if (temp > 200000)
> + return -EAGAIN;
> + else
> + return temp;
> +}
> +
> /**
> * mtk_thermal_bank_temperature - get the temperature of a bank
> * @bank: The bank
> @@ -721,26 +751,9 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
> struct mtk_thermal *mt = bank->mt;
> const struct mtk_thermal_data *conf = mt->conf;
> int i, temp = INT_MIN, max = INT_MIN;
> - u32 raw;
>
> for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
> - raw = readl(mt->thermal_base + conf->msr[i]);
> -
> - if (mt->conf->version == MTK_THERMAL_V1) {
> - temp = raw_to_mcelsius_v1(
> - mt, conf->bank_data[bank->id].sensors[i], raw);
> - } else {
> - temp = raw_to_mcelsius_v2(
> - mt, conf->bank_data[bank->id].sensors[i], raw);
> - }
> -
> - /*
> - * The first read of a sensor often contains very high bogus
> - * temperature value. Filter these out so that the system does
> - * not immediately shut down.
> - */
> - if (temp > 200000)
> - temp = 0;
> + temp = _get_sensor_temp(mt, i);
>
> if (temp > max)
> max = temp;
> @@ -749,9 +762,10 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
> return max;
> }
>
> -static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
> +static int mtk_read_temp(struct thermal_zone_device *tzdev, int *temperature)
> {
> - struct mtk_thermal *mt = tz->devdata;
> + struct mtk_thermal_zone *tz = tzdev->devdata;
> + struct mtk_thermal *mt = tz->mt;
> int i;
> int tempmax = INT_MIN;
>
> @@ -770,10 +784,28 @@ static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
> return 0;
> }
>
> +static int mtk_read_sensor_temp(struct thermal_zone_device *tzdev, int *temperature)
> +{
> + struct mtk_thermal_zone *tz = tzdev->devdata;
> + struct mtk_thermal *mt = tz->mt;
> + int id = tz->id - 1;
> +
> + if (id < 0)
> + return -EACCES;
> +
> + *temperature = _get_sensor_temp(mt, id);
> +
> + return 0;
> +}
> +
> static const struct thermal_zone_device_ops mtk_thermal_ops = {
> .get_temp = mtk_read_temp,
> };
>
> +static const struct thermal_zone_device_ops mtk_thermal_sensor_ops = {
> + .get_temp = mtk_read_sensor_temp,
> +};
> +
> static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
> u32 apmixed_phys_base, u32 auxadc_phys_base,
> int ctrl_id)
> @@ -1072,6 +1104,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
> u64 auxadc_phys_base, apmixed_phys_base;
> struct thermal_zone_device *tzdev;
> void __iomem *apmixed_base, *auxadc_base;
> + struct mtk_thermal_zone *tz;
>
> mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
> if (!mt)
> @@ -1150,6 +1183,9 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>
> mtk_thermal_turn_on_buffer(mt, apmixed_base);
>
> + mt->raw_to_mcelsius = (mt->conf->version == MTK_THERMAL_V1) ?
> + raw_to_mcelsius_v1 : raw_to_mcelsius_v2;
> +
> if (mt->conf->version == MTK_THERMAL_V2) {
> mtk_thermal_release_periodic_ts(mt, auxadc_base);
> }
> @@ -1161,11 +1197,29 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, mt);
>
> - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
> - &mtk_thermal_ops);
> - if (IS_ERR(tzdev)) {
> - ret = PTR_ERR(tzdev);
> - goto err_disable_clk_peri_therm;
> + for (i = 0; i < mt->conf->num_sensors + 1; i++) {
> + tz = devm_kmalloc(&pdev->dev, sizeof(*tz), GFP_KERNEL);
> + if (!tz)
> + return -ENOMEM;
> +
> + tz->mt = mt;
> + tz->id = i;
> +
> + tzdev = devm_thermal_of_zone_register(&pdev->dev, i, tz, (i == 0) ?
> + &mtk_thermal_ops :
> + &mtk_thermal_sensor_ops);
> +
> + if (IS_ERR(tzdev)) {
> + if (PTR_ERR(tzdev) == -ENODEV) {
> + dev_warn(&pdev->dev,
> + "sensor %d not registered in thermal zone in dt\n", i);
> + continue;
> + }
> + if (PTR_ERR(tzdev) == -EACCES) {
> + ret = PTR_ERR(tzdev);
> + goto err_disable_clk_peri_therm;
> + }
> + }
> }
>
> ret = devm_thermal_add_hwmon_sysfs(tzdev);
tzdev can be an error pointer here. I think we should move the line
into the loop above, so hwmon sysfs is not added when IS_ERR(tzdev) ==
true.
Regards,
Pin-yen
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v6 4/4] thermal: mediatek: add another get_temp ops for thermal sensors
2022-11-15 10:49 ` Pin-yen Lin
@ 2022-11-15 13:46 ` Amjad Ouled-Ameur
0 siblings, 0 replies; 10+ messages in thread
From: Amjad Ouled-Ameur @ 2022-11-15 13:46 UTC (permalink / raw)
To: Pin-yen Lin
Cc: Krzysztof Kozlowski, Zhang Rui, Amit Kucheria, Rob Herring,
Rafael J. Wysocki, Daniel Lezcano, Fabien Parent, linux-mediatek,
Rob Herring, Markus Schneider-Pargmann, linux-arm-kernel,
linux-pm, AngeloGioacchino Del Regno, Michael Kao, Hsin-Yi Wang,
linux-kernel, devicetree, Matthias Brugger
Hi Pin-yen,
On 11/15/22 11:49, Pin-yen Lin wrote:
> Hi Amjad,
>
> On Wed, Oct 19, 2022 at 10:17 PM Amjad Ouled-Ameur
> <aouledameur@baylibre.com> wrote:
>> Provide thermal zone to read thermal sensor in the SoC. We can read all the
>> thermal sensors value in the SoC by the node /sys/class/thermal/
>>
>> In mtk_thermal_bank_temperature, return -EAGAIN instead of -EACCESS
>> on the first read of sensor that often are bogus values.
>> This can avoid following warning on boot:
>>
>> thermal thermal_zone6: failed to read out thermal zone (-13)
>>
>> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
>> Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
>> Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
>> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> ---
>> drivers/thermal/mtk_thermal.c | 104 ++++++++++++++++++++++++++++++++----------
>> 1 file changed, 79 insertions(+), 25 deletions(-)
>>
>> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
>> index 3a5df1440822..311ad611fdab 100644
>> --- a/drivers/thermal/mtk_thermal.c
>> +++ b/drivers/thermal/mtk_thermal.c
>> @@ -259,6 +259,11 @@ enum mtk_thermal_version {
>>
>> struct mtk_thermal;
>>
>> +struct mtk_thermal_zone {
>> + struct mtk_thermal *mt;
>> + int id;
>> +};
>> +
>> struct thermal_bank_cfg {
>> unsigned int num_sensors;
>> const int *sensors;
>> @@ -307,6 +312,8 @@ struct mtk_thermal {
>>
>> const struct mtk_thermal_data *conf;
>> struct mtk_thermal_bank banks[MAX_NUM_ZONES];
>> +
>> + int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
>> };
>>
>> /* MT8183 thermal sensor data */
>> @@ -709,6 +716,29 @@ static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
>> mutex_unlock(&mt->lock);
>> }
>>
>> +static int _get_sensor_temp(struct mtk_thermal *mt, int id)
>> +{
>> + u32 raw;
>> + int temp;
>> +
>> + const struct mtk_thermal_data *conf = mt->conf;
>> +
>> + raw = readl(mt->thermal_base + conf->msr[id]);
>> +
>> + temp = mt->raw_to_mcelsius(mt, id, raw);
>> +
>> + /*
>> + * The first read of a sensor often contains very high bogus
>> + * temperature value. Filter these out so that the system does
>> + * not immediately shut down.
>> + */
>> +
>> + if (temp > 200000)
>> + return -EAGAIN;
>> + else
>> + return temp;
>> +}
>> +
>> /**
>> * mtk_thermal_bank_temperature - get the temperature of a bank
>> * @bank: The bank
>> @@ -721,26 +751,9 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
>> struct mtk_thermal *mt = bank->mt;
>> const struct mtk_thermal_data *conf = mt->conf;
>> int i, temp = INT_MIN, max = INT_MIN;
>> - u32 raw;
>>
>> for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
>> - raw = readl(mt->thermal_base + conf->msr[i]);
>> -
>> - if (mt->conf->version == MTK_THERMAL_V1) {
>> - temp = raw_to_mcelsius_v1(
>> - mt, conf->bank_data[bank->id].sensors[i], raw);
>> - } else {
>> - temp = raw_to_mcelsius_v2(
>> - mt, conf->bank_data[bank->id].sensors[i], raw);
>> - }
>> -
>> - /*
>> - * The first read of a sensor often contains very high bogus
>> - * temperature value. Filter these out so that the system does
>> - * not immediately shut down.
>> - */
>> - if (temp > 200000)
>> - temp = 0;
>> + temp = _get_sensor_temp(mt, i);
>>
>> if (temp > max)
>> max = temp;
>> @@ -749,9 +762,10 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
>> return max;
>> }
>>
>> -static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
>> +static int mtk_read_temp(struct thermal_zone_device *tzdev, int *temperature)
>> {
>> - struct mtk_thermal *mt = tz->devdata;
>> + struct mtk_thermal_zone *tz = tzdev->devdata;
>> + struct mtk_thermal *mt = tz->mt;
>> int i;
>> int tempmax = INT_MIN;
>>
>> @@ -770,10 +784,28 @@ static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
>> return 0;
>> }
>>
>> +static int mtk_read_sensor_temp(struct thermal_zone_device *tzdev, int *temperature)
>> +{
>> + struct mtk_thermal_zone *tz = tzdev->devdata;
>> + struct mtk_thermal *mt = tz->mt;
>> + int id = tz->id - 1;
>> +
>> + if (id < 0)
>> + return -EACCES;
>> +
>> + *temperature = _get_sensor_temp(mt, id);
>> +
>> + return 0;
>> +}
>> +
>> static const struct thermal_zone_device_ops mtk_thermal_ops = {
>> .get_temp = mtk_read_temp,
>> };
>>
>> +static const struct thermal_zone_device_ops mtk_thermal_sensor_ops = {
>> + .get_temp = mtk_read_sensor_temp,
>> +};
>> +
>> static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
>> u32 apmixed_phys_base, u32 auxadc_phys_base,
>> int ctrl_id)
>> @@ -1072,6 +1104,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>> u64 auxadc_phys_base, apmixed_phys_base;
>> struct thermal_zone_device *tzdev;
>> void __iomem *apmixed_base, *auxadc_base;
>> + struct mtk_thermal_zone *tz;
>>
>> mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
>> if (!mt)
>> @@ -1150,6 +1183,9 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>>
>> mtk_thermal_turn_on_buffer(mt, apmixed_base);
>>
>> + mt->raw_to_mcelsius = (mt->conf->version == MTK_THERMAL_V1) ?
>> + raw_to_mcelsius_v1 : raw_to_mcelsius_v2;
>> +
>> if (mt->conf->version == MTK_THERMAL_V2) {
>> mtk_thermal_release_periodic_ts(mt, auxadc_base);
>> }
>> @@ -1161,11 +1197,29 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>>
>> platform_set_drvdata(pdev, mt);
>>
>> - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
>> - &mtk_thermal_ops);
>> - if (IS_ERR(tzdev)) {
>> - ret = PTR_ERR(tzdev);
>> - goto err_disable_clk_peri_therm;
>> + for (i = 0; i < mt->conf->num_sensors + 1; i++) {
>> + tz = devm_kmalloc(&pdev->dev, sizeof(*tz), GFP_KERNEL);
>> + if (!tz)
>> + return -ENOMEM;
>> +
>> + tz->mt = mt;
>> + tz->id = i;
>> +
>> + tzdev = devm_thermal_of_zone_register(&pdev->dev, i, tz, (i == 0) ?
>> + &mtk_thermal_ops :
>> + &mtk_thermal_sensor_ops);
>> +
>> + if (IS_ERR(tzdev)) {
>> + if (PTR_ERR(tzdev) == -ENODEV) {
>> + dev_warn(&pdev->dev,
>> + "sensor %d not registered in thermal zone in dt\n", i);
>> + continue;
>> + }
>> + if (PTR_ERR(tzdev) == -EACCES) {
>> + ret = PTR_ERR(tzdev);
>> + goto err_disable_clk_peri_therm;
>> + }
>> + }
>> }
>>
>> ret = devm_thermal_add_hwmon_sysfs(tzdev);
> tzdev can be an error pointer here. I think we should move the line
> into the loop above, so hwmon sysfs is not added when IS_ERR(tzdev) ==
> true.
Good catch, will fix this in next rev.
Regards,
Amjad
> Regards,
> Pin-yen
^ permalink raw reply [flat|nested] 10+ messages in thread