1
2
3
4
5
6
7
8
9#include <common.h>
10#include <dm.h>
11#include <asm/io.h>
12#include <dm/device_compat.h>
13#include <linux/bitops.h>
14#include <power/regulator.h>
15#include "stm32-adc-core.h"
16
17
18#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
19
20
21#define STM32H7_PRESC_SHIFT 18
22#define STM32H7_PRESC_MASK GENMASK(21, 18)
23#define STM32H7_CKMODE_SHIFT 16
24#define STM32H7_CKMODE_MASK GENMASK(17, 16)
25
26
27#define STM32H7_ADC_MAX_CLK_RATE 36000000
28
29
30
31
32
33
34
35struct stm32h7_adc_ck_spec {
36 u32 ckmode;
37 u32 presc;
38 int div;
39};
40
41static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
42
43 { 0, 0, 1 },
44 { 0, 1, 2 },
45 { 0, 2, 4 },
46 { 0, 3, 6 },
47 { 0, 4, 8 },
48 { 0, 5, 10 },
49 { 0, 6, 12 },
50 { 0, 7, 16 },
51 { 0, 8, 32 },
52 { 0, 9, 64 },
53 { 0, 10, 128 },
54 { 0, 11, 256 },
55
56 { 1, 0, 1 },
57 { 2, 0, 2 },
58 { 3, 0, 4 },
59};
60
61static int stm32h7_adc_clk_sel(struct udevice *dev,
62 struct stm32_adc_common *common)
63{
64 u32 ckmode, presc;
65 unsigned long rate;
66 unsigned int i;
67 int div;
68
69
70 if (!clk_valid(&common->bclk)) {
71 dev_err(dev, "No bclk clock found\n");
72 return -ENOENT;
73 }
74
75
76
77
78
79
80 if (clk_valid(&common->aclk)) {
81
82
83
84
85 rate = clk_get_rate(&common->aclk);
86 if (!rate) {
87 dev_err(dev, "Invalid aclk rate: 0\n");
88 return -EINVAL;
89 }
90
91 for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
92 ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
93 presc = stm32h7_adc_ckmodes_spec[i].presc;
94 div = stm32h7_adc_ckmodes_spec[i].div;
95
96 if (ckmode)
97 continue;
98
99 if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
100 goto out;
101 }
102 }
103
104
105 rate = clk_get_rate(&common->bclk);
106 if (!rate) {
107 dev_err(dev, "Invalid bus clock rate: 0\n");
108 return -EINVAL;
109 }
110
111 for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
112 ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
113 presc = stm32h7_adc_ckmodes_spec[i].presc;
114 div = stm32h7_adc_ckmodes_spec[i].div;
115
116 if (!ckmode)
117 continue;
118
119 if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
120 goto out;
121 }
122
123 dev_err(dev, "clk selection failed\n");
124 return -EINVAL;
125
126out:
127
128 common->rate = rate / div;
129
130
131 clrsetbits_le32(common->base + STM32H7_ADC_CCR,
132 STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK,
133 ckmode << STM32H7_CKMODE_SHIFT |
134 presc << STM32H7_PRESC_SHIFT);
135
136 dev_dbg(dev, "Using %s clock/%d source at %ld kHz\n",
137 ckmode ? "bus" : "adc", div, common->rate / 1000);
138
139 return 0;
140}
141
142static int stm32_adc_core_probe(struct udevice *dev)
143{
144 struct stm32_adc_common *common = dev_get_priv(dev);
145 int ret;
146
147 common->base = dev_read_addr_ptr(dev);
148 if (!common->base) {
149 dev_err(dev, "can't get address\n");
150 return -ENOENT;
151 }
152
153 ret = device_get_supply_regulator(dev, "vref-supply", &common->vref);
154 if (ret) {
155 dev_err(dev, "can't get vref-supply: %d\n", ret);
156 return ret;
157 }
158
159 ret = regulator_get_value(common->vref);
160 if (ret < 0) {
161 dev_err(dev, "can't get vref-supply value: %d\n", ret);
162 return ret;
163 }
164 common->vref_uv = ret;
165
166 ret = clk_get_by_name(dev, "adc", &common->aclk);
167 if (!ret) {
168 ret = clk_enable(&common->aclk);
169 if (ret) {
170 dev_err(dev, "Can't enable aclk: %d\n", ret);
171 return ret;
172 }
173 }
174
175 ret = clk_get_by_name(dev, "bus", &common->bclk);
176 if (!ret) {
177 ret = clk_enable(&common->bclk);
178 if (ret) {
179 dev_err(dev, "Can't enable bclk: %d\n", ret);
180 goto err_aclk_disable;
181 }
182 }
183
184 ret = stm32h7_adc_clk_sel(dev, common);
185 if (ret)
186 goto err_bclk_disable;
187
188 return ret;
189
190err_bclk_disable:
191 if (clk_valid(&common->bclk))
192 clk_disable(&common->bclk);
193
194err_aclk_disable:
195 if (clk_valid(&common->aclk))
196 clk_disable(&common->aclk);
197
198 return ret;
199}
200
201static const struct udevice_id stm32_adc_core_ids[] = {
202 { .compatible = "st,stm32h7-adc-core" },
203 { .compatible = "st,stm32mp1-adc-core" },
204 {}
205};
206
207U_BOOT_DRIVER(stm32_adc_core) = {
208 .name = "stm32-adc-core",
209 .id = UCLASS_SIMPLE_BUS,
210 .of_match = stm32_adc_core_ids,
211 .probe = stm32_adc_core_probe,
212 .priv_auto_alloc_size = sizeof(struct stm32_adc_common),
213};
214