Commit 7cb2303d authored by Olivier Moysan's avatar Olivier Moysan Committed by Jonathan Cameron

iio: adc: stm32: manage min sampling time on all internal channels

Force minimum sampling time for all internal channels according
to datasheet requirement. This value can be increased through
DT st,min-sample-time-ns property.
Signed-off-by: default avatarOlivier Moysan <olivier.moysan@foss.st.com>
Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: default avatarFabrice Gasnier <fabrice.gasnier@foss.st.com>
Link: https://lore.kernel.org/r/20221012142205.13041-5-olivier.moysan@foss.st.comSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent cf0fb80a
...@@ -215,7 +215,7 @@ struct stm32_adc; ...@@ -215,7 +215,7 @@ struct stm32_adc;
* @unprepare: optional unprepare routine (disable, power-down) * @unprepare: optional unprepare routine (disable, power-down)
* @irq_clear: routine to clear irqs * @irq_clear: routine to clear irqs
* @smp_cycles: programmable sampling time (ADC clock cycles) * @smp_cycles: programmable sampling time (ADC clock cycles)
* @ts_vrefint_ns: vrefint minimum sampling time in ns * @ts_int_ch: pointer to array of internal channels minimum sampling time in ns
*/ */
struct stm32_adc_cfg { struct stm32_adc_cfg {
const struct stm32_adc_regspec *regs; const struct stm32_adc_regspec *regs;
...@@ -232,7 +232,7 @@ struct stm32_adc_cfg { ...@@ -232,7 +232,7 @@ struct stm32_adc_cfg {
void (*unprepare)(struct iio_dev *); void (*unprepare)(struct iio_dev *);
void (*irq_clear)(struct iio_dev *indio_dev, u32 msk); void (*irq_clear)(struct iio_dev *indio_dev, u32 msk);
const unsigned int *smp_cycles; const unsigned int *smp_cycles;
const unsigned int ts_vrefint_ns; const unsigned int *ts_int_ch;
}; };
/** /**
...@@ -1910,14 +1910,15 @@ static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns) ...@@ -1910,14 +1910,15 @@ static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns)
{ {
const struct stm32_adc_regs *smpr = &adc->cfg->regs->smp_bits[channel]; const struct stm32_adc_regs *smpr = &adc->cfg->regs->smp_bits[channel];
u32 period_ns, shift = smpr->shift, mask = smpr->mask; u32 period_ns, shift = smpr->shift, mask = smpr->mask;
unsigned int smp, r = smpr->reg; unsigned int i, smp, r = smpr->reg;
/* /*
* For vrefint channel, ensure that the sampling time cannot * For internal channels, ensure that the sampling time cannot
* be lower than the one specified in the datasheet * be lower than the one specified in the datasheet
*/ */
if (channel == adc->int_ch[STM32_ADC_INT_CH_VREFINT]) for (i = 0; i < STM32_ADC_INT_CH_NB; i++)
smp_ns = max(smp_ns, adc->cfg->ts_vrefint_ns); if (channel == adc->int_ch[i] && adc->int_ch[i] != STM32_ADC_INT_CH_NONE)
smp_ns = max(smp_ns, adc->cfg->ts_int_ch[i]);
/* Determine sampling time (ADC clock cycles) */ /* Determine sampling time (ADC clock cycles) */
period_ns = NSEC_PER_SEC / adc->common->rate; period_ns = NSEC_PER_SEC / adc->common->rate;
...@@ -2568,6 +2569,9 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = { ...@@ -2568,6 +2569,9 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = {
.irq_clear = stm32f4_adc_irq_clear, .irq_clear = stm32f4_adc_irq_clear,
}; };
const unsigned int stm32_adc_min_ts_h7[] = { 0, 0, 0, 4300, 9000 };
static_assert(ARRAY_SIZE(stm32_adc_min_ts_h7) == STM32_ADC_INT_CH_NB);
static const struct stm32_adc_cfg stm32h7_adc_cfg = { 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,
...@@ -2581,8 +2585,12 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { ...@@ -2581,8 +2585,12 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
.unprepare = stm32h7_adc_unprepare, .unprepare = stm32h7_adc_unprepare,
.smp_cycles = stm32h7_adc_smp_cycles, .smp_cycles = stm32h7_adc_smp_cycles,
.irq_clear = stm32h7_adc_irq_clear, .irq_clear = stm32h7_adc_irq_clear,
.ts_int_ch = stm32_adc_min_ts_h7,
}; };
const unsigned int stm32_adc_min_ts_mp1[] = { 100, 100, 100, 4300, 9800 };
static_assert(ARRAY_SIZE(stm32_adc_min_ts_mp1) == STM32_ADC_INT_CH_NB);
static const struct stm32_adc_cfg stm32mp1_adc_cfg = { static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
.regs = &stm32mp1_adc_regspec, .regs = &stm32mp1_adc_regspec,
.adc_info = &stm32h7_adc_info, .adc_info = &stm32h7_adc_info,
...@@ -2597,9 +2605,12 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { ...@@ -2597,9 +2605,12 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
.unprepare = stm32h7_adc_unprepare, .unprepare = stm32h7_adc_unprepare,
.smp_cycles = stm32h7_adc_smp_cycles, .smp_cycles = stm32h7_adc_smp_cycles,
.irq_clear = stm32h7_adc_irq_clear, .irq_clear = stm32h7_adc_irq_clear,
.ts_vrefint_ns = 4300, .ts_int_ch = stm32_adc_min_ts_mp1,
}; };
const unsigned int stm32_adc_min_ts_mp13[] = { 100, 0, 0, 4300, 9800 };
static_assert(ARRAY_SIZE(stm32_adc_min_ts_mp13) == STM32_ADC_INT_CH_NB);
static const struct stm32_adc_cfg stm32mp13_adc_cfg = { static const struct stm32_adc_cfg stm32mp13_adc_cfg = {
.regs = &stm32mp13_adc_regspec, .regs = &stm32mp13_adc_regspec,
.adc_info = &stm32mp13_adc_info, .adc_info = &stm32mp13_adc_info,
...@@ -2610,6 +2621,7 @@ static const struct stm32_adc_cfg stm32mp13_adc_cfg = { ...@@ -2610,6 +2621,7 @@ static const struct stm32_adc_cfg stm32mp13_adc_cfg = {
.unprepare = stm32h7_adc_unprepare, .unprepare = stm32h7_adc_unprepare,
.smp_cycles = stm32mp13_adc_smp_cycles, .smp_cycles = stm32mp13_adc_smp_cycles,
.irq_clear = stm32h7_adc_irq_clear, .irq_clear = stm32h7_adc_irq_clear,
.ts_int_ch = stm32_adc_min_ts_mp13,
}; };
static const struct of_device_id stm32_adc_of_match[] = { static const struct of_device_id stm32_adc_of_match[] = {
......
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