blob: 1fba707c6f7dac054a0ae843d1990e97d8acbc0d [file] [log] [blame]
Fabrice Gasnier5a1da382018-07-24 16:31:31 +02001// 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>
Simon Glass8237eeb2020-07-19 10:15:52 -060011#include <dm.h>
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020012#include <asm/io.h>
Simon Glass9bc15642020-02-03 07:36:16 -070013#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060014#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060015#include <linux/delay.h>
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020016#include <linux/iopoll.h>
17#include "stm32-adc-core.h"
18
19/* STM32H7 - Registers for each ADC instance */
20#define STM32H7_ADC_ISR 0x00
21#define STM32H7_ADC_CR 0x08
22#define STM32H7_ADC_CFGR 0x0C
23#define STM32H7_ADC_SMPR1 0x14
24#define STM32H7_ADC_SMPR2 0x18
25#define STM32H7_ADC_PCSEL 0x1C
26#define STM32H7_ADC_SQR1 0x30
27#define STM32H7_ADC_DR 0x40
28#define STM32H7_ADC_DIFSEL 0xC0
29
30/* STM32H7_ADC_ISR - bit fields */
31#define STM32MP1_VREGREADY BIT(12)
32#define STM32H7_EOC BIT(2)
33#define STM32H7_ADRDY BIT(0)
34
35/* STM32H7_ADC_CR - bit fields */
Olivier Moysan28dde162022-12-15 13:51:10 +010036#define STM32H7_ADCAL BIT(31)
37#define STM32H7_ADCALDIF BIT(30)
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020038#define STM32H7_DEEPPWD BIT(29)
39#define STM32H7_ADVREGEN BIT(28)
Olivier Moysan28dde162022-12-15 13:51:10 +010040#define STM32H7_ADCALLIN BIT(16)
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020041#define STM32H7_BOOST BIT(8)
42#define STM32H7_ADSTART BIT(2)
43#define STM32H7_ADDIS BIT(1)
44#define STM32H7_ADEN BIT(0)
45
46/* STM32H7_ADC_CFGR bit fields */
47#define STM32H7_EXTEN GENMASK(11, 10)
48#define STM32H7_DMNGT GENMASK(1, 0)
49
50/* STM32H7_ADC_SQR1 - bit fields */
51#define STM32H7_SQ1_SHIFT 6
52
53/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
54#define STM32H7_BOOST_CLKRATE 20000000UL
55
56#define STM32_ADC_CH_MAX 20 /* max number of channels */
57#define STM32_ADC_TIMEOUT_US 100000
58
59struct stm32_adc_cfg {
60 unsigned int max_channels;
61 unsigned int num_bits;
62 bool has_vregready;
63};
64
65struct stm32_adc {
66 void __iomem *regs;
67 int active_channel;
68 const struct stm32_adc_cfg *cfg;
69};
70
Olivier Moysan28dde162022-12-15 13:51:10 +010071static void stm32_adc_enter_pwr_down(struct udevice *dev)
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020072{
73 struct stm32_adc *adc = dev_get_priv(dev);
74
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020075 clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
76 /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
77 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020078}
79
Olivier Moysan28dde162022-12-15 13:51:10 +010080static int stm32_adc_exit_pwr_down(struct udevice *dev)
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020081{
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020082 struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
83 struct stm32_adc *adc = dev_get_priv(dev);
84 int ret;
85 u32 val;
86
Olivier Moysan28dde162022-12-15 13:51:10 +010087 /* return immediately if ADC is not in deep power down mode */
88 if (!(readl(adc->regs + STM32H7_ADC_CR) & STM32H7_DEEPPWD))
89 return 0;
90
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020091 /* Exit deep power down, then enable ADC voltage regulator */
92 clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
93 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN);
Olivier Moysan28dde162022-12-15 13:51:10 +010094
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020095 if (common->rate > STM32H7_BOOST_CLKRATE)
96 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
97
98 /* Wait for startup time */
99 if (!adc->cfg->has_vregready) {
100 udelay(20);
Olivier Moysan28dde162022-12-15 13:51:10 +0100101 return 0;
102 }
103
104 ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
105 val & STM32MP1_VREGREADY,
106 STM32_ADC_TIMEOUT_US);
107 if (ret < 0) {
108 stm32_adc_enter_pwr_down(dev);
109 dev_err(dev, "Failed to enable vreg: %d\n", ret);
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200110 }
111
Olivier Moysan28dde162022-12-15 13:51:10 +0100112 return ret;
113}
114
115static int stm32_adc_stop(struct udevice *dev)
116{
117 struct stm32_adc *adc = dev_get_priv(dev);
118
119 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS);
120 stm32_adc_enter_pwr_down(dev);
121 adc->active_channel = -1;
122
123 return 0;
124}
125
126static int stm32_adc_start_channel(struct udevice *dev, int channel)
127{
128 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
129 struct stm32_adc *adc = dev_get_priv(dev);
130 int ret;
131 u32 val;
132
133 ret = stm32_adc_exit_pwr_down(dev);
134 if (ret < 0)
135 return ret;
136
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200137 /* Only use single ended channels */
138 writel(0, adc->regs + STM32H7_ADC_DIFSEL);
139
140 /* Enable ADC, Poll for ADRDY to be set (after adc startup time) */
141 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADEN);
142 ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
143 val & STM32H7_ADRDY, STM32_ADC_TIMEOUT_US);
144 if (ret < 0) {
145 stm32_adc_stop(dev);
146 dev_err(dev, "Failed to enable ADC: %d\n", ret);
147 return ret;
148 }
149
150 /* Preselect channels */
151 writel(uc_pdata->channel_mask, adc->regs + STM32H7_ADC_PCSEL);
152
153 /* Set sampling time to max value by default */
154 writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR1);
155 writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR2);
156
157 /* Program regular sequence: chan in SQ1 & len = 0 for one channel */
158 writel(channel << STM32H7_SQ1_SHIFT, adc->regs + STM32H7_ADC_SQR1);
159
160 /* Trigger detection disabled (conversion can be launched in SW) */
161 clrbits_le32(adc->regs + STM32H7_ADC_CFGR, STM32H7_EXTEN |
162 STM32H7_DMNGT);
163 adc->active_channel = channel;
164
165 return 0;
166}
167
168static int stm32_adc_channel_data(struct udevice *dev, int channel,
169 unsigned int *data)
170{
171 struct stm32_adc *adc = dev_get_priv(dev);
172 int ret;
173 u32 val;
174
175 if (channel != adc->active_channel) {
176 dev_err(dev, "Requested channel is not active!\n");
177 return -EINVAL;
178 }
179
180 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADSTART);
181 ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
182 val & STM32H7_EOC, STM32_ADC_TIMEOUT_US);
183 if (ret < 0) {
184 dev_err(dev, "conversion timed out: %d\n", ret);
185 return ret;
186 }
187
188 *data = readl(adc->regs + STM32H7_ADC_DR);
189
190 return 0;
191}
192
Olivier Moysan28dde162022-12-15 13:51:10 +0100193/**
194 * Fixed timeout value for ADC calibration.
195 * worst cases:
196 * - low clock frequency (0.12 MHz min)
197 * - maximum prescalers
198 * Calibration requires:
199 * - 16384 ADC clock cycle for the linear calibration
200 * - 20 ADC clock cycle for the offset calibration
201 *
202 * Set to 100ms for now
203 */
204#define STM32H7_ADC_CALIB_TIMEOUT_US 100000
205
206static int stm32_adc_selfcalib(struct udevice *dev)
207{
208 struct stm32_adc *adc = dev_get_priv(dev);
209 int ret;
210 u32 val;
211
212 /*
213 * Select calibration mode:
214 * - Offset calibration for single ended inputs
215 * - No linearity calibration. Done in next step.
216 */
217 clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN);
218
219 /* Start calibration, then wait for completion */
220 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCAL);
221 ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val,
222 !(val & STM32H7_ADCAL), 100,
223 STM32H7_ADC_CALIB_TIMEOUT_US);
224 if (ret) {
225 dev_err(dev, "calibration failed\n");
226 goto out;
227 }
228
229 /*
230 * Select calibration mode, then start calibration:
231 * - Offset calibration for differential input
232 * - Linearity calibration (needs to be done only once for single/diff)
233 * will run simultaneously with offset calibration.
234 */
235 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN);
236
237 /* Start calibration, then wait for completion */
238 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCAL);
239 ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val,
240 !(val & STM32H7_ADCAL), 100,
241 STM32H7_ADC_CALIB_TIMEOUT_US);
242 if (ret)
243 dev_err(dev, "calibration failed\n");
244
245out:
246 clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN);
247
248 return ret;
249}
250
Olivier Moysanf3850e92022-11-23 16:20:15 +0100251static int stm32_adc_get_legacy_chan_count(struct udevice *dev)
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200252{
Patrick Delaunay35fc48d2019-06-21 15:26:44 +0200253 int ret;
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200254
255 /* Retrieve single ended channels listed in device tree */
Patrick Delaunay35fc48d2019-06-21 15:26:44 +0200256 ret = dev_read_size(dev, "st,adc-channels");
257 if (ret < 0) {
258 dev_err(dev, "can't get st,adc-channels: %d\n", ret);
259 return ret;
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200260 }
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200261
Olivier Moysanf3850e92022-11-23 16:20:15 +0100262 return (ret / sizeof(u32));
263}
264
265static int stm32_adc_legacy_chan_init(struct udevice *dev, unsigned int num_channels)
266{
267 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
268 struct stm32_adc *adc = dev_get_priv(dev);
269 u32 chans[STM32_ADC_CH_MAX];
270 int i, ret;
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200271
272 ret = dev_read_u32_array(dev, "st,adc-channels", chans, num_channels);
273 if (ret < 0) {
274 dev_err(dev, "can't read st,adc-channels: %d\n", ret);
275 return ret;
276 }
277
278 for (i = 0; i < num_channels; i++) {
279 if (chans[i] >= adc->cfg->max_channels) {
280 dev_err(dev, "bad channel %u\n", chans[i]);
281 return -EINVAL;
282 }
283 uc_pdata->channel_mask |= 1 << chans[i];
284 }
285
Olivier Moysanf3850e92022-11-23 16:20:15 +0100286 return ret;
287}
288
Olivier Moysancd9cf582022-11-23 16:20:16 +0100289static int stm32_adc_generic_chan_init(struct udevice *dev, unsigned int num_channels)
290{
291 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
292 struct stm32_adc *adc = dev_get_priv(dev);
293 ofnode child;
294 int val, ret;
295
296 ofnode_for_each_subnode(child, dev_ofnode(dev)) {
297 ret = ofnode_read_u32(child, "reg", &val);
298 if (ret) {
299 dev_err(dev, "Missing channel index %d\n", ret);
300 return ret;
301 }
302
303 if (val >= adc->cfg->max_channels) {
304 dev_err(dev, "Invalid channel %d\n", val);
305 return -EINVAL;
306 }
307
308 uc_pdata->channel_mask |= 1 << val;
309 }
310
311 return 0;
312}
313
Olivier Moysanf3850e92022-11-23 16:20:15 +0100314static int stm32_adc_chan_of_init(struct udevice *dev)
315{
316 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
317 struct stm32_adc *adc = dev_get_priv(dev);
318 unsigned int num_channels;
319 int ret;
Olivier Moysancd9cf582022-11-23 16:20:16 +0100320 bool legacy = false;
Olivier Moysanf3850e92022-11-23 16:20:15 +0100321
Olivier Moysancd9cf582022-11-23 16:20:16 +0100322 num_channels = dev_get_child_count(dev);
323 /* If no channels have been found, fallback to channels legacy properties. */
324 if (!num_channels) {
325 legacy = true;
326
327 ret = stm32_adc_get_legacy_chan_count(dev);
328 if (!ret) {
329 dev_err(dev, "No channel found\n");
330 return -ENODATA;
331 } else if (ret < 0) {
332 return ret;
333 }
334 num_channels = ret;
335 }
Olivier Moysanf3850e92022-11-23 16:20:15 +0100336
337 if (num_channels > adc->cfg->max_channels) {
338 dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
339 return -EINVAL;
340 }
341
Olivier Moysancd9cf582022-11-23 16:20:16 +0100342 if (legacy)
343 ret = stm32_adc_legacy_chan_init(dev, num_channels);
344 else
345 ret = stm32_adc_generic_chan_init(dev, num_channels);
Olivier Moysanf3850e92022-11-23 16:20:15 +0100346 if (ret < 0)
347 return ret;
348
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200349 uc_pdata->data_mask = (1 << adc->cfg->num_bits) - 1;
350 uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
351 uc_pdata->data_timeout_us = 100000;
352
353 return 0;
354}
355
356static int stm32_adc_probe(struct udevice *dev)
357{
Simon Glass71fa5b42020-12-03 16:55:18 -0700358 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200359 struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
360 struct stm32_adc *adc = dev_get_priv(dev);
Olivier Moysan28dde162022-12-15 13:51:10 +0100361 int offset, ret;
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200362
363 offset = dev_read_u32_default(dev, "reg", -ENODATA);
364 if (offset < 0) {
365 dev_err(dev, "Can't read reg property\n");
366 return offset;
367 }
368 adc->regs = common->base + offset;
369 adc->cfg = (const struct stm32_adc_cfg *)dev_get_driver_data(dev);
370
371 /* VDD supplied by common vref pin */
372 uc_pdata->vdd_supply = common->vref;
373 uc_pdata->vdd_microvolts = common->vref_uv;
374 uc_pdata->vss_microvolts = 0;
375
Olivier Moysan28dde162022-12-15 13:51:10 +0100376 ret = stm32_adc_chan_of_init(dev);
377 if (ret < 0)
378 return ret;
379
380 ret = stm32_adc_exit_pwr_down(dev);
381 if (ret < 0)
382 return ret;
383
384 ret = stm32_adc_selfcalib(dev);
385 if (ret)
386 stm32_adc_enter_pwr_down(dev);
387
388 return ret;
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200389}
390
391static const struct adc_ops stm32_adc_ops = {
392 .start_channel = stm32_adc_start_channel,
393 .channel_data = stm32_adc_channel_data,
394 .stop = stm32_adc_stop,
395};
396
397static const struct stm32_adc_cfg stm32h7_adc_cfg = {
398 .num_bits = 16,
399 .max_channels = STM32_ADC_CH_MAX,
400};
401
402static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
403 .num_bits = 16,
404 .max_channels = STM32_ADC_CH_MAX,
405 .has_vregready = true,
406};
407
408static const struct udevice_id stm32_adc_ids[] = {
409 { .compatible = "st,stm32h7-adc",
410 .data = (ulong)&stm32h7_adc_cfg },
411 { .compatible = "st,stm32mp1-adc",
412 .data = (ulong)&stm32mp1_adc_cfg },
413 {}
414};
415
416U_BOOT_DRIVER(stm32_adc) = {
417 .name = "stm32-adc",
418 .id = UCLASS_ADC,
419 .of_match = stm32_adc_ids,
420 .probe = stm32_adc_probe,
421 .ops = &stm32_adc_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700422 .priv_auto = sizeof(struct stm32_adc),
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200423};