1 // 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-core.c.
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 /* STM32H7 - common registers for all ADC instances */
18 #define STM32H7_ADC_CCR			(STM32_ADCX_COMN_OFFSET + 0x08)
19 
20 /* STM32H7_ADC_CCR - bit fields */
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 /* STM32 H7 maximum analog clock rate (from datasheet) */
27 #define STM32H7_ADC_MAX_CLK_RATE	36000000
28 
29 /**
30  * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
31  * @ckmode: ADC clock mode, Async or sync with prescaler.
32  * @presc: prescaler bitfield for async clock mode
33  * @div: prescaler division ratio
34  */
35 struct stm32h7_adc_ck_spec {
36 	u32 ckmode;
37 	u32 presc;
38 	int div;
39 };
40 
41 static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
42 	/* 00: CK_ADC[1..3]: Asynchronous clock modes */
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 	/* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
56 	{ 1, 0, 1 },
57 	{ 2, 0, 2 },
58 	{ 3, 0, 4 },
59 };
60 
stm32h7_adc_clk_sel(struct udevice * dev,struct stm32_adc_common * common)61 static 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 	/* stm32h7 bus clock is common for all ADC instances (mandatory) */
70 	if (!clk_valid(&common->bclk)) {
71 		dev_err(dev, "No bclk clock found\n");
72 		return -ENOENT;
73 	}
74 
75 	/*
76 	 * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry.
77 	 * So, choice is to have bus clock mandatory and adc clock optional.
78 	 * If optional 'adc' clock has been found, then try to use it first.
79 	 */
80 	if (clk_valid(&common->aclk)) {
81 		/*
82 		 * Asynchronous clock modes (e.g. ckmode == 0)
83 		 * From spec: PLL output musn't exceed max rate
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 	/* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
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 
126 out:
127 	/* rate used later by each ADC instance to control BOOST mode */
128 	common->rate = rate / div;
129 
130 	/* Set common clock mode and prescaler */
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 
stm32_adc_core_probe(struct udevice * dev)142 static 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 
190 err_bclk_disable:
191 	if (clk_valid(&common->bclk))
192 		clk_disable(&common->bclk);
193 
194 err_aclk_disable:
195 	if (clk_valid(&common->aclk))
196 		clk_disable(&common->aclk);
197 
198 	return ret;
199 }
200 
201 static const struct udevice_id stm32_adc_core_ids[] = {
202 	{ .compatible = "st,stm32h7-adc-core" },
203 	{ .compatible = "st,stm32mp1-adc-core" },
204 	{}
205 };
206 
207 U_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	= sizeof(struct stm32_adc_common),
213 };
214