blob: 85efc119dbf15b2db647f4f5e708ea31fc76a146 [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 */
36#define STM32H7_DEEPPWD BIT(29)
37#define STM32H7_ADVREGEN BIT(28)
38#define STM32H7_BOOST BIT(8)
39#define STM32H7_ADSTART BIT(2)
40#define STM32H7_ADDIS BIT(1)
41#define STM32H7_ADEN BIT(0)
42
43/* STM32H7_ADC_CFGR bit fields */
44#define STM32H7_EXTEN GENMASK(11, 10)
45#define STM32H7_DMNGT GENMASK(1, 0)
46
47/* STM32H7_ADC_SQR1 - bit fields */
48#define STM32H7_SQ1_SHIFT 6
49
50/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
51#define STM32H7_BOOST_CLKRATE 20000000UL
52
53#define STM32_ADC_CH_MAX 20 /* max number of channels */
54#define STM32_ADC_TIMEOUT_US 100000
55
56struct stm32_adc_cfg {
57 unsigned int max_channels;
58 unsigned int num_bits;
59 bool has_vregready;
60};
61
62struct stm32_adc {
63 void __iomem *regs;
64 int active_channel;
65 const struct stm32_adc_cfg *cfg;
66};
67
68static int stm32_adc_stop(struct udevice *dev)
69{
70 struct stm32_adc *adc = dev_get_priv(dev);
71
72 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS);
73 clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
74 /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
75 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
76 adc->active_channel = -1;
77
78 return 0;
79}
80
81static int stm32_adc_start_channel(struct udevice *dev, int channel)
82{
Simon Glass71fa5b42020-12-03 16:55:18 -070083 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
Fabrice Gasnier5a1da382018-07-24 16:31:31 +020084 struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
85 struct stm32_adc *adc = dev_get_priv(dev);
86 int ret;
87 u32 val;
88
89 /* Exit deep power down, then enable ADC voltage regulator */
90 clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
91 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN);
92 if (common->rate > STM32H7_BOOST_CLKRATE)
93 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
94
95 /* Wait for startup time */
96 if (!adc->cfg->has_vregready) {
97 udelay(20);
98 } else {
99 ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
100 val & STM32MP1_VREGREADY,
101 STM32_ADC_TIMEOUT_US);
102 if (ret < 0) {
103 stm32_adc_stop(dev);
104 dev_err(dev, "Failed to enable vreg: %d\n", ret);
105 return ret;
106 }
107 }
108
109 /* Only use single ended channels */
110 writel(0, adc->regs + STM32H7_ADC_DIFSEL);
111
112 /* Enable ADC, Poll for ADRDY to be set (after adc startup time) */
113 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADEN);
114 ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
115 val & STM32H7_ADRDY, STM32_ADC_TIMEOUT_US);
116 if (ret < 0) {
117 stm32_adc_stop(dev);
118 dev_err(dev, "Failed to enable ADC: %d\n", ret);
119 return ret;
120 }
121
122 /* Preselect channels */
123 writel(uc_pdata->channel_mask, adc->regs + STM32H7_ADC_PCSEL);
124
125 /* Set sampling time to max value by default */
126 writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR1);
127 writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR2);
128
129 /* Program regular sequence: chan in SQ1 & len = 0 for one channel */
130 writel(channel << STM32H7_SQ1_SHIFT, adc->regs + STM32H7_ADC_SQR1);
131
132 /* Trigger detection disabled (conversion can be launched in SW) */
133 clrbits_le32(adc->regs + STM32H7_ADC_CFGR, STM32H7_EXTEN |
134 STM32H7_DMNGT);
135 adc->active_channel = channel;
136
137 return 0;
138}
139
140static int stm32_adc_channel_data(struct udevice *dev, int channel,
141 unsigned int *data)
142{
143 struct stm32_adc *adc = dev_get_priv(dev);
144 int ret;
145 u32 val;
146
147 if (channel != adc->active_channel) {
148 dev_err(dev, "Requested channel is not active!\n");
149 return -EINVAL;
150 }
151
152 setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADSTART);
153 ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
154 val & STM32H7_EOC, STM32_ADC_TIMEOUT_US);
155 if (ret < 0) {
156 dev_err(dev, "conversion timed out: %d\n", ret);
157 return ret;
158 }
159
160 *data = readl(adc->regs + STM32H7_ADC_DR);
161
162 return 0;
163}
164
Olivier Moysanf3850e92022-11-23 16:20:15 +0100165static int stm32_adc_get_legacy_chan_count(struct udevice *dev)
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200166{
Patrick Delaunay35fc48d2019-06-21 15:26:44 +0200167 int ret;
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200168
169 /* Retrieve single ended channels listed in device tree */
Patrick Delaunay35fc48d2019-06-21 15:26:44 +0200170 ret = dev_read_size(dev, "st,adc-channels");
171 if (ret < 0) {
172 dev_err(dev, "can't get st,adc-channels: %d\n", ret);
173 return ret;
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200174 }
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200175
Olivier Moysanf3850e92022-11-23 16:20:15 +0100176 return (ret / sizeof(u32));
177}
178
179static int stm32_adc_legacy_chan_init(struct udevice *dev, unsigned int num_channels)
180{
181 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
182 struct stm32_adc *adc = dev_get_priv(dev);
183 u32 chans[STM32_ADC_CH_MAX];
184 int i, ret;
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200185
186 ret = dev_read_u32_array(dev, "st,adc-channels", chans, num_channels);
187 if (ret < 0) {
188 dev_err(dev, "can't read st,adc-channels: %d\n", ret);
189 return ret;
190 }
191
192 for (i = 0; i < num_channels; i++) {
193 if (chans[i] >= adc->cfg->max_channels) {
194 dev_err(dev, "bad channel %u\n", chans[i]);
195 return -EINVAL;
196 }
197 uc_pdata->channel_mask |= 1 << chans[i];
198 }
199
Olivier Moysanf3850e92022-11-23 16:20:15 +0100200 return ret;
201}
202
Olivier Moysancd9cf582022-11-23 16:20:16 +0100203static int stm32_adc_generic_chan_init(struct udevice *dev, unsigned int num_channels)
204{
205 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
206 struct stm32_adc *adc = dev_get_priv(dev);
207 ofnode child;
208 int val, ret;
209
210 ofnode_for_each_subnode(child, dev_ofnode(dev)) {
211 ret = ofnode_read_u32(child, "reg", &val);
212 if (ret) {
213 dev_err(dev, "Missing channel index %d\n", ret);
214 return ret;
215 }
216
217 if (val >= adc->cfg->max_channels) {
218 dev_err(dev, "Invalid channel %d\n", val);
219 return -EINVAL;
220 }
221
222 uc_pdata->channel_mask |= 1 << val;
223 }
224
225 return 0;
226}
227
Olivier Moysanf3850e92022-11-23 16:20:15 +0100228static int stm32_adc_chan_of_init(struct udevice *dev)
229{
230 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
231 struct stm32_adc *adc = dev_get_priv(dev);
232 unsigned int num_channels;
233 int ret;
Olivier Moysancd9cf582022-11-23 16:20:16 +0100234 bool legacy = false;
Olivier Moysanf3850e92022-11-23 16:20:15 +0100235
Olivier Moysancd9cf582022-11-23 16:20:16 +0100236 num_channels = dev_get_child_count(dev);
237 /* If no channels have been found, fallback to channels legacy properties. */
238 if (!num_channels) {
239 legacy = true;
240
241 ret = stm32_adc_get_legacy_chan_count(dev);
242 if (!ret) {
243 dev_err(dev, "No channel found\n");
244 return -ENODATA;
245 } else if (ret < 0) {
246 return ret;
247 }
248 num_channels = ret;
249 }
Olivier Moysanf3850e92022-11-23 16:20:15 +0100250
251 if (num_channels > adc->cfg->max_channels) {
252 dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
253 return -EINVAL;
254 }
255
Olivier Moysancd9cf582022-11-23 16:20:16 +0100256 if (legacy)
257 ret = stm32_adc_legacy_chan_init(dev, num_channels);
258 else
259 ret = stm32_adc_generic_chan_init(dev, num_channels);
Olivier Moysanf3850e92022-11-23 16:20:15 +0100260 if (ret < 0)
261 return ret;
262
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200263 uc_pdata->data_mask = (1 << adc->cfg->num_bits) - 1;
264 uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
265 uc_pdata->data_timeout_us = 100000;
266
267 return 0;
268}
269
270static int stm32_adc_probe(struct udevice *dev)
271{
Simon Glass71fa5b42020-12-03 16:55:18 -0700272 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200273 struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
274 struct stm32_adc *adc = dev_get_priv(dev);
275 int offset;
276
277 offset = dev_read_u32_default(dev, "reg", -ENODATA);
278 if (offset < 0) {
279 dev_err(dev, "Can't read reg property\n");
280 return offset;
281 }
282 adc->regs = common->base + offset;
283 adc->cfg = (const struct stm32_adc_cfg *)dev_get_driver_data(dev);
284
285 /* VDD supplied by common vref pin */
286 uc_pdata->vdd_supply = common->vref;
287 uc_pdata->vdd_microvolts = common->vref_uv;
288 uc_pdata->vss_microvolts = 0;
289
290 return stm32_adc_chan_of_init(dev);
291}
292
293static const struct adc_ops stm32_adc_ops = {
294 .start_channel = stm32_adc_start_channel,
295 .channel_data = stm32_adc_channel_data,
296 .stop = stm32_adc_stop,
297};
298
299static const struct stm32_adc_cfg stm32h7_adc_cfg = {
300 .num_bits = 16,
301 .max_channels = STM32_ADC_CH_MAX,
302};
303
304static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
305 .num_bits = 16,
306 .max_channels = STM32_ADC_CH_MAX,
307 .has_vregready = true,
308};
309
310static const struct udevice_id stm32_adc_ids[] = {
311 { .compatible = "st,stm32h7-adc",
312 .data = (ulong)&stm32h7_adc_cfg },
313 { .compatible = "st,stm32mp1-adc",
314 .data = (ulong)&stm32mp1_adc_cfg },
315 {}
316};
317
318U_BOOT_DRIVER(stm32_adc) = {
319 .name = "stm32-adc",
320 .id = UCLASS_ADC,
321 .of_match = stm32_adc_ids,
322 .probe = stm32_adc_probe,
323 .ops = &stm32_adc_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700324 .priv_auto = sizeof(struct stm32_adc),
Fabrice Gasnier5a1da382018-07-24 16:31:31 +0200325};