[PATCH v4 4/8] thermal: amlogic: Add support for secure monitor calibration readout
Ronald Claveau
linux-kernel-dev at aliel.fr
Fri Apr 24 08:13:03 PDT 2026
On 4/24/26 11:52 AM, Neil Armstrong wrote:
> On 4/23/26 18:07, Ronald Claveau via B4 Relay wrote:
>> From: Ronald Claveau <linux-kernel-dev at aliel.fr>
>>
>> Some SoCs (e.g. T7) expose thermal calibration data through the secure
>> monitor rather than a directly accessible eFuse register. Add a use_sm
>> flag to amlogic_thermal_data to select this path, and retrieve the
>> firmware handle and tsensor_id from the "amlogic,secure-monitor" DT
>> phandle with one fixed argument.
>>
>> Also introduce the amlogic,t7-thermal compatible using this new path.
>>
>> While refactoring, fix a pre-existing bug where
>> amlogic_thermal_initialize() was called after
>> devm_thermal_of_zone_register(), causing the thermal framework to
>> read an uninitialized trim_info on zone registration.
>>
>> Signed-off-by: Ronald Claveau <linux-kernel-dev at aliel.fr>
>> ---
>> drivers/thermal/amlogic_thermal.c | 115 +++++++++++++++++++++++++++
>> +----------
>> 1 file changed, 85 insertions(+), 30 deletions(-)
>>
>> diff --git a/drivers/thermal/amlogic_thermal.c b/drivers/thermal/
>> amlogic_thermal.c
>> index 5448d772db12a..0d0c01e57b85e 100644
>> --- a/drivers/thermal/amlogic_thermal.c
>> +++ b/drivers/thermal/amlogic_thermal.c
>> @@ -25,6 +25,7 @@
>> #include <linux/platform_device.h>
>> #include <linux/regmap.h>
>> #include <linux/thermal.h>
>> +#include <linux/firmware/meson/meson_sm.h>
>> #include "thermal_hwmon.h"
>> @@ -84,12 +85,14 @@ struct amlogic_thermal_soc_calib_data {
>> * @u_efuse_off: register offset to read fused calibration value
>> * @calibration_parameters: calibration parameters structure pointer
>> * @regmap_config: regmap config for the device
>> + * @use_sm: read data from secure monitor instead of efuse
>> * This structure is required for configuration of amlogic thermal
>> driver.
>> */
>> struct amlogic_thermal_data {
>> int u_efuse_off;
>> const struct amlogic_thermal_soc_calib_data
>> *calibration_parameters;
>> const struct regmap_config *regmap_config;
>> + bool use_sm;
>> };
>> struct amlogic_thermal {
>> @@ -100,6 +103,8 @@ struct amlogic_thermal {
>> struct clk *clk;
>> struct thermal_zone_device *tzd;
>> u32 trim_info;
>> + struct meson_sm_firmware *sm_fw;
>> + u32 tsensor_id;
>> };
>> /*
>> @@ -133,26 +138,6 @@ static int
>> amlogic_thermal_code_to_millicelsius(struct amlogic_thermal *pdata,
>> return temp;
>> }
>> -static int amlogic_thermal_initialize(struct amlogic_thermal *pdata)
>> -{
>> - int ret = 0;
>> - int ver;
>> -
>> - regmap_read(pdata->sec_ao_map, pdata->data->u_efuse_off,
>> - &pdata->trim_info);
>> -
>> - ver = TSENSOR_TRIM_VERSION(pdata->trim_info);
>> -
>> - if ((ver & TSENSOR_TRIM_CALIB_VALID_MASK) == 0) {
>> - ret = -EINVAL;
>> - dev_err(&pdata->pdev->dev,
>> - "tsensor thermal calibration not supported: 0x%x!\n",
>> - ver);
>> - }
>> -
>> - return ret;
>> -}
>> -
>> static int amlogic_thermal_enable(struct amlogic_thermal *data)
>> {
>> int ret;
>> @@ -190,6 +175,70 @@ static int amlogic_thermal_get_temp(struct
>> thermal_zone_device *tz, int *temp)
>> return 0;
>> }
>> +static int amlogic_thermal_probe_sm(struct platform_device *pdev,
>> + struct amlogic_thermal *pdata)
>> +{
>> + struct device *dev = &pdev->dev;
>> + struct device_node *sm_np;
>> + struct of_phandle_args ph_args;
>> + int ret;
>> +
>> + ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
>> + "amlogic,secure-monitor",
>> + 1, 0, &ph_args);
>> + if (ret)
>> + return ret;
>> +
>> + sm_np = ph_args.np;
>
> Drop this sm_np variable and use ph_args.np
>
>> + if (!sm_np) {
>> + dev_err(dev,
>> + "Failed to parse secure monitor phandle\n");
>
> Single line
>
>> + return -ENODEV;
>> + }
>> +
>> + pdata->sm_fw = meson_sm_get(sm_np);
>> + of_node_put(sm_np);
>> + if (!pdata->sm_fw) {
>> + dev_err(dev, "Failed to get secure monitor firmware\n");
>> + return -EPROBE_DEFER;
>> + }
>> +
>> + pdata->tsensor_id = ph_args.args[0];
>> +
>> + return meson_sm_get_thermal_calib(pdata->sm_fw,
>> + &pdata->trim_info,
>> + pdata->tsensor_id);
>> +}
>> +
>> +static int amlogic_thermal_probe_syscon(struct platform_device *pdev,
>> + struct amlogic_thermal *pdata)
>> +{
>> + struct device *dev = &pdev->dev;
>> + int ret = 0;
>> + int ver;
>> +
>> + pdata->sec_ao_map = syscon_regmap_lookup_by_phandle
>> + (pdev->dev.of_node, "amlogic,ao-secure");
>
> Rewrite as:
> pdata->sec_ao_map =
> syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> "amlogic,ao-secure");
>
>> + if (IS_ERR(pdata->sec_ao_map)) {
>> + dev_err(dev, "syscon regmap lookup failed.\n");
>> + return PTR_ERR(pdata->sec_ao_map);
>> + }
>> +
>> + regmap_read(pdata->sec_ao_map, pdata->data->u_efuse_off,
>> + &pdata->trim_info);
>> +
>> + ver = TSENSOR_TRIM_VERSION(pdata->trim_info);
>> +
>> + if ((ver & TSENSOR_TRIM_CALIB_VALID_MASK) == 0) {
>> + ret = -EINVAL;
>> + dev_err(&pdata->pdev->dev,
>> + "tsensor thermal calibration not supported: 0x%x!\n",
>> + ver);
>
> Just return -EINVAL here
>
>> + }
>> +
>> + return ret;
>
> return 0
>
>> +}
>> +
>> static const struct thermal_zone_device_ops amlogic_thermal_ops = {
>> .get_temp = amlogic_thermal_get_temp,
>> };
>> @@ -226,6 +275,12 @@ static const struct amlogic_thermal_data
>> amlogic_thermal_a1_cpu_param = {
>> .regmap_config = &amlogic_thermal_regmap_config_g12a,
>> };
>> +static const struct amlogic_thermal_data amlogic_thermal_t7_param = {
>> + .use_sm = true,
>> + .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",
>> @@ -239,6 +294,10 @@ static const struct of_device_id
>> of_amlogic_thermal_match[] = {
>> .compatible = "amlogic,a1-cpu-thermal",
>> .data = &amlogic_thermal_a1_cpu_param,
>> },
>> + {
>> + .compatible = "amlogic,t7-thermal",
>> + .data = &amlogic_thermal_t7_param,
>> + },
>> { /* sentinel */ }
>> };
>> MODULE_DEVICE_TABLE(of, of_amlogic_thermal_match);
>> @@ -271,12 +330,12 @@ static int amlogic_thermal_probe(struct
>> platform_device *pdev)
>> if (IS_ERR(pdata->clk))
>> return dev_err_probe(dev, PTR_ERR(pdata->clk), "failed to
>> get clock\n");
>> - pdata->sec_ao_map = syscon_regmap_lookup_by_phandle
>> - (pdev->dev.of_node, "amlogic,ao-secure");
>> - if (IS_ERR(pdata->sec_ao_map)) {
>> - dev_err(dev, "syscon regmap lookup failed.\n");
>> - return PTR_ERR(pdata->sec_ao_map);
>> - }
>> + if (pdata->data->use_sm)
>> + ret = amlogic_thermal_probe_sm(pdev, pdata);
>> + else
>> + ret = amlogic_thermal_probe_syscon(pdev, pdata);
>> + if (ret)
>> + return ret;
>> pdata->tzd = devm_thermal_of_zone_register(&pdev->dev,
>> 0,
>> @@ -290,10 +349,6 @@ static int amlogic_thermal_probe(struct
>> platform_device *pdev)
>> devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd);
>> - ret = amlogic_thermal_initialize(pdata);
>> - if (ret)
>> - return ret;
>> -
>> ret = amlogic_thermal_enable(pdata);
>> return ret;
>>
>
> With that fixed:
> Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>
>
Thanks for your feedback, I will incorporate the requested changes.
> Thanks,
> Neil
>
>
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic
--
Best regards,
Ronald
More information about the linux-amlogic
mailing list