[PATCH v5 04/17] iio: adc: at91-sama5d2_adc: rework temp calibration layout handling
Varshini Rajendran <[email protected]> Tue, 4 Aug 2026 17:03:25 +0530
| Newsgroups | org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-iio,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Extend support to handle different temperature calibration layouts. Add a temperature calibration data layout structure to describe indexes of the factors P1, P4, P6, tag, minimum length of the packet and the scaling factors for P1 (p1_scale) which are SoC-specific instead of the older non scalable id structure. This helps handle the differences in the same function flow and prepare the calibration data to be applied. Reviewed-by: Eugen Hristev <[email protected]> Signed-off-by: Varshini Rajendran <[email protected]> --- drivers/iio/adc/at91-sama5d2_adc.c | 66 ++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 09390f082fc4..82db8f2f4db0 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -16,6 +16,7 @@ #include <linux/dmaengine.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/math.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/property.h> @@ -444,6 +445,27 @@ static const struct at91_adc_reg_layout sama7g5_layout = { #define at91_adc_writel(st, reg, val) \ writel_relaxed(val, (st)->base + (st)->soc_info.platform->layout->reg) +/* Temperature calibration tag "ACST" in ASCII */ +#define AT91_TEMP_CALIB_TAG_ACST 0x41435354 + +/** + * struct at91_adc_temp_calib_layout - temperature calibration packet layout + * @tag_idx: index of Packet tag in the NVMEM cell buffer + * @p1_idx: index of FT1_TEMP, equivalent to P1 in the NVMEM cell buffer + * @p4_idx: index of FT1_VPAT, equivalent to P4 in the NVMEM cell buffer + * @p6_idx: index of FT2_VBG, equivalent to P6 in the NVMEM cell buffer + * @min_len: minimum number of u32 words expected in the NVMEM cell buffer + * @p1_scale: scaling factor applied to P1 to convert to millicelcius + */ +struct at91_adc_temp_calib_layout { + unsigned int tag_idx; + unsigned int p1_idx; + unsigned int p4_idx; + unsigned int p6_idx; + unsigned int min_len; + struct u32_fract p1_scale; +}; + /** * struct at91_adc_platform - at91-sama5d2 platform information struct * @layout: pointer to the reg layout struct @@ -462,6 +484,7 @@ static const struct at91_adc_reg_layout sama7g5_layout = { * @oversampling_avail_no: number of available oversampling values * @chan_realbits: realbits for registered channels * @temp_chan: temperature channel index + * @temp_calib_layout: temperature calibration packet layout * @temp_sensor: temperature sensor supported */ struct at91_adc_platform { @@ -479,6 +502,7 @@ struct at91_adc_platform { unsigned int oversampling_avail_no; unsigned int chan_realbits; unsigned int temp_chan; + const struct at91_adc_temp_calib_layout *temp_calib_layout; bool temp_sensor; }; @@ -495,18 +519,13 @@ struct at91_adc_temp_sensor_clb { u32 p6; }; -/** - * enum at91_adc_ts_clb_idx - calibration indexes in NVMEM buffer - * @AT91_ADC_TS_CLB_IDX_P1: index for P1 - * @AT91_ADC_TS_CLB_IDX_P4: index for P4 - * @AT91_ADC_TS_CLB_IDX_P6: index for P6 - * @AT91_ADC_TS_CLB_IDX_MAX: max index for temperature calibration packet in OTP - */ -enum at91_adc_ts_clb_idx { - AT91_ADC_TS_CLB_IDX_P1 = 2, - AT91_ADC_TS_CLB_IDX_P4 = 5, - AT91_ADC_TS_CLB_IDX_P6 = 7, - AT91_ADC_TS_CLB_IDX_MAX = 19, +static const struct at91_adc_temp_calib_layout sama7g5_temp_calib = { + .tag_idx = 1, + .p1_idx = 2, + .p4_idx = 5, + .p6_idx = 7, + .min_len = 19, + .p1_scale = { .numerator = 1000, .denominator = 1 }, }; /* Temperature sensor calibration - Vtemp voltage sensitivity to temperature. */ @@ -744,6 +763,7 @@ static const struct at91_adc_platform sama7g5_platform = { .chan_realbits = 16, .temp_sensor = true, .temp_chan = AT91_SAMA7G5_ADC_TEMP_CHANNEL, + .temp_calib_layout = &sama7g5_temp_calib, }; static int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan) @@ -2249,12 +2269,19 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st, struct device *dev) { struct at91_adc_temp_sensor_clb *clb = &st->soc_info.temp_sensor_clb; + const struct at91_adc_temp_calib_layout *layout; size_t len; int ret = 0; if (!st->soc_info.platform->temp_sensor) return 0; + layout = st->soc_info.platform->temp_calib_layout; + if (!layout) + return -ENODEV; + if (!layout->p1_scale.denominator) + return -EINVAL; + /* Get the calibration data from NVMEM. */ struct nvmem_cell *temp_calib __free(nvmem_cell_put) = nvmem_cell_get(dev, "temperature_calib"); @@ -2270,20 +2297,23 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st, return dev_err_probe(dev, PTR_ERR(buf), "Failed to read calibration data!\n"); - if (len < AT91_ADC_TS_CLB_IDX_MAX * sizeof(*buf)) { + if (len < layout->min_len * sizeof(*buf)) { dev_err(dev, "Invalid calibration data!\n"); return -EINVAL; } /* Store calibration data for later use. */ - clb->p1 = buf[AT91_ADC_TS_CLB_IDX_P1]; - clb->p4 = buf[AT91_ADC_TS_CLB_IDX_P4]; - clb->p6 = buf[AT91_ADC_TS_CLB_IDX_P6]; + clb->p1 = buf[layout->p1_idx]; + clb->p4 = buf[layout->p4_idx]; + clb->p6 = buf[layout->p6_idx]; /* - * We prepare here the conversion to milli to avoid doing it on hotpath. + * Here we prepare the conversion to milli to avoid doing it on hotpath. + * The p1 value is multiplied and divided with a scaling factor as per + * the SoC storage format described by per-platform calibration layout. */ - clb->p1 = clb->p1 * 1000; + clb->p1 *= layout->p1_scale.numerator; + clb->p1 /= layout->p1_scale.denominator; return 0; } -- 2.34.1