On Wed, 20 Mar 2024 11:04:05 +0100 Andrej Picej <andrej.picej@xxxxxxxxx> wrote: > Make calibration properties: > - AVGEN: allow averaging of calibration time, Confused. How do you average time? Or is this enabling averaging of ADC readings at calibration time? > - NRSMPL: select the number of averaging samples during calibration and Assuming I read AVGEN right, just have a value of 1 in here mean AVGEN is disabled. > - TSAMP: specifies the sample time of calibration conversions Not sure what this means. Is it acquisition time? Is it time after a mux changes? Anyhow, more info needed. This is the only one I can see being possibly board related. But if it is and is needed for calibration, why not for normal read out? > > configurable with device tree properties: > - nxp,calib-avg-en, > - nxp,calib-nr-samples and > - nxp,calib-t-samples. > > Signed-off-by: Andrej Picej <andrej.picej@xxxxxxxxx> > --- > drivers/iio/adc/imx93_adc.c | 66 ++++++++++++++++++++++++++++++++++--- > 1 file changed, 61 insertions(+), 5 deletions(-) > > diff --git a/drivers/iio/adc/imx93_adc.c b/drivers/iio/adc/imx93_adc.c > index 4ccf4819f1f1..ad24105761ab 100644 > --- a/drivers/iio/adc/imx93_adc.c > +++ b/drivers/iio/adc/imx93_adc.c > @@ -18,6 +18,7 @@ > #include <linux/platform_device.h> > #include <linux/pm_runtime.h> > #include <linux/regulator/consumer.h> > +#include <linux/property.h> > > #define IMX93_ADC_DRIVER_NAME "imx93-adc" > > @@ -43,6 +44,9 @@ > #define IMX93_ADC_MCR_MODE_MASK BIT(29) > #define IMX93_ADC_MCR_NSTART_MASK BIT(24) > #define IMX93_ADC_MCR_CALSTART_MASK BIT(14) > +#define IMX93_ADC_MCR_AVGEN_MASK BIT(13) > +#define IMX93_ADC_MCR_NRSMPL_MASK GENMASK(12, 11) > +#define IMX93_ADC_MCR_TSAMP_MASK GENMASK(10, 9) > #define IMX93_ADC_MCR_ADCLKSE_MASK BIT(8) > #define IMX93_ADC_MCR_PWDN_MASK BIT(0) > #define IMX93_ADC_MSR_CALFAIL_MASK BIT(30) > @@ -145,7 +149,7 @@ static void imx93_adc_config_ad_clk(struct imx93_adc *adc) > > static int imx93_adc_calibration(struct imx93_adc *adc) > { > - u32 mcr, msr; > + u32 mcr, msr, value; > int ret; > > /* make sure ADC in power down mode */ > @@ -156,12 +160,64 @@ static int imx93_adc_calibration(struct imx93_adc *adc) > mcr &= ~FIELD_PREP(IMX93_ADC_MCR_ADCLKSE_MASK, 1); > writel(mcr, adc->regs + IMX93_ADC_MCR); > > - imx93_adc_power_up(adc); > - > /* > - * TODO: we use the default TSAMP/NRSMPL/AVGEN in MCR, > - * can add the setting of these bit if need in future. > + * Set calibration settings: > + * - AVGEN: allow averaging of calibration time, > + * - NRSMPL: select the number of averaging samples during calibration, > + * - TSAMP: specifies the sample time of calibration conversions. > */ > + if (!device_property_read_u32(adc->dev, "nxp,calib-avg-en", &value)) { > + mcr &= ~IMX93_ADC_MCR_AVGEN_MASK; > + mcr |= FIELD_PREP(IMX93_ADC_MCR_AVGEN_MASK, value); > + } > + > + if (!device_property_read_u32(adc->dev, "nxp,calib-nr-samples", &value)) { Handle error for not present different from a failure to read or similar. Not present isn't an error, just a fall back to defaults. For other error codes we should fail the probe. > + switch (value) { > + case 16: > + value = 0x0; Don't do this in place, meaning of value before this point different to what you have in it going forwards. Use a different variable name to make that clear. reg_val vs nr_samples perhaps? > + break; > + case 32: > + value = 0x1; > + break; > + case 128: > + value = 0x2; > + break; > + case 512: > + value = 0x3; > + break; > + default: > + dev_warn(adc->dev, "NRSMPL: wrong value, using default: 512\n"); Fail the probe rather than papering over a wrong value. I'd rather we got the DT fixed quickly and if someone wanted another value, they really did want it. We probably do want a default though for the property not being present (given it is new). so take setting of this variable outside the if(!device_property_read_u32); > + value = 0x3; > + } > + mcr &= ~IMX93_ADC_MCR_NRSMPL_MASK; > + mcr |= FIELD_PREP(IMX93_ADC_MCR_NRSMPL_MASK, value); > + } > + > + if (!device_property_read_u32(adc->dev, "nxp,calib-t-samples", &value)) { > + switch (value) { > + case 8: > + value = 0x1; > + break; > + case 16: > + value = 0x2; > + break; > + case 22: > + value = 0x0; > + break; > + case 32: > + value = 0x3; > + break; > + default: > + dev_warn(adc->dev, "TSAMP: wrong value, using default: 22\n"); > + value = 0x0; > + } > + mcr &= ~IMX93_ADC_MCR_TSAMP_MASK; > + mcr |= FIELD_PREP(IMX93_ADC_MCR_TSAMP_MASK, value); > + } > + > + writel(mcr, adc->regs + IMX93_ADC_MCR); > + > + imx93_adc_power_up(adc); > > /* run calibration */ > mcr = readl(adc->regs + IMX93_ADC_MCR);