uboot/drivers/adc/stm32-adc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
   4 * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
   5 *
   6 * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc.c.
   7 */
   8
   9#include <common.h>
  10#include <adc.h>
  11#include <asm/io.h>
  12#include <linux/iopoll.h>
  13#include "stm32-adc-core.h"
  14
  15/* STM32H7 - Registers for each ADC instance */
  16#define STM32H7_ADC_ISR                 0x00
  17#define STM32H7_ADC_CR                  0x08
  18#define STM32H7_ADC_CFGR                0x0C
  19#define STM32H7_ADC_SMPR1               0x14
  20#define STM32H7_ADC_SMPR2               0x18
  21#define STM32H7_ADC_PCSEL               0x1C
  22#define STM32H7_ADC_SQR1                0x30
  23#define STM32H7_ADC_DR                  0x40
  24#define STM32H7_ADC_DIFSEL              0xC0
  25
  26/* STM32H7_ADC_ISR - bit fields */
  27#define STM32MP1_VREGREADY              BIT(12)
  28#define STM32H7_EOC                     BIT(2)
  29#define STM32H7_ADRDY                   BIT(0)
  30
  31/* STM32H7_ADC_CR - bit fields */
  32#define STM32H7_DEEPPWD                 BIT(29)
  33#define STM32H7_ADVREGEN                BIT(28)
  34#define STM32H7_BOOST                   BIT(8)
  35#define STM32H7_ADSTART                 BIT(2)
  36#define STM32H7_ADDIS                   BIT(1)
  37#define STM32H7_ADEN                    BIT(0)
  38
  39/* STM32H7_ADC_CFGR bit fields */
  40#define STM32H7_EXTEN                   GENMASK(11, 10)
  41#define STM32H7_DMNGT                   GENMASK(1, 0)
  42
  43/* STM32H7_ADC_SQR1 - bit fields */
  44#define STM32H7_SQ1_SHIFT               6
  45
  46/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
  47#define STM32H7_BOOST_CLKRATE           20000000UL
  48
  49#define STM32_ADC_CH_MAX                20      /* max number of channels */
  50#define STM32_ADC_TIMEOUT_US            100000
  51
  52struct stm32_adc_cfg {
  53        unsigned int max_channels;
  54        unsigned int num_bits;
  55        bool has_vregready;
  56};
  57
  58struct stm32_adc {
  59        void __iomem *regs;
  60        int active_channel;
  61        const struct stm32_adc_cfg *cfg;
  62};
  63
  64static int stm32_adc_stop(struct udevice *dev)
  65{
  66        struct stm32_adc *adc = dev_get_priv(dev);
  67
  68        setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS);
  69        clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
  70        /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
  71        setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
  72        adc->active_channel = -1;
  73
  74        return 0;
  75}
  76
  77static int stm32_adc_start_channel(struct udevice *dev, int channel)
  78{
  79        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
  80        struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
  81        struct stm32_adc *adc = dev_get_priv(dev);
  82        int ret;
  83        u32 val;
  84
  85        /* Exit deep power down, then enable ADC voltage regulator */
  86        clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
  87        setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN);
  88        if (common->rate > STM32H7_BOOST_CLKRATE)
  89                setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
  90
  91        /* Wait for startup time */
  92        if (!adc->cfg->has_vregready) {
  93                udelay(20);
  94        } else {
  95                ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
  96                                         val & STM32MP1_VREGREADY,
  97                                         STM32_ADC_TIMEOUT_US);
  98                if (ret < 0) {
  99                        stm32_adc_stop(dev);
 100                        dev_err(dev, "Failed to enable vreg: %d\n", ret);
 101                        return ret;
 102                }
 103        }
 104
 105        /* Only use single ended channels */
 106        writel(0, adc->regs + STM32H7_ADC_DIFSEL);
 107
 108        /* Enable ADC, Poll for ADRDY to be set (after adc startup time) */
 109        setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADEN);
 110        ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
 111                                 val & STM32H7_ADRDY, STM32_ADC_TIMEOUT_US);
 112        if (ret < 0) {
 113                stm32_adc_stop(dev);
 114                dev_err(dev, "Failed to enable ADC: %d\n", ret);
 115                return ret;
 116        }
 117
 118        /* Preselect channels */
 119        writel(uc_pdata->channel_mask, adc->regs + STM32H7_ADC_PCSEL);
 120
 121        /* Set sampling time to max value by default */
 122        writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR1);
 123        writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR2);
 124
 125        /* Program regular sequence: chan in SQ1 & len = 0 for one channel */
 126        writel(channel << STM32H7_SQ1_SHIFT, adc->regs + STM32H7_ADC_SQR1);
 127
 128        /* Trigger detection disabled (conversion can be launched in SW) */
 129        clrbits_le32(adc->regs + STM32H7_ADC_CFGR, STM32H7_EXTEN |
 130                     STM32H7_DMNGT);
 131        adc->active_channel = channel;
 132
 133        return 0;
 134}
 135
 136static int stm32_adc_channel_data(struct udevice *dev, int channel,
 137                                  unsigned int *data)
 138{
 139        struct stm32_adc *adc = dev_get_priv(dev);
 140        int ret;
 141        u32 val;
 142
 143        if (channel != adc->active_channel) {
 144                dev_err(dev, "Requested channel is not active!\n");
 145                return -EINVAL;
 146        }
 147
 148        setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADSTART);
 149        ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
 150                                 val & STM32H7_EOC, STM32_ADC_TIMEOUT_US);
 151        if (ret < 0) {
 152                dev_err(dev, "conversion timed out: %d\n", ret);
 153                return ret;
 154        }
 155
 156        *data = readl(adc->regs + STM32H7_ADC_DR);
 157
 158        return 0;
 159}
 160
 161static int stm32_adc_chan_of_init(struct udevice *dev)
 162{
 163        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 164        struct stm32_adc *adc = dev_get_priv(dev);
 165        u32 chans[STM32_ADC_CH_MAX];
 166        int i, num_channels, ret;
 167
 168        /* Retrieve single ended channels listed in device tree */
 169        num_channels = dev_read_size(dev, "st,adc-channels");
 170        if (num_channels < 0) {
 171                dev_err(dev, "can't get st,adc-channels: %d\n", num_channels);
 172                return num_channels;
 173        }
 174        num_channels /= sizeof(u32);
 175
 176        if (num_channels > adc->cfg->max_channels) {
 177                dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
 178                return -EINVAL;
 179        }
 180
 181        ret = dev_read_u32_array(dev, "st,adc-channels", chans, num_channels);
 182        if (ret < 0) {
 183                dev_err(dev, "can't read st,adc-channels: %d\n", ret);
 184                return ret;
 185        }
 186
 187        for (i = 0; i < num_channels; i++) {
 188                if (chans[i] >= adc->cfg->max_channels) {
 189                        dev_err(dev, "bad channel %u\n", chans[i]);
 190                        return -EINVAL;
 191                }
 192                uc_pdata->channel_mask |= 1 << chans[i];
 193        }
 194
 195        uc_pdata->data_mask = (1 << adc->cfg->num_bits) - 1;
 196        uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
 197        uc_pdata->data_timeout_us = 100000;
 198
 199        return 0;
 200}
 201
 202static int stm32_adc_probe(struct udevice *dev)
 203{
 204        struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 205        struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
 206        struct stm32_adc *adc = dev_get_priv(dev);
 207        int offset;
 208
 209        offset = dev_read_u32_default(dev, "reg", -ENODATA);
 210        if (offset < 0) {
 211                dev_err(dev, "Can't read reg property\n");
 212                return offset;
 213        }
 214        adc->regs = common->base + offset;
 215        adc->cfg = (const struct stm32_adc_cfg *)dev_get_driver_data(dev);
 216
 217        /* VDD supplied by common vref pin */
 218        uc_pdata->vdd_supply = common->vref;
 219        uc_pdata->vdd_microvolts = common->vref_uv;
 220        uc_pdata->vss_microvolts = 0;
 221
 222        return stm32_adc_chan_of_init(dev);
 223}
 224
 225static const struct adc_ops stm32_adc_ops = {
 226        .start_channel = stm32_adc_start_channel,
 227        .channel_data = stm32_adc_channel_data,
 228        .stop = stm32_adc_stop,
 229};
 230
 231static const struct stm32_adc_cfg stm32h7_adc_cfg = {
 232        .num_bits = 16,
 233        .max_channels = STM32_ADC_CH_MAX,
 234};
 235
 236static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
 237        .num_bits = 16,
 238        .max_channels = STM32_ADC_CH_MAX,
 239        .has_vregready = true,
 240};
 241
 242static const struct udevice_id stm32_adc_ids[] = {
 243        { .compatible = "st,stm32h7-adc",
 244          .data = (ulong)&stm32h7_adc_cfg },
 245        { .compatible = "st,stm32mp1-adc",
 246          .data = (ulong)&stm32mp1_adc_cfg },
 247        {}
 248};
 249
 250U_BOOT_DRIVER(stm32_adc) = {
 251        .name  = "stm32-adc",
 252        .id = UCLASS_ADC,
 253        .of_match = stm32_adc_ids,
 254        .probe = stm32_adc_probe,
 255        .ops = &stm32_adc_ops,
 256        .priv_auto_alloc_size = sizeof(struct stm32_adc),
 257};
 258