[PATCH v6 3/5] thermal/drivers/sun8i: get calibration data from two nvmem cells

Chen-Yu Tsai wens at kernel.org
Sun Sep 20 02:50:41 PDT 2026


On Sun, Sep 13, 2026 at 10:56 PM Mikhail Kalashnikov <iuncuim at gmail.com> wrote:
>
> From: Mikhail Kalashnikov <iuncuim at gmail.com>
>
> The A523 processor has calibration data in two nvmem cells. To be able to
> add support, the ability to add data from two cells into one array must be
> added.
>
> Signed-off-by: Mikhail Kalashnikov <iuncuim at gmail.com>

I'd say that Sashiko's comment on "leaking" memory until the device is
removed is not too much of a concern. Sure it could be released sooner
since it's not used, but it's not a lot of memory.

Reviewed-by: Chen-Yu Tsai <wens at kernel.org>

> ---
>  drivers/thermal/sun8i_thermal.c | 81 +++++++++++++++++++++------------
>  1 file changed, 53 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> index 1412bce63..360654880 100644
> --- a/drivers/thermal/sun8i_thermal.c
> +++ b/drivers/thermal/sun8i_thermal.c
> @@ -300,43 +300,68 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
>
>  static int sun8i_ths_calibrate(struct ths_device *tmdev)
>  {
> -       struct nvmem_cell *calcell;
> +       struct nvmem_cell *calcell = NULL;
>         struct device *dev = tmdev->dev;
> -       u16 *caldata;
> -       size_t callen;
> +       struct device_node *np = dev_of_node(dev);
> +       struct property *prop;
> +       const char *cellname;
> +       u8 *caldata = NULL;
> +       size_t callen = 0;
>         int ret = 0;
>
> -       calcell = nvmem_cell_get(dev, "calibration");
> -       if (IS_ERR(calcell)) {
> -               if (PTR_ERR(calcell) == -EPROBE_DEFER)
> -                       return -EPROBE_DEFER;
> -               /*
> -                * Even if the external calibration data stored in sid is
> -                * not accessible, the THS hardware can still work, although
> -                * the data won't be so accurate.
> -                *
> -                * The default value of calibration register is 0x800 for
> -                * every sensor, and the calibration value is usually 0x7xx
> -                * or 0x8xx, so they won't be away from the default value
> -                * for a lot.
> -                *
> -                * So here we do not return error if the calibration data is
> -                * not available, except the probe needs deferring.
> -                */
> -               goto out;
> +       of_property_for_each_string(np, "nvmem-cell-names", prop, cellname) {
> +               size_t len;
> +               u8 *caldatapart;
> +
> +               calcell = of_nvmem_cell_get(np, cellname);
> +               if (IS_ERR(calcell)) {
> +                       if (PTR_ERR(calcell) == -EPROBE_DEFER)
> +                               return -EPROBE_DEFER;
> +                       /*
> +                        * Even if the external calibration data stored in sid is
> +                        * not accessible, the THS hardware can still work, although
> +                        * the data won't be so accurate.
> +                        *
> +                        * The default value of calibration register is 0x800 for
> +                        * every sensor, and the calibration value is usually 0x7xx
> +                        * or 0x8xx, so they won't be away from the default value
> +                        * for a lot.
> +                        *
> +                        * So here we do not return error if the calibration data is
> +                        * not available, except the probe needs deferring.
> +                        */
> +                       goto out;
> +               }
> +
> +               caldatapart = nvmem_cell_read(calcell, &len);
> +               nvmem_cell_put(calcell);
> +               calcell = NULL;
> +               if (IS_ERR(caldatapart)) {
> +                       ret = PTR_ERR(caldatapart);
> +                       goto out;
> +               }
> +
> +               caldata = devm_krealloc(dev, caldata, callen + len, GFP_KERNEL);
> +               if (!caldata) {
> +                       kfree(caldatapart);
> +                       ret = -ENOMEM;
> +                       goto out;
> +               }
> +
> +               memcpy(caldata + callen, caldatapart, len);
> +               callen += len;
> +               kfree(caldatapart);
>         }
>
> -       caldata = nvmem_cell_read(calcell, &callen);
> -       if (IS_ERR(caldata)) {
> -               ret = PTR_ERR(caldata);
> +       if (!caldata)
>                 goto out;
> -       }
>
> -       tmdev->chip->calibrate(tmdev, caldata, callen);
> +       tmdev->chip->calibrate(tmdev, (u16 *)caldata, callen);
>
> -       kfree(caldata);
> +       devm_kfree(dev, caldata);
> +       caldata = NULL;
>  out:
> -       if (!IS_ERR(calcell))
> +       if (!IS_ERR_OR_NULL(calcell))
>                 nvmem_cell_put(calcell);
>         return ret;
>  }
> --
> 2.55.0
>



More information about the linux-arm-kernel mailing list