xref: /optee_os/core/drivers/regulator/stm32_vrefbuf.c (revision 86dbb179ca94ad5512680d4a7691447c47f3bdb1)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2021-2023, STMicroelectronics
4  */
5 
6 #include <drivers/clk.h>
7 #include <drivers/clk_dt.h>
8 #include <drivers/regulator.h>
9 #include <drivers/stm32_vrefbuf.h>
10 #include <initcall.h>
11 #include <io.h>
12 #include <keep.h>
13 #include <kernel/delay.h>
14 #include <kernel/pm.h>
15 #include <libfdt.h>
16 #include <mm/core_memprot.h>
17 
18 /* STM32 VREFBUF registers */
19 #define VREFBUF_CSR			U(0)
20 
21 /* STM32 VREFBUF CSR bitfields */
22 
23 /* VRS bit 3 is unused because the voltage is not specified */
24 #define VREFBUF_CSR_VRS			GENMASK_32(5, 4)
25 #define VREFBUF_CSR_VRS_SHIFT		U(4)
26 #define INV_VRS(x)			((~(x)) & VREFBUF_CSR_VRS)
27 
28 #define VREFBUF_CSR_VRR			BIT(3)
29 #define VREFBUF_CSR_HIZ			BIT(1)
30 #define VREFBUF_CSR_ENVR			BIT(0)
31 
32 #define TIMEOUT_US_10MS			U(10 * 1000)
33 #define TIMEOUT_US_1MS			U(1 * 1000)
34 
35 #define VREFBUF_LEVELS_COUNT		U(4)
36 
37 /*
38  * struct vrefbuf_compat - Compatibility data
39  * @voltages: Voltage levels supported
40  */
41 struct vrefbuf_compat {
42 	int voltages[VREFBUF_LEVELS_COUNT];
43 };
44 
45 /*
46  * struct vrefbuf_regul - VREFBUF regulator
47  * @base: IO memory base address
48  * @clock: VREFBUF access bus clock
49  * @regulator: Preallocated instance for the regulator
50  * @compat: Compatibility data
51  * @voltages_desc: Supported voltage level description
52  * @voltages_level: Supplorted levels description
53  * @voltages_start_index: start index in compat for supported levels
54  */
55 struct vrefbuf_regul {
56 	vaddr_t base;
57 	struct clk *clock;
58 	uint64_t disable_timeout;
59 	struct regulator regulator;
60 	const struct vrefbuf_compat *compat;
61 	struct regulator_voltages_desc voltages_desc;
62 	size_t voltages_start_index;
63 };
64 
65 static const struct vrefbuf_compat stm32mp15_vrefbuf_compat = {
66 	.voltages = {
67 		/* Matches resp. VRS = 011b, 010b, 001b, 000b */
68 		1500000, 1800000, 2048000, 2500000,
69 	},
70 };
71 
72 static const struct vrefbuf_compat stm32mp13_vrefbuf_compat = {
73 	.voltages = {
74 		/* Matches resp. VRS = 011b, 010b, 001b, 000b */
75 		1650000, 1800000, 2048000, 2500000,
76 	},
77 };
78 
79 /* Expect at most 1 instance */
80 static struct vrefbuf_regul *stm32_vrefbuf;
81 
82 struct regulator *stm32_vrefbuf_regulator(void)
83 {
84 	if (!stm32_vrefbuf)
85 		return NULL;
86 
87 	return &stm32_vrefbuf->regulator;
88 }
89 
90 static struct vrefbuf_regul *regulator_to_vr(struct regulator *regulator)
91 {
92 	return container_of(regulator, struct vrefbuf_regul, regulator);
93 }
94 
95 static TEE_Result vrefbuf_wait_ready(struct vrefbuf_regul *vr)
96 {
97 	uint32_t val = 0;
98 
99 	if (IO_READ32_POLL_TIMEOUT(vr->base + VREFBUF_CSR, val,
100 				   val & VREFBUF_CSR_VRR, 0, TIMEOUT_US_10MS))
101 		return TEE_ERROR_GENERIC;
102 
103 	return TEE_SUCCESS;
104 }
105 
106 static TEE_Result vrefbuf_set_state(struct regulator *regulator, bool enable)
107 {
108 	struct vrefbuf_regul *vr = regulator_to_vr(regulator);
109 	TEE_Result res = TEE_ERROR_GENERIC;
110 
111 	res = clk_enable(vr->clock);
112 	if (res)
113 		return res;
114 
115 	if (enable) {
116 		io_clrbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_HIZ);
117 
118 		/*
119 		 * If first enable after boot or if it was disabled since
120 		 * less than 1ms, then wait for 1ms in pull down mode to
121 		 * avoid an overshoot.
122 		 */
123 		if (!vr->disable_timeout ||
124 		    !timeout_elapsed(vr->disable_timeout))
125 			udelay(1000);
126 
127 		io_setbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_ENVR);
128 
129 		if (vrefbuf_wait_ready(vr) != TEE_SUCCESS) {
130 			clk_disable(vr->clock);
131 
132 			return TEE_ERROR_GENERIC;
133 		}
134 	} else {
135 		io_clrbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_ENVR);
136 
137 		vr->disable_timeout = timeout_init_us(TIMEOUT_US_1MS);
138 	}
139 
140 	clk_disable(vr->clock);
141 
142 	return TEE_SUCCESS;
143 }
144 
145 static TEE_Result vrefbuf_get_state(struct regulator *regulator, bool *enabled)
146 {
147 	struct vrefbuf_regul *vr = regulator_to_vr(regulator);
148 	TEE_Result res = TEE_ERROR_GENERIC;
149 
150 	res = clk_enable(vr->clock);
151 	if (res)
152 		return res;
153 
154 	*enabled = io_read32(vr->base + VREFBUF_CSR) & VREFBUF_CSR_VRR;
155 
156 	clk_disable(vr->clock);
157 
158 	return TEE_SUCCESS;
159 }
160 
161 static TEE_Result vrefbuf_get_voltage(struct regulator *regulator,
162 				      int *level_uv)
163 {
164 	struct vrefbuf_regul *vr = regulator_to_vr(regulator);
165 	TEE_Result res = TEE_ERROR_GENERIC;
166 	uint32_t index = 0;
167 
168 	res = clk_enable(vr->clock);
169 	if (res)
170 		return res;
171 
172 	index = io_read32(vr->base + VREFBUF_CSR) & VREFBUF_CSR_VRS;
173 	index = INV_VRS(index) >> VREFBUF_CSR_VRS_SHIFT;
174 
175 	clk_disable(vr->clock);
176 
177 	*level_uv = vr->compat->voltages[index];
178 
179 	return TEE_SUCCESS;
180 }
181 
182 static TEE_Result vrefbuf_set_voltage(struct regulator *regulator, int level_uv)
183 {
184 	struct vrefbuf_regul *vr = regulator_to_vr(regulator);
185 	TEE_Result res = TEE_ERROR_GENERIC;
186 	size_t i = 0;
187 
188 	for (i = 0 ; i < ARRAY_SIZE(vr->compat->voltages) ; i++) {
189 		if (vr->compat->voltages[i] == level_uv) {
190 			uint32_t val = INV_VRS(i << VREFBUF_CSR_VRS_SHIFT);
191 
192 			res = clk_enable(vr->clock);
193 			if (res)
194 				return res;
195 
196 			io_clrsetbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_VRS,
197 					val);
198 
199 			clk_disable(vr->clock);
200 
201 			return TEE_SUCCESS;
202 		}
203 	}
204 
205 	EMSG("Failed to set voltage on vrefbuf");
206 
207 	return TEE_ERROR_BAD_PARAMETERS;
208 }
209 
210 static TEE_Result vrefbuf_list_voltages(struct regulator *regulator __unused,
211 					struct regulator_voltages_desc **desc,
212 					const int **levels)
213 {
214 	struct vrefbuf_regul *vr = regulator_to_vr(regulator);
215 	const int *levels_ref = vr->compat->voltages;
216 
217 	if (!vr->voltages_desc.type) {
218 		size_t num_levels = ARRAY_SIZE(vr->compat->voltages);
219 		unsigned int index_high = num_levels - 1;
220 		unsigned int index_low = 0;
221 		unsigned int count = 0;
222 		unsigned int n = 0;
223 
224 		for (n = 0; n <= index_high; n++)
225 			if (vr->compat->voltages[n] >= regulator->min_uv)
226 				break;
227 		if (n > index_high)
228 			return TEE_ERROR_GENERIC;
229 		index_low = n;
230 
231 		for (n = index_high; n >= index_low; n--)
232 			if (vr->compat->voltages[n] <= regulator->max_uv)
233 				break;
234 		if (n < index_low)
235 			return TEE_ERROR_GENERIC;
236 		index_high = n;
237 
238 		count = index_high - index_low + 1;
239 
240 		vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST;
241 		vr->voltages_desc.num_levels = count;
242 		vr->voltages_start_index = index_low;
243 	}
244 
245 	*desc = &vr->voltages_desc;
246 	*levels = levels_ref + vr->voltages_start_index;
247 
248 	return TEE_SUCCESS;
249 }
250 
251 static TEE_Result stm32_vrefbuf_pm(enum pm_op op, unsigned int pm_hint __unused,
252 				   const struct pm_callback_handle *hdl)
253 {
254 	struct regulator *regulator = hdl->handle;
255 	struct vrefbuf_regul *vr = regulator_to_vr(regulator);
256 	vaddr_t csr_va = vr->base + VREFBUF_CSR;
257 	TEE_Result res = TEE_ERROR_GENERIC;
258 	/* Context to save/restore on PM suspend/resume */
259 	static uint32_t pm_val;
260 
261 	assert(op == PM_OP_SUSPEND || op == PM_OP_RESUME);
262 
263 	res = clk_enable(vr->clock);
264 	if (res)
265 		return res;
266 
267 	if (op == PM_OP_SUSPEND) {
268 		pm_val = io_read32(csr_va);
269 
270 		if (pm_val & VREFBUF_CSR_ENVR && vrefbuf_wait_ready(vr)) {
271 			clk_disable(vr->clock);
272 
273 			return TEE_ERROR_GENERIC;
274 		}
275 	} else {
276 		io_clrsetbits32(csr_va, VREFBUF_CSR_VRS, pm_val);
277 
278 		if (pm_val & VREFBUF_CSR_ENVR) {
279 			vr->disable_timeout = 0;
280 			vrefbuf_set_state(&vr->regulator, true);
281 		}
282 	}
283 
284 	clk_disable(vr->clock);
285 
286 	return TEE_SUCCESS;
287 }
288 DECLARE_KEEP_PAGER(stm32_vrefbuf_pm);
289 
290 static TEE_Result stm32_vrefbuf_init(struct regulator *regulator,
291 				     const void *fdt __unused,
292 				     int node __unused)
293 {
294 	register_pm_driver_cb(stm32_vrefbuf_pm, regulator, "stm32-vrefbuf");
295 
296 	return TEE_SUCCESS;
297 }
298 
299 static const struct regulator_ops vrefbuf_ops = {
300 	.set_state = vrefbuf_set_state,
301 	.get_state = vrefbuf_get_state,
302 	.set_voltage = vrefbuf_set_voltage,
303 	.get_voltage = vrefbuf_get_voltage,
304 	.supported_voltages = vrefbuf_list_voltages,
305 	.supplied_init = stm32_vrefbuf_init,
306 };
307 
308 static TEE_Result stm32_vrefbuf_regulator_probe(const void *fdt, int node,
309 						const void *compat_data)
310 {
311 	TEE_Result res = TEE_ERROR_GENERIC;
312 	struct vrefbuf_regul *vr = NULL;
313 	struct regu_dt_desc desc = { };
314 	char *regu_name = NULL;
315 	struct clk *clk = NULL;
316 	paddr_t reg_base = 0;
317 	size_t reg_size = 0;
318 
319 	assert(!stm32_vrefbuf);
320 
321 	res = clk_dt_get_by_index(fdt, node, 0, &clk);
322 	if (res)
323 		return res;
324 
325 	vr = calloc(1, sizeof(*vr));
326 	if (!vr)
327 		panic();
328 
329 	vr->compat = compat_data;
330 
331 	regu_name = strdup(fdt_get_name(fdt, node, NULL));
332 	if (!regu_name)
333 		panic();
334 
335 	reg_base = fdt_reg_base_address(fdt, node);
336 	reg_size = fdt_reg_size(fdt, node);
337 	if (reg_base == DT_INFO_INVALID_REG ||
338 	    reg_size == DT_INFO_INVALID_REG_SIZE)
339 		panic();
340 
341 	vr->base = (vaddr_t)phys_to_virt(reg_base, MEM_AREA_IO_SEC, reg_size);
342 	if (!vr->base)
343 		panic();
344 
345 	vr->clock = clk;
346 
347 	desc = (struct regu_dt_desc){
348 		.name = regu_name,
349 		.ops = &vrefbuf_ops,
350 		.supply_name = "vdda",
351 		.regulator = &vr->regulator,
352 	};
353 
354 	res = regulator_dt_register(fdt, node, node, &desc);
355 	if (res)
356 		panic();
357 
358 	stm32_vrefbuf = vr;
359 
360 	return TEE_SUCCESS;
361 }
362 
363 static const struct dt_device_match stm32_vrefbuf_match_table[] = {
364 	{
365 		.compatible = "st,stm32-vrefbuf",
366 		.compat_data = &stm32mp15_vrefbuf_compat,
367 	},
368 	{
369 		.compatible = "st,stm32mp13-vrefbuf",
370 		.compat_data = &stm32mp13_vrefbuf_compat
371 	},
372 	{ }
373 };
374 
375 DEFINE_DT_DRIVER(stm32_vrefbuf_regulator_dt_driver) = {
376 	.name = "stm32-vrefbuf-regulator",
377 	.match_table = stm32_vrefbuf_match_table,
378 	.probe = &stm32_vrefbuf_regulator_probe,
379 };
380