Commit 0da98c7b authored by Fabrice Gasnier's avatar Fabrice Gasnier Committed by Jonathan Cameron

iio: adc: stm32-adc: move self-calibration to prepare routine

Move self-calibration routine to prepare routine.
- This is precursor patch to ease power management handling.
- This also allow to factorize few error cases (error handling).
Signed-off-by: default avatarFabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 7f6232e6
...@@ -199,11 +199,13 @@ struct stm32_adc_trig_info { ...@@ -199,11 +199,13 @@ struct stm32_adc_trig_info {
* @calfact_s: Calibration offset for single ended channels * @calfact_s: Calibration offset for single ended channels
* @calfact_d: Calibration offset in differential * @calfact_d: Calibration offset in differential
* @lincalfact: Linearity calibration factor * @lincalfact: Linearity calibration factor
* @calibrated: Indicates calibration status
*/ */
struct stm32_adc_calib { struct stm32_adc_calib {
u32 calfact_s; u32 calfact_s;
u32 calfact_d; u32 calfact_d;
u32 lincalfact[STM32H7_LINCALFACT_NUM]; u32 lincalfact[STM32H7_LINCALFACT_NUM];
bool calibrated;
}; };
/** /**
...@@ -251,7 +253,6 @@ struct stm32_adc; ...@@ -251,7 +253,6 @@ struct stm32_adc;
* @trigs: external trigger sources * @trigs: external trigger sources
* @clk_required: clock is required * @clk_required: clock is required
* @has_vregready: vregready status flag presence * @has_vregready: vregready status flag presence
* @selfcalib: optional routine for self-calibration
* @prepare: optional prepare routine (power-up, enable) * @prepare: optional prepare routine (power-up, enable)
* @start_conv: routine to start conversions * @start_conv: routine to start conversions
* @stop_conv: routine to stop conversions * @stop_conv: routine to stop conversions
...@@ -264,7 +265,6 @@ struct stm32_adc_cfg { ...@@ -264,7 +265,6 @@ struct stm32_adc_cfg {
struct stm32_adc_trig_info *trigs; struct stm32_adc_trig_info *trigs;
bool clk_required; bool clk_required;
bool has_vregready; bool has_vregready;
int (*selfcalib)(struct stm32_adc *);
int (*prepare)(struct stm32_adc *); int (*prepare)(struct stm32_adc *);
void (*start_conv)(struct stm32_adc *, bool dma); void (*start_conv)(struct stm32_adc *, bool dma);
void (*stop_conv)(struct stm32_adc *); void (*stop_conv)(struct stm32_adc *);
...@@ -777,6 +777,7 @@ static void stm32h7_adc_disable(struct stm32_adc *adc) ...@@ -777,6 +777,7 @@ static void stm32h7_adc_disable(struct stm32_adc *adc)
/** /**
* stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result * stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result
* @adc: stm32 adc instance * @adc: stm32 adc instance
* Note: Must be called once ADC is enabled, so LINCALRDYW[1..6] are writable
*/ */
static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc) static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
{ {
...@@ -784,11 +785,6 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc) ...@@ -784,11 +785,6 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
int i, ret; int i, ret;
u32 lincalrdyw_mask, val; u32 lincalrdyw_mask, val;
/* Enable adc so LINCALRDYW1..6 bits are writable */
ret = stm32h7_adc_enable(adc);
if (ret)
return ret;
/* Read linearity calibration */ /* Read linearity calibration */
lincalrdyw_mask = STM32H7_LINCALRDYW6; lincalrdyw_mask = STM32H7_LINCALRDYW6;
for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
...@@ -801,7 +797,7 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc) ...@@ -801,7 +797,7 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
100, STM32_ADC_TIMEOUT_US); 100, STM32_ADC_TIMEOUT_US);
if (ret) { if (ret) {
dev_err(&indio_dev->dev, "Failed to read calfact\n"); dev_err(&indio_dev->dev, "Failed to read calfact\n");
goto disable; return ret;
} }
val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2); val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2);
...@@ -817,11 +813,9 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc) ...@@ -817,11 +813,9 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
adc->cal.calfact_s >>= STM32H7_CALFACT_S_SHIFT; adc->cal.calfact_s >>= STM32H7_CALFACT_S_SHIFT;
adc->cal.calfact_d = (val & STM32H7_CALFACT_D_MASK); adc->cal.calfact_d = (val & STM32H7_CALFACT_D_MASK);
adc->cal.calfact_d >>= STM32H7_CALFACT_D_SHIFT; adc->cal.calfact_d >>= STM32H7_CALFACT_D_SHIFT;
adc->cal.calibrated = true;
disable: return 0;
stm32h7_adc_disable(adc);
return ret;
} }
/** /**
...@@ -898,9 +892,9 @@ static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc) ...@@ -898,9 +892,9 @@ static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc)
#define STM32H7_ADC_CALIB_TIMEOUT_US 100000 #define STM32H7_ADC_CALIB_TIMEOUT_US 100000
/** /**
* stm32h7_adc_selfcalib() - Procedure to calibrate ADC (from power down) * stm32h7_adc_selfcalib() - Procedure to calibrate ADC
* @adc: stm32 adc instance * @adc: stm32 adc instance
* Exit from power down, calibrate ADC, then return to power down. * Note: Must be called once ADC is out of power down.
*/ */
static int stm32h7_adc_selfcalib(struct stm32_adc *adc) static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
{ {
...@@ -908,9 +902,8 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc) ...@@ -908,9 +902,8 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
int ret; int ret;
u32 val; u32 val;
ret = stm32h7_adc_exit_pwr_down(adc); if (adc->cal.calibrated)
if (ret) return true;
return ret;
/* /*
* Select calibration mode: * Select calibration mode:
...@@ -927,7 +920,7 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc) ...@@ -927,7 +920,7 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
STM32H7_ADC_CALIB_TIMEOUT_US); STM32H7_ADC_CALIB_TIMEOUT_US);
if (ret) { if (ret) {
dev_err(&indio_dev->dev, "calibration failed\n"); dev_err(&indio_dev->dev, "calibration failed\n");
goto pwr_dwn; goto out;
} }
/* /*
...@@ -944,18 +937,13 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc) ...@@ -944,18 +937,13 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
STM32H7_ADC_CALIB_TIMEOUT_US); STM32H7_ADC_CALIB_TIMEOUT_US);
if (ret) { if (ret) {
dev_err(&indio_dev->dev, "calibration failed\n"); dev_err(&indio_dev->dev, "calibration failed\n");
goto pwr_dwn; goto out;
} }
out:
stm32_adc_clr_bits(adc, STM32H7_ADC_CR, stm32_adc_clr_bits(adc, STM32H7_ADC_CR,
STM32H7_ADCALDIF | STM32H7_ADCALLIN); STM32H7_ADCALDIF | STM32H7_ADCALLIN);
/* Read calibration result for future reference */
ret = stm32h7_adc_read_selfcalib(adc);
pwr_dwn:
stm32h7_adc_enter_pwr_down(adc);
return ret; return ret;
} }
...@@ -972,19 +960,28 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc) ...@@ -972,19 +960,28 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
*/ */
static int stm32h7_adc_prepare(struct stm32_adc *adc) static int stm32h7_adc_prepare(struct stm32_adc *adc)
{ {
int ret; int calib, ret;
ret = stm32h7_adc_exit_pwr_down(adc); ret = stm32h7_adc_exit_pwr_down(adc);
if (ret) if (ret)
return ret; return ret;
ret = stm32h7_adc_selfcalib(adc);
if (ret < 0)
goto pwr_dwn;
calib = ret;
stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel); stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel);
ret = stm32h7_adc_enable(adc); ret = stm32h7_adc_enable(adc);
if (ret) if (ret)
goto pwr_dwn; goto pwr_dwn;
ret = stm32h7_adc_restore_selfcalib(adc); /* Either restore or read calibration result for future reference */
if (calib)
ret = stm32h7_adc_restore_selfcalib(adc);
else
ret = stm32h7_adc_read_selfcalib(adc);
if (ret) if (ret)
goto disable; goto disable;
...@@ -1880,12 +1877,6 @@ static int stm32_adc_probe(struct platform_device *pdev) ...@@ -1880,12 +1877,6 @@ static int stm32_adc_probe(struct platform_device *pdev)
goto err_clk_disable; goto err_clk_disable;
stm32_adc_set_res(adc); stm32_adc_set_res(adc);
if (adc->cfg->selfcalib) {
ret = adc->cfg->selfcalib(adc);
if (ret)
goto err_clk_disable;
}
ret = stm32_adc_chan_of_init(indio_dev); ret = stm32_adc_chan_of_init(indio_dev);
if (ret < 0) if (ret < 0)
goto err_clk_disable; goto err_clk_disable;
...@@ -1961,7 +1952,6 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { ...@@ -1961,7 +1952,6 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
.regs = &stm32h7_adc_regspec, .regs = &stm32h7_adc_regspec,
.adc_info = &stm32h7_adc_info, .adc_info = &stm32h7_adc_info,
.trigs = stm32h7_adc_trigs, .trigs = stm32h7_adc_trigs,
.selfcalib = stm32h7_adc_selfcalib,
.start_conv = stm32h7_adc_start_conv, .start_conv = stm32h7_adc_start_conv,
.stop_conv = stm32h7_adc_stop_conv, .stop_conv = stm32h7_adc_stop_conv,
.prepare = stm32h7_adc_prepare, .prepare = stm32h7_adc_prepare,
...@@ -1974,7 +1964,6 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { ...@@ -1974,7 +1964,6 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
.adc_info = &stm32h7_adc_info, .adc_info = &stm32h7_adc_info,
.trigs = stm32h7_adc_trigs, .trigs = stm32h7_adc_trigs,
.has_vregready = true, .has_vregready = true,
.selfcalib = stm32h7_adc_selfcalib,
.start_conv = stm32h7_adc_start_conv, .start_conv = stm32h7_adc_start_conv,
.stop_conv = stm32h7_adc_stop_conv, .stop_conv = stm32h7_adc_stop_conv,
.prepare = stm32h7_adc_prepare, .prepare = stm32h7_adc_prepare,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment