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