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