Add thermal binding doc for Freescale's i.MX8MP Thermal Monitoring Unit.
Signed-off-by: Anson Huang <[email protected]>
---
Documentation/devicetree/bindings/thermal/imx8mm-thermal.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/thermal/imx8mm-thermal.txt b/Documentation/devicetree/bindings/thermal/imx8mm-thermal.txt
index d09ae82..3629d3c 100644
--- a/Documentation/devicetree/bindings/thermal/imx8mm-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/imx8mm-thermal.txt
@@ -1,10 +1,10 @@
* Thermal Monitoring Unit (TMU) on Freescale i.MX8MM SoC
Required properties:
-- compatible : Must be "fsl,imx8mm-tmu".
+- compatible : Must be "fsl,imx8mm-tmu" or "fsl,imx8mp-tmu".
- reg : Address range of TMU registers.
- clocks : TMU's clock source.
-- #thermal-sensor-cells : Should be 0. See ./thermal.txt for a description.
+- #thermal-sensor-cells : Should be 0 or 1. See ./thermal.txt for a description.
Example:
tmu: tmu@30260000 {
--
2.7.4
i.MX8MP shares same TMU with i.MX8MM, the only difference is i.MX8MP
has two thermal sensors while i.MX8MM ONLY has one, add multiple sensors
support for i.MX8MM TMU driver.
Signed-off-by: Anson Huang <[email protected]>
---
drivers/thermal/imx8mm_thermal.c | 108 +++++++++++++++++++++++++++++++++------
1 file changed, 93 insertions(+), 15 deletions(-)
diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c
index d597ceb..8a87ed0 100644
--- a/drivers/thermal/imx8mm_thermal.c
+++ b/drivers/thermal/imx8mm_thermal.c
@@ -10,34 +10,75 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/thermal.h>
#include "thermal_core.h"
#define TER 0x0 /* TMU enable */
+#define TPS 0x4
#define TRITSR 0x20 /* TMU immediate temp */
#define TER_EN BIT(31)
#define TRITSR_VAL_MASK 0xff
-#define TEMP_LOW_LIMIT 10
+#define PROBE_SEL_ALL GENMASK(31, 30)
-struct imx8mm_tmu {
+#define PROBE0_STATUS_OFFSET 30
+#define PROBE0_VAL_OFFSET 16
+#define SIGN_BIT BIT(7)
+#define TEMP_VAL_MASK GENMASK(6, 0)
+
+#define VER1_TEMP_LOW_LIMIT 10
+#define VER2_TEMP_LOW_LIMIT -40
+#define VER2_TEMP_HIGH_LIMIT 125
+
+#define TMU_VER1 0x1
+#define TMU_VER2 0x2
+
+struct thermal_soc_data {
+ u32 num_sensors;
+ u32 version;
+};
+
+struct tmu_sensor {
+ struct imx8mm_tmu *priv;
+ u32 hw_id;
struct thermal_zone_device *tzd;
+};
+
+struct imx8mm_tmu {
void __iomem *base;
struct clk *clk;
+ const struct thermal_soc_data *socdata;
+ struct tmu_sensor sensors[0];
};
static int tmu_get_temp(void *data, int *temp)
{
- struct imx8mm_tmu *tmu = data;
+ struct tmu_sensor *sensor = data;
+ struct imx8mm_tmu *tmu = sensor->priv;
+ bool ready;
u32 val;
- val = readl_relaxed(tmu->base + TRITSR) & TRITSR_VAL_MASK;
- if (val < TEMP_LOW_LIMIT)
- return -EAGAIN;
+ if (tmu->socdata->version == TMU_VER1) {
+ val = readl_relaxed(tmu->base + TRITSR) & TRITSR_VAL_MASK;
+ if (val < VER1_TEMP_LOW_LIMIT)
+ return -EAGAIN;
+ } else {
+ val = readl_relaxed(tmu->base + TRITSR);
+ ready = val & (1 << (sensor->hw_id + PROBE0_STATUS_OFFSET));
+ val = (val >> (sensor->hw_id * PROBE0_VAL_OFFSET))
+ & TRITSR_VAL_MASK;
+ if (val & SIGN_BIT) /* negative */
+ val = (~(val & TEMP_VAL_MASK) + 1);
+
+ *temp = val;
+ if (!ready || *temp < VER2_TEMP_LOW_LIMIT ||
+ *temp > VER2_TEMP_HIGH_LIMIT)
+ return -EAGAIN;
+ }
*temp = val * 1000;
@@ -50,14 +91,21 @@ static struct thermal_zone_of_device_ops tmu_tz_ops = {
static int imx8mm_tmu_probe(struct platform_device *pdev)
{
+ const struct thermal_soc_data *data;
struct imx8mm_tmu *tmu;
u32 val;
int ret;
+ int i;
+
+ data = of_device_get_match_data(&pdev->dev);
- tmu = devm_kzalloc(&pdev->dev, sizeof(struct imx8mm_tmu), GFP_KERNEL);
+ tmu = devm_kzalloc(&pdev->dev, struct_size(tmu, sensors,
+ data->num_sensors), GFP_KERNEL);
if (!tmu)
return -ENOMEM;
+ tmu->socdata = data;
+
tmu->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(tmu->base))
return PTR_ERR(tmu->base);
@@ -77,16 +125,35 @@ static int imx8mm_tmu_probe(struct platform_device *pdev)
return ret;
}
- tmu->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
- tmu, &tmu_tz_ops);
- if (IS_ERR(tmu->tzd)) {
- dev_err(&pdev->dev,
- "failed to register thermal zone sensor: %d\n", ret);
- return PTR_ERR(tmu->tzd);
+ /* disable the monitor during initialization */
+ val = readl_relaxed(tmu->base + TER);
+ val &= ~TER_EN;
+ writel_relaxed(val, tmu->base + TER);
+
+ for (i = 0; i < data->num_sensors; i++) {
+ tmu->sensors[i].priv = tmu;
+ tmu->sensors[i].tzd =
+ devm_thermal_zone_of_sensor_register(&pdev->dev, i,
+ &tmu->sensors[i],
+ &tmu_tz_ops);
+ if (IS_ERR(tmu->sensors[i].tzd)) {
+ dev_err(&pdev->dev,
+ "failed to register thermal zone sensor[%d]: %d\n",
+ i, ret);
+ return PTR_ERR(tmu->sensors[i].tzd);
+ }
+ tmu->sensors[i].hw_id = i;
}
platform_set_drvdata(pdev, tmu);
+ /* enable all the probes for V2 TMU */
+ if (tmu->socdata->version == TMU_VER2) {
+ val = readl_relaxed(tmu->base + TPS);
+ val |= PROBE_SEL_ALL;
+ writel_relaxed(val, tmu->base + TPS);
+ }
+
/* enable the monitor */
val = readl_relaxed(tmu->base + TER);
val |= TER_EN;
@@ -111,8 +178,19 @@ static int imx8mm_tmu_remove(struct platform_device *pdev)
return 0;
}
+static struct thermal_soc_data imx8mm_tmu_data = {
+ .num_sensors = 1,
+ .version = TMU_VER1,
+};
+
+static struct thermal_soc_data imx8mp_tmu_data = {
+ .num_sensors = 2,
+ .version = TMU_VER2,
+};
+
static const struct of_device_id imx8mm_tmu_table[] = {
- { .compatible = "fsl,imx8mm-tmu", },
+ { .compatible = "fsl,imx8mm-tmu", .data = &imx8mm_tmu_data, },
+ { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, },
{ },
};
--
2.7.4
i.MX8MP has a TMU inside which supports two thermal zones, add support
for them.
Signed-off-by: Anson Huang <[email protected]>
---
arch/arm64/boot/dts/freescale/imx8mp.dtsi | 63 +++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index a253c3f..c621988 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
#include "imx8mp-pinfunc.h"
@@ -43,6 +44,7 @@
clocks = <&clk IMX8MP_CLK_ARM>;
enable-method = "psci";
next-level-cache = <&A53_L2>;
+ #cooling-cells = <2>;
};
A53_1: cpu@1 {
@@ -53,6 +55,7 @@
clocks = <&clk IMX8MP_CLK_ARM>;
enable-method = "psci";
next-level-cache = <&A53_L2>;
+ #cooling-cells = <2>;
};
A53_2: cpu@2 {
@@ -63,6 +66,7 @@
clocks = <&clk IMX8MP_CLK_ARM>;
enable-method = "psci";
next-level-cache = <&A53_L2>;
+ #cooling-cells = <2>;
};
A53_3: cpu@3 {
@@ -73,6 +77,7 @@
clocks = <&clk IMX8MP_CLK_ARM>;
enable-method = "psci";
next-level-cache = <&A53_L2>;
+ #cooling-cells = <2>;
};
A53_L2: l2-cache0 {
@@ -127,6 +132,57 @@
method = "smc";
};
+ thermal-zones {
+ cpu-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <2000>;
+ thermal-sensors = <&tmu 0x0>;
+ trips {
+ cpu_alert0: trip0 {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_crit0: trip1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert0>;
+ cooling-device =
+ <&A53_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ soc-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <2000>;
+ thermal-sensors = <&tmu 0x1>;
+ trips {
+ soc_alert0: trip0 {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ soc_crit0: trip1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
@@ -215,6 +271,13 @@
gpio-ranges = <&iomuxc 0 114 30>;
};
+ tmu: tmu@30260000 {
+ compatible = "fsl,imx8mp-tmu";
+ reg = <0x30260000 0x10000>;
+ clocks = <&clk IMX8MP_CLK_TSENSOR_ROOT>;
+ #thermal-sensor-cells = <1>;
+ };
+
wdog1: watchdog@30280000 {
compatible = "fsl,imx8mp-wdt", "fsl,imx21-wdt";
reg = <0x30280000 0x10000>;
--
2.7.4
On 08/03/2020 16:27, Anson Huang wrote:
> i.MX8MP shares same TMU with i.MX8MM, the only difference is i.MX8MP
> has two thermal sensors while i.MX8MM ONLY has one, add multiple sensors
> support for i.MX8MM TMU driver.
>
> Signed-off-by: Anson Huang <[email protected]>
> ---
> drivers/thermal/imx8mm_thermal.c | 108 +++++++++++++++++++++++++++++++++------
> 1 file changed, 93 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c
> index d597ceb..8a87ed0 100644
> --- a/drivers/thermal/imx8mm_thermal.c
> +++ b/drivers/thermal/imx8mm_thermal.c
> @@ -10,34 +10,75 @@
> #include <linux/io.h>
> #include <linux/module.h>
> #include <linux/of.h>
> -#include <linux/of_address.h>
> +#include <linux/of_device.h>
> #include <linux/platform_device.h>
> #include <linux/thermal.h>
>
> #include "thermal_core.h"
>
> #define TER 0x0 /* TMU enable */
> +#define TPS 0x4
> #define TRITSR 0x20 /* TMU immediate temp */
>
> #define TER_EN BIT(31)
> #define TRITSR_VAL_MASK 0xff
>
> -#define TEMP_LOW_LIMIT 10
> +#define PROBE_SEL_ALL GENMASK(31, 30)
>
> -struct imx8mm_tmu {
> +#define PROBE0_STATUS_OFFSET 30
> +#define PROBE0_VAL_OFFSET 16
> +#define SIGN_BIT BIT(7)
> +#define TEMP_VAL_MASK GENMASK(6, 0)
> +
> +#define VER1_TEMP_LOW_LIMIT 10
> +#define VER2_TEMP_LOW_LIMIT -40
> +#define VER2_TEMP_HIGH_LIMIT 125
> +
> +#define TMU_VER1 0x1
> +#define TMU_VER2 0x2
> +
> +struct thermal_soc_data {
> + u32 num_sensors;
> + u32 version;
> +};
> +
> +struct tmu_sensor {
> + struct imx8mm_tmu *priv;
> + u32 hw_id;
> struct thermal_zone_device *tzd;
> +};
> +
> +struct imx8mm_tmu {
> void __iomem *base;
> struct clk *clk;
> + const struct thermal_soc_data *socdata;
> + struct tmu_sensor sensors[0];
> };
>
> static int tmu_get_temp(void *data, int *temp)
> {
> - struct imx8mm_tmu *tmu = data;
> + struct tmu_sensor *sensor = data;
> + struct imx8mm_tmu *tmu = sensor->priv;
> + bool ready;
> u32 val;
>
> - val = readl_relaxed(tmu->base + TRITSR) & TRITSR_VAL_MASK;
> - if (val < TEMP_LOW_LIMIT)
> - return -EAGAIN;
> + if (tmu->socdata->version == TMU_VER1) {
Don't do this here, implement a callback to read the temp, store it in
the socdata and call it directly from here.
So you end up with something simple like:
*temp = tmu->socdata->get_temp(...);
> + val = readl_relaxed(tmu->base + TRITSR) & TRITSR_VAL_MASK;
> + if (val < VER1_TEMP_LOW_LIMIT)
> + return -EAGAIN;> + } else {
> + val = readl_relaxed(tmu->base + TRITSR);
> + ready = val & (1 << (sensor->hw_id + PROBE0_STATUS_OFFSET));
test_bit()?
> + val = (val >> (sensor->hw_id * PROBE0_VAL_OFFSET))
> + & TRITSR_VAL_MASK;
> + if (val & SIGN_BIT) /* negative */
> + val = (~(val & TEMP_VAL_MASK) + 1);
Please have a look at the different bitops available to simplify this
decoding.
> + *temp = val;
> + if (!ready || *temp < VER2_TEMP_LOW_LIMIT ||
> + *temp > VER2_TEMP_HIGH_LIMIT)
> + return -EAGAIN;
> + }
>
> *temp = val * 1000;
>
> @@ -50,14 +91,21 @@ static struct thermal_zone_of_device_ops tmu_tz_ops = {
>
> static int imx8mm_tmu_probe(struct platform_device *pdev)
> {
> + const struct thermal_soc_data *data;
> struct imx8mm_tmu *tmu;
> u32 val;
> int ret;
> + int i;
> +
> + data = of_device_get_match_data(&pdev->dev);
>
> - tmu = devm_kzalloc(&pdev->dev, sizeof(struct imx8mm_tmu), GFP_KERNEL);
> + tmu = devm_kzalloc(&pdev->dev, struct_size(tmu, sensors,
> + data->num_sensors), GFP_KERNEL);
> if (!tmu)
> return -ENOMEM;
>
> + tmu->socdata = data;
> +
> tmu->base = devm_platform_ioremap_resource(pdev, 0);
> if (IS_ERR(tmu->base))
> return PTR_ERR(tmu->base);
> @@ -77,16 +125,35 @@ static int imx8mm_tmu_probe(struct platform_device *pdev)
> return ret;
> }
>
> - tmu->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
> - tmu, &tmu_tz_ops);
> - if (IS_ERR(tmu->tzd)) {
> - dev_err(&pdev->dev,
> - "failed to register thermal zone sensor: %d\n", ret);
> - return PTR_ERR(tmu->tzd);
> + /* disable the monitor during initialization */
> + val = readl_relaxed(tmu->base + TER);
> + val &= ~TER_EN;
> + writel_relaxed(val, tmu->base + TER);
Could you wrap those calls inside a small helper function with a self
described name?
> +
> + for (i = 0; i < data->num_sensors; i++) {
> + tmu->sensors[i].priv = tmu;
> + tmu->sensors[i].tzd =
> + devm_thermal_zone_of_sensor_register(&pdev->dev, i,
> + &tmu->sensors[i],
> + &tmu_tz_ops);
> + if (IS_ERR(tmu->sensors[i].tzd)) {
> + dev_err(&pdev->dev,
> + "failed to register thermal zone sensor[%d]: %d\n",
> + i, ret);
> + return PTR_ERR(tmu->sensors[i].tzd);
> + }
> + tmu->sensors[i].hw_id = i;
May be you can store the offset directly, so it is not computed every
time the temperature is read?
> }
>
> platform_set_drvdata(pdev, tmu);
>
> + /* enable all the probes for V2 TMU */
> + if (tmu->socdata->version == TMU_VER2) {
> + val = readl_relaxed(tmu->base + TPS);
> + val |= PROBE_SEL_ALL;
> + writel_relaxed(val, tmu->base + TPS);
> + }
Same comment as before about putting these in a helper
> /* enable the monitor */
> val = readl_relaxed(tmu->base + TER);
> val |= TER_EN;
> @@ -111,8 +178,19 @@ static int imx8mm_tmu_remove(struct platform_device *pdev)
> return 0;
> }
>
> +static struct thermal_soc_data imx8mm_tmu_data = {
> + .num_sensors = 1,
> + .version = TMU_VER1,
> +};
> +
> +static struct thermal_soc_data imx8mp_tmu_data = {
> + .num_sensors = 2,
> + .version = TMU_VER2,
> +};
> +
> static const struct of_device_id imx8mm_tmu_table[] = {
> - { .compatible = "fsl,imx8mm-tmu", },
> + { .compatible = "fsl,imx8mm-tmu", .data = &imx8mm_tmu_data, },
> + { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, },
> { },
> };
>
>
--
<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
Hi, Daniel
> Subject: Re: [PATCH 2/3] thermal: imx8mm: Add i.MX8MP support
>
> On 08/03/2020 16:27, Anson Huang wrote:
> > i.MX8MP shares same TMU with i.MX8MM, the only difference is i.MX8MP
> > has two thermal sensors while i.MX8MM ONLY has one, add multiple
> > sensors support for i.MX8MM TMU driver.
> >
> > Signed-off-by: Anson Huang <[email protected]>
> > ---
> > drivers/thermal/imx8mm_thermal.c | 108
> > +++++++++++++++++++++++++++++++++------
> > 1 file changed, 93 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/thermal/imx8mm_thermal.c
> > b/drivers/thermal/imx8mm_thermal.c
> > index d597ceb..8a87ed0 100644
> > --- a/drivers/thermal/imx8mm_thermal.c
> > +++ b/drivers/thermal/imx8mm_thermal.c
> > @@ -10,34 +10,75 @@
> > #include <linux/io.h>
> > #include <linux/module.h>
> > #include <linux/of.h>
> > -#include <linux/of_address.h>
> > +#include <linux/of_device.h>
> > #include <linux/platform_device.h>
> > #include <linux/thermal.h>
> >
> > #include "thermal_core.h"
> >
> > #define TER 0x0 /* TMU enable */
> > +#define TPS 0x4
> > #define TRITSR 0x20 /* TMU immediate temp */
> >
> > #define TER_EN BIT(31)
> > #define TRITSR_VAL_MASK 0xff
> >
> > -#define TEMP_LOW_LIMIT 10
> > +#define PROBE_SEL_ALL GENMASK(31, 30)
> >
> > -struct imx8mm_tmu {
> > +#define PROBE0_STATUS_OFFSET 30
> > +#define PROBE0_VAL_OFFSET 16
> > +#define SIGN_BIT BIT(7)
> > +#define TEMP_VAL_MASK GENMASK(6, 0)
> > +
> > +#define VER1_TEMP_LOW_LIMIT 10
> > +#define VER2_TEMP_LOW_LIMIT -40
> > +#define VER2_TEMP_HIGH_LIMIT 125
> > +
> > +#define TMU_VER1 0x1
> > +#define TMU_VER2 0x2
> > +
> > +struct thermal_soc_data {
> > + u32 num_sensors;
> > + u32 version;
> > +};
> > +
> > +struct tmu_sensor {
> > + struct imx8mm_tmu *priv;
> > + u32 hw_id;
> > struct thermal_zone_device *tzd;
> > +};
> > +
> > +struct imx8mm_tmu {
> > void __iomem *base;
> > struct clk *clk;
> > + const struct thermal_soc_data *socdata;
> > + struct tmu_sensor sensors[0];
> > };
> >
> > static int tmu_get_temp(void *data, int *temp) {
> > - struct imx8mm_tmu *tmu = data;
> > + struct tmu_sensor *sensor = data;
> > + struct imx8mm_tmu *tmu = sensor->priv;
> > + bool ready;
> > u32 val;
> >
> > - val = readl_relaxed(tmu->base + TRITSR) & TRITSR_VAL_MASK;
> > - if (val < TEMP_LOW_LIMIT)
> > - return -EAGAIN;
> > + if (tmu->socdata->version == TMU_VER1) {
>
> Don't do this here, implement a callback to read the temp, store it in the
> socdata and call it directly from here.
>
> So you end up with something simple like:
>
> *temp = tmu->socdata->get_temp(...);
>
Make sense, do it in V2.
> > + val = readl_relaxed(tmu->base + TRITSR) &
> TRITSR_VAL_MASK;
> > + if (val < VER1_TEMP_LOW_LIMIT)
> > + return -EAGAIN;> + } else {
> > + val = readl_relaxed(tmu->base + TRITSR);
> > + ready = val & (1 << (sensor->hw_id +
> PROBE0_STATUS_OFFSET));
>
> test_bit()?
OK.
>
> > + val = (val >> (sensor->hw_id * PROBE0_VAL_OFFSET))
> > + & TRITSR_VAL_MASK;
> > + if (val & SIGN_BIT) /* negative */
> > + val = (~(val & TEMP_VAL_MASK) + 1);
>
> Please have a look at the different bitops available to simplify this decoding.
I can ONLY find the FIELD_GET for getting the temperature value field, for the positive
and negative value check, I can't find any API for it.
>
> > + *temp = val;
> > + if (!ready || *temp < VER2_TEMP_LOW_LIMIT ||
> > + *temp > VER2_TEMP_HIGH_LIMIT)
> > + return -EAGAIN;
> > + }
> >
> > *temp = val * 1000;
> >
> > @@ -50,14 +91,21 @@ static struct thermal_zone_of_device_ops
> > tmu_tz_ops = {
> >
> > static int imx8mm_tmu_probe(struct platform_device *pdev) {
> > + const struct thermal_soc_data *data;
> > struct imx8mm_tmu *tmu;
> > u32 val;
> > int ret;
> > + int i;
> > +
> > + data = of_device_get_match_data(&pdev->dev);
> >
> > - tmu = devm_kzalloc(&pdev->dev, sizeof(struct imx8mm_tmu),
> GFP_KERNEL);
> > + tmu = devm_kzalloc(&pdev->dev, struct_size(tmu, sensors,
> > + data->num_sensors), GFP_KERNEL);
> > if (!tmu)
> > return -ENOMEM;
> >
> > + tmu->socdata = data;
> > +
> > tmu->base = devm_platform_ioremap_resource(pdev, 0);
> > if (IS_ERR(tmu->base))
> > return PTR_ERR(tmu->base);
> > @@ -77,16 +125,35 @@ static int imx8mm_tmu_probe(struct
> platform_device *pdev)
> > return ret;
> > }
> >
> > - tmu->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
> > - tmu, &tmu_tz_ops);
> > - if (IS_ERR(tmu->tzd)) {
> > - dev_err(&pdev->dev,
> > - "failed to register thermal zone sensor: %d\n", ret);
> > - return PTR_ERR(tmu->tzd);
> > + /* disable the monitor during initialization */
> > + val = readl_relaxed(tmu->base + TER);
> > + val &= ~TER_EN;
> > + writel_relaxed(val, tmu->base + TER);
>
> Could you wrap those calls inside a small helper function with a self
> described name?
OK.
>
> > +
> > + for (i = 0; i < data->num_sensors; i++) {
> > + tmu->sensors[i].priv = tmu;
> > + tmu->sensors[i].tzd =
> > + devm_thermal_zone_of_sensor_register(&pdev->dev,
> i,
> > + &tmu->sensors[i],
> > + &tmu_tz_ops);
> > + if (IS_ERR(tmu->sensors[i].tzd)) {
> > + dev_err(&pdev->dev,
> > + "failed to register thermal zone
> sensor[%d]: %d\n",
> > + i, ret);
> > + return PTR_ERR(tmu->sensors[i].tzd);
> > + }
> > + tmu->sensors[i].hw_id = i;
>
> May be you can store the offset directly, so it is not computed every time the
> temperature is read?
There are 2 place need to identify the sensor ID, the ready bit and the temperature
value field, so I think the hw_id is necessary, and it also make the logic easy to read.
>
> > }
> >
> > platform_set_drvdata(pdev, tmu);
> >
> > + /* enable all the probes for V2 TMU */
> > + if (tmu->socdata->version == TMU_VER2) {
> > + val = readl_relaxed(tmu->base + TPS);
> > + val |= PROBE_SEL_ALL;
> > + writel_relaxed(val, tmu->base + TPS);
> > + }
>
> Same comment as before about putting these in a helper
OK
Please help review V2 patch.
Thanks,
Anson