[PATCH v3 4/8] thermal: amlogic: Add support for secure monitor calibration readout
Ronald Claveau
linux-kernel-dev at aliel.fr
Thu Apr 23 08:09:41 PDT 2026
Hi Daniel,
Thanks for your feedback.
On 4/23/26 12:25 PM, Daniel Lezcano wrote:
>
> Hi Ronald,
>
> On 4/21/26 09:19, Ronald Claveau wrote:
>> 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.
>>
>> Signed-off-by: Ronald Claveau <linux-kernel-dev at aliel.fr>
>> ---
>> drivers/thermal/amlogic_thermal.c | 58 +++++++++++++++++++++++++++++
>> ++++++----
>> 1 file changed, 53 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/thermal/amlogic_thermal.c b/drivers/thermal/
>> amlogic_thermal.c
>> index 5448d772db12a..11e3948cc0669 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;
>> };
>> /*
>> @@ -138,6 +143,12 @@ static int amlogic_thermal_initialize(struct
>> amlogic_thermal *pdata)
>> int ret = 0;
>> int ver;
>> + if (pdata->data->use_sm) {
>> + return meson_sm_get_thermal_calib(pdata->sm_fw,
>> + &pdata->trim_info,
>> + pdata->tsensor_id);
>> + }
>> +
>> regmap_read(pdata->sec_ao_map, pdata->data->u_efuse_off,
>> &pdata->trim_info);
>> @@ -226,6 +237,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 +256,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,11 +292,38 @@ 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) {
>> + struct device_node *sm_np;
>> + struct of_phandle_args ph_args;
>> +
>> + 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;
>> + if (!sm_np) {
>> + dev_err(dev,
>> + "Failed to parse secure monitor phandle\n");
>> + 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];
>> + } else {
>> + 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);
>> + }
>> }
>
> I suggest to separate these two routines into functions. That will help
> the readability.
>
Sure, I will do that.
>> pdata->tzd = devm_thermal_of_zone_register(&pdev->dev
>
> The thermal zone is registered before calling
> amlogic_thermal_initialize(), thus pdata->trim_info is not initialized.
> When a thermal zone is registered the thermal framework reads the
> temperature, so it reads an invalid value because:
>
> devm_thermal_of_zone_register()
> -> thermal_of_zone_register()
> -> thermal_zone_device_register_with_trips()
> -> thermal_zone_device_enable()
> -> __thermal_zone_device_update()
> -> __thermal_zone_get_temp()
> -> amlogic_thermal_get_temp()
> -> amlogic_thermal_code_to_millicelsius()
> [ Use of uninitialized pdata->trim_info ]
>
> Right ?
>
Yes, I will move the initialize before the register.
> IIUC, amlogic_thermal_initialize() can be also split and moved the
> corresponding blocks to the functions to be created in the comment above.
>
The SM and syscon setup will be extracted into two functions.
amlogic_thermal_initialize() itself is kept as-is but moved before
devm_thermal_of_zone_register().
Let me know if you'd prefer a different approach.
>
>>
>
--
Best regards,
Ronald
More information about the linux-amlogic
mailing list