[PATCH 3/8] iio: adc: stm32-adc: add stm32mp13 support

Andy Shevchenko andy.shevchenko at gmail.com
Wed Sep 28 10:07:18 PDT 2022


On Wed, Sep 28, 2022 at 7:42 PM Olivier Moysan
<olivier.moysan at foss.st.com> wrote:
>
> Add STM32 ADC support for STM32MP13x SOCs family.
>
> On STM32MP13x, each ADC peripheral has a single ADC block.
> These ADC peripherals, ADC1 and ADC2, are fully independent.
> This introduces changes in common registers handling.
>
> Some features such as boost mode, channel preselection and
> linear calibration are not supported by the STM32MP13x ADC.
> Add diversity management for these features.
>
> The STM32MP13x ADC introduces registers and bitfield variants
> on existing features such as calibration factors and internal
> channels. Add register diversity management.
>
> Add also support of new internal channels VDDCPU and VDDQ_DDR.

for new

>
> Signed-off-by: Olivier Moysan <olivier.moysan at foss.st.com>
> ---
>  drivers/iio/adc/stm32-adc-core.c |  21 +++
>  drivers/iio/adc/stm32-adc-core.h |  32 +++++
>  drivers/iio/adc/stm32-adc.c      | 212 +++++++++++++++++++++++++++----
>  3 files changed, 237 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
> index 81d5db91c67b..6564aa61b595 100644
> --- a/drivers/iio/adc/stm32-adc-core.c
> +++ b/drivers/iio/adc/stm32-adc-core.c
> @@ -322,6 +322,16 @@ static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
>         .eocie_msk = STM32H7_EOCIE,
>  };
>
> +/* STM32MP13 common registers definitions */
> +static const struct stm32_adc_common_regs stm32mp13_adc_common_regs = {
> +       .csr = STM32H7_ADC_CSR,
> +       .ccr = STM32H7_ADC_CCR,
> +       .eoc_msk = { STM32H7_EOC_MST},
> +       .ovr_msk = { STM32H7_OVR_MST},
> +       .ier = STM32H7_ADC_IER,
> +       .eocie_msk = STM32H7_EOCIE,
> +};
> +
>  static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
>         0, STM32_ADC_OFFSET, STM32_ADC_OFFSET * 2,
>  };
> @@ -868,6 +878,14 @@ static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
>         .num_irqs = 2,
>  };
>
> +static const struct stm32_adc_priv_cfg stm32mp13_adc_priv_cfg = {
> +       .regs = &stm32mp13_adc_common_regs,
> +       .clk_sel = stm32h7_adc_clk_sel,
> +       .max_clk_rate_hz = 75000000,

75 * HZ_PER_MHZ ?

> +       .ipid = STM32MP13_IPIDR_NUMBER,
> +       .num_irqs = 1,
> +};
> +
>  static const struct of_device_id stm32_adc_of_match[] = {
>         {
>                 .compatible = "st,stm32f4-adc-core",
> @@ -878,6 +896,9 @@ static const struct of_device_id stm32_adc_of_match[] = {
>         }, {
>                 .compatible = "st,stm32mp1-adc-core",
>                 .data = (void *)&stm32mp1_adc_priv_cfg
> +       }, {
> +               .compatible = "st,stm32mp13-adc-core",
> +               .data = (void *)&stm32mp13_adc_priv_cfg
>         }, {
>         },
>  };
> diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
> index 2118ef63843d..658fef4308ac 100644
> --- a/drivers/iio/adc/stm32-adc-core.h
> +++ b/drivers/iio/adc/stm32-adc-core.h
> @@ -112,6 +112,11 @@
>  #define STM32MP1_ADC_IPDR              0x3F8
>  #define STM32MP1_ADC_SIDR              0x3FC
>
> +/* STM32MP13 - Registers for each ADC instance */
> +#define STM32MP13_ADC_DIFSEL           0xB0
> +#define STM32MP13_ADC_CALFACT          0xB4
> +#define STM32MP13_ADC2_OR              0xC8
> +
>  /* STM32H7 - common registers for all ADC instances */
>  #define STM32H7_ADC_CSR                        (STM32_ADCX_COMN_OFFSET + 0x00)
>  #define STM32H7_ADC_CCR                        (STM32_ADCX_COMN_OFFSET + 0x08)
> @@ -161,6 +166,10 @@ enum stm32h7_adc_dmngt {
>         STM32H7_DMNGT_DMA_CIRC,         /* DMA circular mode */
>  };
>
> +/* STM32H7_ADC_DIFSEL - bit fields */
> +#define STM32H7_DIFSEL_SHIFT           0
> +#define STM32H7_DIFSEL_MASK            GENMASK(19, 0)
> +
>  /* STM32H7_ADC_CALFACT - bit fields */
>  #define STM32H7_CALFACT_D_SHIFT                16
>  #define STM32H7_CALFACT_D_MASK         GENMASK(26, 16)
> @@ -210,7 +219,30 @@ enum stm32h7_adc_dmngt {
>  /* STM32MP1_ADC_SIDR - bit fields */
>  #define STM32MP1_SIDR_MASK             GENMASK(31, 0)
>
> +/* STM32MP13_ADC_CFGR specific bit fields */
> +#define STM32MP13_DMAEN                        BIT(0)
> +#define STM32MP13_DMACFG               BIT(1)
> +#define STM32MP13_DFSDMCFG             BIT(2)
> +#define STM32MP13_RES_SHIFT            3
> +#define STM32MP13_RES_MASK             GENMASK(4, 3)
> +
> +/* STM32MP13_ADC_DIFSEL - bit fields */
> +#define STM32MP13_DIFSEL_SHIFT         0
> +#define STM32MP13_DIFSEL_MASK          GENMASK(18, 0)
> +
> +/* STM32MP13_ADC_CALFACT - bit fields */
> +#define STM32MP13_CALFACT_D_SHIFT      16
> +#define STM32MP13_CALFACT_D_MASK       GENMASK(22, 16)
> +#define STM32MP13_CALFACT_S_SHIFT      0
> +#define STM32MP13_CALFACT_S_MASK       GENMASK(6, 0)
> +
> +/* STM32MP13_ADC2_OR - bit fields */
> +#define STM32MP13_OP2                  BIT(2)
> +#define STM32MP13_OP1                  BIT(1)
> +#define STM32MP13_OP0                  BIT(0)
> +
>  #define STM32MP15_IPIDR_NUMBER         0x00110005
> +#define STM32MP13_IPIDR_NUMBER         0x00110006
>
>  /**
>   * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
> diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
> index 3cda529f081d..362db64bbd69 100644
> --- a/drivers/iio/adc/stm32-adc.c
> +++ b/drivers/iio/adc/stm32-adc.c
> @@ -82,6 +82,8 @@ enum stm32_adc_extsel {
>  enum stm32_adc_int_ch {
>         STM32_ADC_INT_CH_NONE = -1,
>         STM32_ADC_INT_CH_VDDCORE,
> +       STM32_ADC_INT_CH_VDDCPU,
> +       STM32_ADC_INT_CH_VDDQ_DDR,
>         STM32_ADC_INT_CH_VREFINT,
>         STM32_ADC_INT_CH_VBAT,
>         STM32_ADC_INT_CH_NB,
> @@ -99,6 +101,8 @@ struct stm32_adc_ic {
>
>  static const struct stm32_adc_ic stm32_adc_ic[STM32_ADC_INT_CH_NB] = {
>         { "vddcore", STM32_ADC_INT_CH_VDDCORE },
> +       { "vddcpu", STM32_ADC_INT_CH_VDDCPU },
> +       { "vddq_ddr", STM32_ADC_INT_CH_VDDQ_DDR },
>         { "vrefint", STM32_ADC_INT_CH_VREFINT },
>         { "vbat", STM32_ADC_INT_CH_VBAT },
>  };
> @@ -160,9 +164,14 @@ struct stm32_adc_vrefint {
>   * @exten:             trigger control register & bitfield
>   * @extsel:            trigger selection register & bitfield
>   * @res:               resolution selection register & bitfield
> + * @difsel:            differential mode selection register & bitfield
> + * @calfact_s:         single-ended calibration factors register & bitfield
> + * @calfact_d:         differential calibration factors register & bitfield
>   * @smpr:              smpr1 & smpr2 registers offset array
>   * @smp_bits:          smpr1 & smpr2 index and bitfields
> - * @or_vdd:            option register & vddcore bitfield
> + * @or_vddcore:                option register & vddcore bitfield
> + * @or_vddcpu:         option register & vddcpu bitfield
> + * @or_vddq_ddr:       option register & vddq_ddr bitfield
>   * @ccr_vbat:          common register & vbat bitfield
>   * @ccr_vref:          common register & vrefint bitfield
>   */
> @@ -176,9 +185,14 @@ struct stm32_adc_regspec {
>         const struct stm32_adc_regs exten;
>         const struct stm32_adc_regs extsel;
>         const struct stm32_adc_regs res;
> +       const struct stm32_adc_regs difsel;
> +       const struct stm32_adc_regs calfact_s;
> +       const struct stm32_adc_regs calfact_d;
>         const u32 smpr[2];
>         const struct stm32_adc_regs *smp_bits;
> -       const struct stm32_adc_regs or_vdd;
> +       const struct stm32_adc_regs or_vddcore;
> +       const struct stm32_adc_regs or_vddcpu;
> +       const struct stm32_adc_regs or_vddq_ddr;
>         const struct stm32_adc_regs ccr_vbat;
>         const struct stm32_adc_regs ccr_vref;
>  };
> @@ -192,6 +206,9 @@ struct stm32_adc;
>   * @trigs:             external trigger sources
>   * @clk_required:      clock is required
>   * @has_vregready:     vregready status flag presence
> + * @has_boostmode:     boost mode support flag
> + * @has_linearcal:     linear calibration support flag
> + * @has_presel:                channel preselection support flag
>   * @prepare:           optional prepare routine (power-up, enable)
>   * @start_conv:                routine to start conversions
>   * @stop_conv:         routine to stop conversions
> @@ -206,6 +223,9 @@ struct stm32_adc_cfg {
>         struct stm32_adc_trig_info      *trigs;
>         bool clk_required;
>         bool has_vregready;
> +       bool has_boostmode;
> +       bool has_linearcal;
> +       bool has_presel;
>         int (*prepare)(struct iio_dev *);
>         void (*start_conv)(struct iio_dev *, bool dma);
>         void (*stop_conv)(struct iio_dev *);
> @@ -312,6 +332,13 @@ static const struct stm32_adc_info stm32h7_adc_info = {
>         .num_res = ARRAY_SIZE(stm32h7_adc_resolutions),
>  };
>
> +/* stm32mp13 can have up to 19 channels */
> +static const struct stm32_adc_info stm32mp13_adc_info = {
> +       .max_channels = 19,
> +       .resolutions = stm32f4_adc_resolutions,
> +       .num_res = ARRAY_SIZE(stm32f4_adc_resolutions),
> +};
> +
>  /*
>   * stm32f4_sq - describe regular sequence registers
>   * - L: sequence len (register & bit field)
> @@ -497,8 +524,43 @@ static const struct stm32_adc_regspec stm32h7_adc_regspec = {
>         .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
>                     STM32H7_EXTSEL_SHIFT },
>         .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
> +       .difsel = { STM32H7_ADC_DIFSEL, STM32H7_DIFSEL_MASK},
> +       .calfact_s = { STM32H7_ADC_CALFACT, STM32H7_CALFACT_S_MASK,
> +                      STM32H7_CALFACT_S_SHIFT },
> +       .calfact_d = { STM32H7_ADC_CALFACT, STM32H7_CALFACT_D_MASK,
> +                      STM32H7_CALFACT_D_SHIFT },
> +       .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
> +       .smp_bits = stm32h7_smp_bits,
> +};
> +
> +/* STM32MP13 programmable sampling time (ADC clock cycles, rounded down) */
> +static const unsigned int stm32mp13_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
> +       2, 6, 12, 24, 47, 92, 247, 640,
> +};
> +
> +static const struct stm32_adc_regspec stm32mp13_adc_regspec = {
> +       .dr = STM32H7_ADC_DR,
> +       .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
> +       .ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
> +       .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
> +       .isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
> +       .sqr = stm32h7_sq,
> +       .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
> +       .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
> +                   STM32H7_EXTSEL_SHIFT },
> +       .res = { STM32H7_ADC_CFGR, STM32MP13_RES_MASK, STM32MP13_RES_SHIFT },
> +       .difsel = { STM32MP13_ADC_DIFSEL, STM32MP13_DIFSEL_MASK},
> +       .calfact_s = { STM32MP13_ADC_CALFACT, STM32MP13_CALFACT_S_MASK,
> +                      STM32MP13_CALFACT_S_SHIFT },
> +       .calfact_d = { STM32MP13_ADC_CALFACT, STM32MP13_CALFACT_D_MASK,
> +                      STM32MP13_CALFACT_D_SHIFT },
>         .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
>         .smp_bits = stm32h7_smp_bits,
> +       .or_vddcore = { STM32MP13_ADC2_OR, STM32MP13_OP0 },
> +       .or_vddcpu = { STM32MP13_ADC2_OR, STM32MP13_OP1 },
> +       .or_vddq_ddr = { STM32MP13_ADC2_OR, STM32MP13_OP2 },
> +       .ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN },
> +       .ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN },
>  };
>
>  static const struct stm32_adc_regspec stm32mp1_adc_regspec = {
> @@ -512,9 +574,14 @@ static const struct stm32_adc_regspec stm32mp1_adc_regspec = {
>         .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
>                     STM32H7_EXTSEL_SHIFT },
>         .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
> +       .difsel = { STM32H7_ADC_DIFSEL, STM32H7_DIFSEL_MASK},
> +       .calfact_s = { STM32H7_ADC_CALFACT, STM32H7_CALFACT_S_MASK,
> +                      STM32H7_CALFACT_S_SHIFT },
> +       .calfact_d = { STM32H7_ADC_CALFACT, STM32H7_CALFACT_D_MASK,
> +                      STM32H7_CALFACT_D_SHIFT },
>         .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
>         .smp_bits = stm32h7_smp_bits,
> -       .or_vdd = { STM32MP1_ADC2_OR, STM32MP1_VDDCOREEN },
> +       .or_vddcore = { STM32MP1_ADC2_OR, STM32MP1_VDDCOREEN },
>         .ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN },
>         .ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN },
>  };
> @@ -675,8 +742,18 @@ static void stm32_adc_int_ch_enable(struct iio_dev *indio_dev)
>                 switch (i) {
>                 case STM32_ADC_INT_CH_VDDCORE:
>                         dev_dbg(&indio_dev->dev, "Enable VDDCore\n");
> -                       stm32_adc_set_bits(adc, adc->cfg->regs->or_vdd.reg,
> -                                          adc->cfg->regs->or_vdd.mask);
> +                       stm32_adc_set_bits(adc, adc->cfg->regs->or_vddcore.reg,
> +                                          adc->cfg->regs->or_vddcore.mask);
> +                       break;
> +               case STM32_ADC_INT_CH_VDDCPU:
> +                       dev_dbg(&indio_dev->dev, "Enable VDDCPU\n");
> +                       stm32_adc_set_bits(adc, adc->cfg->regs->or_vddcpu.reg,
> +                                          adc->cfg->regs->or_vddcpu.mask);
> +                       break;
> +               case STM32_ADC_INT_CH_VDDQ_DDR:
> +                       dev_dbg(&indio_dev->dev, "Enable VDDQ_DDR\n");
> +                       stm32_adc_set_bits(adc, adc->cfg->regs->or_vddq_ddr.reg,
> +                                          adc->cfg->regs->or_vddq_ddr.mask);
>                         break;
>                 case STM32_ADC_INT_CH_VREFINT:
>                         dev_dbg(&indio_dev->dev, "Enable VREFInt\n");
> @@ -702,8 +779,16 @@ static void stm32_adc_int_ch_disable(struct stm32_adc *adc)
>
>                 switch (i) {
>                 case STM32_ADC_INT_CH_VDDCORE:
> -                       stm32_adc_clr_bits(adc, adc->cfg->regs->or_vdd.reg,
> -                                          adc->cfg->regs->or_vdd.mask);
> +                       stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddcore.reg,
> +                                          adc->cfg->regs->or_vddcore.mask);
> +                       break;
> +               case STM32_ADC_INT_CH_VDDCPU:
> +                       stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddcpu.reg,
> +                                          adc->cfg->regs->or_vddcpu.mask);
> +                       break;
> +               case STM32_ADC_INT_CH_VDDQ_DDR:
> +                       stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddq_ddr.reg,
> +                                          adc->cfg->regs->or_vddq_ddr.mask);
>                         break;
>                 case STM32_ADC_INT_CH_VREFINT:
>                         stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vref.reg,
> @@ -801,6 +886,7 @@ static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev)
>         if (ret)
>                 dev_warn(&indio_dev->dev, "stop failed\n");
>
> +       /* STM32H7_DMNGT_MASK covers STM32MP13_DMAEN & STM32MP13_DMACFG */
>         stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
>  }
>
> @@ -811,6 +897,17 @@ static void stm32h7_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
>         stm32_adc_set_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
>  }
>
> +static void stm32mp13_adc_start_conv(struct iio_dev *indio_dev, bool dma)
> +{
> +       struct stm32_adc *adc = iio_priv(indio_dev);
> +
> +       if (dma)
> +               stm32_adc_set_bits(adc, STM32H7_ADC_CFGR,
> +                                  STM32MP13_DMAEN | STM32MP13_DMACFG);
> +
> +       stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART);
> +}
> +
>  static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
>  {
>         struct stm32_adc *adc = iio_priv(indio_dev);
> @@ -821,7 +918,8 @@ static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
>         stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
>         stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN);
>
> -       if (adc->common->rate > STM32H7_BOOST_CLKRATE)
> +       if (adc->cfg->has_boostmode &&
> +           adc->common->rate > STM32H7_BOOST_CLKRATE)
>                 stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
>
>         /* Wait for startup time */
> @@ -843,7 +941,8 @@ static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
>
>  static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc)
>  {
> -       stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
> +       if (adc->cfg->has_boostmode)
> +               stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
>
>         /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
>         stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
> @@ -901,6 +1000,9 @@ static int stm32h7_adc_read_selfcalib(struct iio_dev *indio_dev)
>         int i, ret;
>         u32 lincalrdyw_mask, val;
>
> +       if (!adc->cfg->has_linearcal)
> +               goto skip_linearcal;
> +
>         /* Read linearity calibration */
>         lincalrdyw_mask = STM32H7_LINCALRDYW6;
>         for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
> @@ -923,12 +1025,13 @@ static int stm32h7_adc_read_selfcalib(struct iio_dev *indio_dev)
>                 lincalrdyw_mask >>= 1;
>         }
>
> +skip_linearcal:
>         /* Read offset calibration */
> -       val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT);
> -       adc->cal.calfact_s = (val & STM32H7_CALFACT_S_MASK);
> -       adc->cal.calfact_s >>= STM32H7_CALFACT_S_SHIFT;
> -       adc->cal.calfact_d = (val & STM32H7_CALFACT_D_MASK);
> -       adc->cal.calfact_d >>= STM32H7_CALFACT_D_SHIFT;
> +       val = stm32_adc_readl(adc, adc->cfg->regs->calfact_s.reg);
> +       adc->cal.calfact_s = (val & adc->cfg->regs->calfact_s.mask);
> +       adc->cal.calfact_s >>= adc->cfg->regs->calfact_s.shift;
> +       adc->cal.calfact_d = (val & adc->cfg->regs->calfact_d.mask);
> +       adc->cal.calfact_d >>= adc->cfg->regs->calfact_d.shift;
>         adc->cal.calibrated = true;
>
>         return 0;
> @@ -945,9 +1048,12 @@ static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev)
>         int i, ret;
>         u32 lincalrdyw_mask, val;
>
> -       val = (adc->cal.calfact_s << STM32H7_CALFACT_S_SHIFT) |
> -               (adc->cal.calfact_d << STM32H7_CALFACT_D_SHIFT);
> -       stm32_adc_writel(adc, STM32H7_ADC_CALFACT, val);
> +       val = (adc->cal.calfact_s << adc->cfg->regs->calfact_s.shift) |
> +               (adc->cal.calfact_d << adc->cfg->regs->calfact_d.shift);
> +       stm32_adc_writel(adc, adc->cfg->regs->calfact_s.reg, val);
> +
> +       if (!adc->cfg->has_linearcal)
> +               return 0;
>
>         lincalrdyw_mask = STM32H7_LINCALRDYW6;
>         for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
> @@ -1016,11 +1122,13 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev)
>  {
>         struct stm32_adc *adc = iio_priv(indio_dev);
>         int ret;
> -       u32 val;
> +       u32 val, msk = STM32H7_ADCALDIF;
>
>         if (adc->cal.calibrated)
>                 return true;
>
> +       if (adc->cfg->has_linearcal)
> +               msk |= STM32H7_ADCALLIN;
>         /* ADC must be disabled for calibration */
>         stm32h7_adc_disable(indio_dev);
>
> @@ -1029,8 +1137,7 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev)
>          * - Offset calibration for single ended inputs
>          * - No linearity calibration (do it later, before reading it)
>          */
> -       stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADCALDIF);
> -       stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADCALLIN);
> +       stm32_adc_clr_bits(adc, STM32H7_ADC_CR, msk);
>
>         /* Start calibration, then wait for completion */
>         stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL);
> @@ -1048,8 +1155,7 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev)
>          * - Linearity calibration (needs to be done only once for single/diff)
>          *   will run simultaneously with offset calibration.
>          */
> -       stm32_adc_set_bits(adc, STM32H7_ADC_CR,
> -                          STM32H7_ADCALDIF | STM32H7_ADCALLIN);
> +       stm32_adc_set_bits(adc, STM32H7_ADC_CR, msk);
>         stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL);
>         ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
>                                            !(val & STM32H7_ADCAL), 100,
> @@ -1060,8 +1166,7 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev)
>         }
>
>  out:
> -       stm32_adc_clr_bits(adc, STM32H7_ADC_CR,
> -                          STM32H7_ADCALDIF | STM32H7_ADCALLIN);
> +       stm32_adc_clr_bits(adc, STM32H7_ADC_CR, msk);
>
>         return ret;
>  }
> @@ -1093,7 +1198,7 @@ static int stm32h7_adc_prepare(struct iio_dev *indio_dev)
>
>         stm32_adc_int_ch_enable(indio_dev);
>
> -       stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel);
> +       stm32_adc_writel(adc, adc->cfg->regs->difsel.reg, adc->difsel);
>
>         ret = stm32h7_adc_enable(indio_dev);
>         if (ret)
> @@ -1107,7 +1212,8 @@ static int stm32h7_adc_prepare(struct iio_dev *indio_dev)
>         if (ret)
>                 goto disable;
>
> -       stm32_adc_writel(adc, STM32H7_ADC_PCSEL, adc->pcsel);
> +       if (adc->cfg->has_presel)
> +               stm32_adc_writel(adc, STM32H7_ADC_PCSEL, adc->pcsel);
>
>         return 0;
>
> @@ -1125,7 +1231,8 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev)
>  {
>         struct stm32_adc *adc = iio_priv(indio_dev);
>
> -       stm32_adc_writel(adc, STM32H7_ADC_PCSEL, 0);
> +       if (adc->cfg->has_presel)
> +               stm32_adc_writel(adc, STM32H7_ADC_PCSEL, 0);
>         stm32h7_adc_disable(indio_dev);
>         stm32_adc_int_ch_disable(adc);
>         stm32h7_adc_enter_pwr_down(adc);
> @@ -1857,7 +1964,7 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
>         adc->pcsel |= BIT(chan->channel);
>         if (differential) {
>                 /* pre-build diff channels mask */
> -               adc->difsel |= BIT(chan->channel);
> +               adc->difsel |= BIT(chan->channel) & adc->cfg->regs->difsel.mask;
>                 /* Also add negative input to pre-selected channels */
>                 adc->pcsel |= BIT(chan->channel2);
>         }
> @@ -1998,6 +2105,35 @@ static int stm32_adc_populate_int_ch(struct iio_dev *indio_dev, const char *ch_n
>
>         for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
>                 if (!strncmp(stm32_adc_ic[i].name, ch_name, STM32_ADC_CH_SZ)) {
> +                       /* Check internal channel availability */
> +                       switch (i) {
> +                       case STM32_ADC_INT_CH_VDDCORE:
> +                               if (!adc->cfg->regs->or_vddcore.reg)
> +                                       dev_warn(&indio_dev->dev,
> +                                                "%s channel not available\n", ch_name);
> +                               break;
> +                       case STM32_ADC_INT_CH_VDDCPU:
> +                               if (!adc->cfg->regs->or_vddcpu.reg)
> +                                       dev_warn(&indio_dev->dev,
> +                                                "%s channel not available\n", ch_name);
> +                               break;
> +                       case STM32_ADC_INT_CH_VDDQ_DDR:
> +                               if (!adc->cfg->regs->or_vddq_ddr.reg)
> +                                       dev_warn(&indio_dev->dev,
> +                                                "%s channel not available\n", ch_name);
> +                               break;
> +                       case STM32_ADC_INT_CH_VREFINT:
> +                               if (!adc->cfg->regs->ccr_vref.reg)
> +                                       dev_warn(&indio_dev->dev,
> +                                                "%s channel not available\n", ch_name);
> +                               break;
> +                       case STM32_ADC_INT_CH_VBAT:
> +                               if (!adc->cfg->regs->ccr_vbat.reg)
> +                                       dev_warn(&indio_dev->dev,
> +                                                "%s channel not available\n", ch_name);
> +                               break;
> +                       }
> +
>                         if (stm32_adc_ic[i].idx != STM32_ADC_INT_CH_VREFINT) {
>                                 adc->int_ch[i] = chan;
>                                 break;
> @@ -2435,6 +2571,9 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
>         .regs = &stm32h7_adc_regspec,
>         .adc_info = &stm32h7_adc_info,
>         .trigs = stm32h7_adc_trigs,
> +       .has_boostmode = true,
> +       .has_linearcal = true,
> +       .has_presel = true,
>         .start_conv = stm32h7_adc_start_conv,
>         .stop_conv = stm32h7_adc_stop_conv,
>         .prepare = stm32h7_adc_prepare,
> @@ -2448,6 +2587,9 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
>         .adc_info = &stm32h7_adc_info,
>         .trigs = stm32h7_adc_trigs,
>         .has_vregready = true,
> +       .has_boostmode = true,
> +       .has_linearcal = true,
> +       .has_presel = true,
>         .start_conv = stm32h7_adc_start_conv,
>         .stop_conv = stm32h7_adc_stop_conv,
>         .prepare = stm32h7_adc_prepare,
> @@ -2457,10 +2599,24 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
>         .ts_vrefint_ns = 4300,
>  };
>
> +static const struct stm32_adc_cfg stm32mp13_adc_cfg = {
> +       .regs = &stm32mp13_adc_regspec,
> +       .adc_info = &stm32mp13_adc_info,
> +       .trigs = stm32h7_adc_trigs,
> +       .start_conv = stm32mp13_adc_start_conv,
> +       .stop_conv = stm32h7_adc_stop_conv,
> +       .prepare = stm32h7_adc_prepare,
> +       .unprepare = stm32h7_adc_unprepare,
> +       .smp_cycles = stm32mp13_adc_smp_cycles,
> +       .irq_clear = stm32h7_adc_irq_clear,
> +};
> +
>  static const struct of_device_id stm32_adc_of_match[] = {
>         { .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_cfg },
>         { .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg },
>         { .compatible = "st,stm32mp1-adc", .data = (void *)&stm32mp1_adc_cfg },
> +       { .compatible = "st,stm32mp13-adc",
> +         .data = (void *)&stm32mp13_adc_cfg },

I think it would be nicer to have it on one line despite being longer than 80.

>         {},
>  };
>  MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
> --
> 2.25.1
>


-- 
With Best Regards,
Andy Shevchenko



More information about the linux-arm-kernel mailing list