xref: /optee_os/core/drivers/stm32_omm.c (revision 528e10da3fd4c2cfab6af22a87cd3ac7faf95f07)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2021-2025, STMicroelectronics
4  */
5 
6 #include <arm.h>
7 #include <config.h>
8 #include <drivers/clk.h>
9 #include <drivers/clk_dt.h>
10 #include <drivers/rstctrl.h>
11 #include <drivers/stm32_gpio.h>
12 #include <io.h>
13 #include <kernel/boot.h>
14 #include <kernel/delay.h>
15 #include <kernel/dt.h>
16 #include <kernel/dt_driver.h>
17 #include <kernel/panic.h>
18 #include <kernel/pm.h>
19 #include <libfdt.h>
20 #include <mm/core_memprot.h>
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <stm32_sysconf.h>
24 #include <stm32_util.h>
25 #include <trace.h>
26 
27 /*
28  * OCTOSPI registers
29  */
30 #define _OCTOSPI_CR			U(0x0)
31 
32 /*
33  * OCTOSPI CR register bitfields
34  */
35 #define _OCTOSPI_CR_EN			BIT(0)
36 
37 /*
38  * OCTOSPIM registers
39  */
40 #define _OCTOSPIM_CR			U(0x0)
41 
42 /*
43  * OCTOSPIM CR register bitfields
44  */
45 
46 #define _OCTOSPIM_CR_MUXEN		BIT(0)
47 #define _OCTOSPIM_CR_MUXEN_MODE_MASK	GENMASK_32(1, 0)
48 #define _OCTOSPIM_CR_CSSEL_OVR_EN	BIT(4)
49 #define _OCTOSPIM_CR_CSSEL_OVR_MASK	GENMASK_32(6, 4)
50 #define _OCTOSPIM_CR_CSSEL_OVR_SHIFT	U(5)
51 #define _OCTOSPIM_CR_REQ2ACK_MASK	GENMASK_32(23, 16)
52 #define _OCTOSPIM_CR_REQ2ACK_SHIFT	U(16)
53 
54 #define OSPI_NB				U(2)
55 #define OSPIM_NSEC_PER_SEC		UL(1000000000)
56 #define OSPI_NB_RESET			U(2)
57 #define OSPI_TIMEOUT_US_1MS		U(1000)
58 #define OSPI_RESET_DELAY		U(2)
59 
60 #define OMM_CS_OVERRIDE_DISABLE		U(0xff)
61 
62 struct stm32_mm_region {
63 	paddr_t start;
64 	paddr_t end;
65 };
66 
67 struct stm32_ospi_pdata {
68 	struct clk *clock;
69 	struct rstctrl *reset[OSPI_NB_RESET];
70 	struct stm32_mm_region region;
71 };
72 
73 struct stm32_omm_pdata {
74 	struct clk *clock;
75 	struct pinctrl_state *pinctrl_d;
76 	struct pinctrl_state *pinctrl_s;
77 	struct stm32_ospi_pdata ospi_d[OSPI_NB];
78 	struct stm32_mm_region region;
79 	vaddr_t base;
80 	uint32_t mux;
81 	uint32_t cssel_ovr;
82 	uint32_t req2ack;
83 };
84 
85 static struct stm32_omm_pdata *omm_d;
86 
stm32_omm_parse_fdt(const void * fdt,int node)87 static TEE_Result stm32_omm_parse_fdt(const void *fdt, int node)
88 {
89 	struct stm32_ospi_pdata *ospi_d = NULL;
90 	size_t size = DT_INFO_INVALID_REG_SIZE;
91 	TEE_Result res = TEE_ERROR_GENERIC;
92 	paddr_t base = DT_INFO_INVALID_REG;
93 	const fdt32_t *cuint = NULL;
94 	struct io_pa_va addr = { };
95 	uint8_t ospi_assigned = 0;
96 	unsigned int reset_i = 0;
97 	uint32_t ospi_i = 0;
98 	unsigned int i = 0;
99 	int ctrl_node = 0;
100 	int len = 0;
101 
102 	if (fdt_get_reg_props_by_name(fdt, node, "regs", &base, &size) < 0)
103 		panic();
104 
105 	addr.pa = base;
106 	omm_d->base = io_pa_or_va(&addr, size);
107 
108 	if (fdt_get_reg_props_by_name(fdt, node, "memory_map", &base, &size) <
109 	    0)
110 		panic();
111 
112 	omm_d->region.start = base;
113 	omm_d->region.end = base + size;
114 	if (size)
115 		omm_d->region.end--;
116 
117 	res = clk_dt_get_by_index(fdt, node, 0, &omm_d->clock);
118 	if (res)
119 		return res;
120 
121 	res = pinctrl_get_state_by_name(fdt, node, "default",
122 					&omm_d->pinctrl_d);
123 	if (res && res != TEE_ERROR_ITEM_NOT_FOUND)
124 		return res;
125 
126 	res = pinctrl_get_state_by_name(fdt, node, "sleep",
127 					&omm_d->pinctrl_s);
128 	if (res && res != TEE_ERROR_ITEM_NOT_FOUND)
129 		return res;
130 
131 	omm_d->mux = fdt_read_uint32_default(fdt, node, "st,omm-mux", 0);
132 	omm_d->req2ack = fdt_read_uint32_default(fdt, node,
133 						 "st,omm-req2ack-ns", 0);
134 	omm_d->cssel_ovr = fdt_read_uint32_default(fdt, node,
135 						   "st,omm-cssel-ovr",
136 						   OMM_CS_OVERRIDE_DISABLE);
137 
138 	cuint = fdt_getprop(fdt, node, "memory-region", &len);
139 	if (cuint) {
140 		const char *mm_name[OSPI_NB] = { "mm_ospi1", "mm_ospi2" };
141 		struct stm32_mm_region *region = NULL;
142 		uint32_t offset = 0;
143 		int pnode = 0;
144 		int index = 0;
145 
146 		for (i = 0; i < OSPI_NB; i++) {
147 			index = fdt_stringlist_search(fdt, node,
148 						      "memory-region-names",
149 						      mm_name[i]);
150 			if (index < 0)
151 				continue;
152 
153 			if (index >= (int)(len / sizeof(uint32_t)))
154 				panic();
155 
156 			offset = fdt32_to_cpu(*(cuint + index));
157 			pnode = fdt_node_offset_by_phandle(fdt, offset);
158 			if (pnode < 0)
159 				panic();
160 
161 			region = &omm_d->ospi_d[i].region;
162 			if (fdt_reg_info(fdt, pnode, &region->start, &size) < 0)
163 				panic();
164 
165 			region->end = region->start + size;
166 			if (size)
167 				region->end--;
168 		}
169 	}
170 
171 	fdt_for_each_subnode(ctrl_node, fdt, node)
172 		ospi_i++;
173 
174 	if (ospi_i != OSPI_NB)
175 		panic();
176 
177 	fdt_for_each_subnode(ctrl_node, fdt, node) {
178 		cuint = fdt_getprop(fdt, ctrl_node, "reg", NULL);
179 		if (!cuint)
180 			panic();
181 
182 		ospi_i = fdt32_to_cpu(*cuint);
183 		if (ospi_i >= OSPI_NB || (ospi_assigned & BIT(ospi_i)))
184 			panic();
185 
186 		ospi_d = &omm_d->ospi_d[ospi_i];
187 		ospi_assigned |= BIT(ospi_i);
188 
189 		res = clk_dt_get_by_index(fdt, ctrl_node, 0, &ospi_d->clock);
190 		if (res)
191 			return res;
192 
193 		for (reset_i = 0; reset_i < OSPI_NB_RESET; reset_i++) {
194 			res = rstctrl_dt_get_by_index(fdt, ctrl_node, reset_i,
195 						      &ospi_d->reset[reset_i]);
196 			if (res)
197 				return res;
198 		}
199 	}
200 
201 	return res;
202 }
203 
stm32_omm_region_contains(struct stm32_mm_region * r1,struct stm32_mm_region * r2)204 static bool stm32_omm_region_contains(struct stm32_mm_region *r1,
205 				      struct stm32_mm_region *r2)
206 {
207 	return r1->start <= r2->start && r1->end >= r2->end;
208 }
209 
stm32_omm_region_overlaps(struct stm32_mm_region * r1,struct stm32_mm_region * r2)210 static bool stm32_omm_region_overlaps(struct stm32_mm_region *r1,
211 				      struct stm32_mm_region *r2)
212 {
213 	return r1->start <= r2->end && r1->end >= r2->start;
214 }
215 
stm32_omm_set_mm(void)216 static void stm32_omm_set_mm(void)
217 {
218 	struct stm32_mm_region *region[OSPI_NB] = { };
219 	unsigned int valid_regions = 0;
220 	size_t mm_size[OSPI_NB] = { };
221 	unsigned int ospi_i = 0;
222 
223 	for (ospi_i = 0; ospi_i < OSPI_NB; ospi_i++) {
224 		region[ospi_i] = &omm_d->ospi_d[ospi_i].region;
225 
226 		if (region[ospi_i]->start >= region[ospi_i]->end)
227 			continue;
228 
229 		if (!stm32_omm_region_contains(&omm_d->region, region[ospi_i]))
230 			panic();
231 
232 		mm_size[ospi_i] = region[ospi_i]->end - region[ospi_i]->start
233 				  + 1;
234 		valid_regions++;
235 	}
236 
237 	if (valid_regions == OSPI_NB &&
238 	    stm32_omm_region_overlaps(region[0], region[1]))
239 		panic();
240 
241 	if (valid_regions)
242 		stm32mp25_syscfg_set_amcr(mm_size[0], mm_size[1]);
243 }
244 
stm32_omm_configure(void)245 static void stm32_omm_configure(void)
246 {
247 	struct stm32_ospi_pdata *ospi_d = NULL;
248 	unsigned long clk_rate_max = 0;
249 	unsigned int reset_i = 0;
250 	unsigned int ospi_i = 0;
251 	uint32_t cssel_ovr = 0;
252 	uint32_t req2ack = 0;
253 
254 	for (ospi_i = 0; ospi_i < OSPI_NB; ospi_i++) {
255 		ospi_d = &omm_d->ospi_d[ospi_i];
256 		clk_rate_max = MAX(clk_get_rate(ospi_d->clock), clk_rate_max);
257 
258 		if (clk_enable(ospi_d->clock))
259 			panic();
260 
261 		for (reset_i = 0; reset_i < OSPI_NB_RESET; reset_i++) {
262 			if (rstctrl_assert_to(ospi_d->reset[reset_i],
263 					      OSPI_TIMEOUT_US_1MS))
264 				panic();
265 		}
266 
267 		udelay(OSPI_RESET_DELAY);
268 
269 		for (reset_i = 0; reset_i < OSPI_NB_RESET; reset_i++) {
270 			if (rstctrl_deassert_to(ospi_d->reset[reset_i],
271 						OSPI_TIMEOUT_US_1MS))
272 				panic();
273 		}
274 
275 		clk_disable(ospi_d->clock);
276 	}
277 
278 	if (omm_d->mux & _OCTOSPIM_CR_MUXEN && omm_d->req2ack) {
279 		unsigned long hclkn = OSPIM_NSEC_PER_SEC / clk_rate_max;
280 		unsigned long timing = DIV_ROUND_UP(omm_d->req2ack, hclkn) - 1;
281 
282 		if (timing >
283 		    _OCTOSPIM_CR_REQ2ACK_MASK >> _OCTOSPIM_CR_REQ2ACK_SHIFT)
284 			req2ack = _OCTOSPIM_CR_REQ2ACK_MASK;
285 		else
286 			req2ack = timing << _OCTOSPIM_CR_REQ2ACK_SHIFT;
287 	}
288 
289 	if (omm_d->cssel_ovr != OMM_CS_OVERRIDE_DISABLE)
290 		cssel_ovr = (omm_d->cssel_ovr << _OCTOSPIM_CR_CSSEL_OVR_SHIFT) |
291 			    _OCTOSPIM_CR_CSSEL_OVR_EN;
292 
293 	if (clk_enable(omm_d->clock))
294 		panic();
295 
296 	io_clrsetbits32(omm_d->base + _OCTOSPIM_CR,
297 			_OCTOSPIM_CR_REQ2ACK_MASK |
298 			_OCTOSPIM_CR_CSSEL_OVR_MASK |
299 			_OCTOSPIM_CR_MUXEN_MODE_MASK,
300 			req2ack | cssel_ovr | omm_d->mux);
301 
302 	clk_disable(omm_d->clock);
303 
304 	if (omm_d->mux & _OCTOSPIM_CR_MUXEN) {
305 		/*
306 		 * If the mux is enabled, the 2 OSPI clocks have to be
307 		 * always enabled
308 		 */
309 		for (ospi_i = 0; ospi_i < OSPI_NB; ospi_i++) {
310 			ospi_d = &omm_d->ospi_d[ospi_i];
311 
312 			if (clk_enable(ospi_d->clock))
313 				panic();
314 		}
315 	}
316 }
317 
stm32_omm_setup(void)318 static void stm32_omm_setup(void)
319 {
320 	stm32_omm_set_mm();
321 	stm32_omm_configure();
322 	if (omm_d->pinctrl_d && pinctrl_apply_state(omm_d->pinctrl_d))
323 		panic();
324 }
325 
stm32_omm_suspend(void)326 static void stm32_omm_suspend(void)
327 {
328 	if (omm_d->pinctrl_s && pinctrl_apply_state(omm_d->pinctrl_s))
329 		panic();
330 }
331 
332 static TEE_Result
stm32_omm_pm(enum pm_op op,unsigned int pm_hint,const struct pm_callback_handle * pm_handle __unused)333 stm32_omm_pm(enum pm_op op, unsigned int pm_hint,
334 	     const struct pm_callback_handle *pm_handle __unused)
335 {
336 	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
337 		return TEE_SUCCESS;
338 
339 	if (op == PM_OP_RESUME)
340 		stm32_omm_setup();
341 	else
342 		stm32_omm_suspend();
343 
344 	return TEE_SUCCESS;
345 }
346 
stm32_omm_probe(const void * fdt,int node,const void * compat_data __unused)347 static TEE_Result stm32_omm_probe(const void *fdt, int node,
348 				  const void *compat_data __unused)
349 {
350 	TEE_Result res = TEE_ERROR_GENERIC;
351 
352 	omm_d = calloc(1, sizeof(*omm_d));
353 	if (!omm_d)
354 		return TEE_ERROR_OUT_OF_MEMORY;
355 
356 	res = stm32_omm_parse_fdt(fdt, node);
357 	if (res)
358 		goto err_free;
359 
360 	stm32_omm_setup();
361 
362 	register_pm_core_service_cb(stm32_omm_pm, NULL, "stm32-omm");
363 
364 	return TEE_SUCCESS;
365 
366 err_free:
367 	free(omm_d);
368 
369 	return res;
370 }
371 
372 static const struct dt_device_match stm32_omm_match_table[] = {
373 	{ .compatible = "st,stm32mp25-omm" },
374 	{ }
375 };
376 
377 DEFINE_DT_DRIVER(stm32_omm_dt_driver) = {
378 	.name = "stm32_omm",
379 	.match_table = stm32_omm_match_table,
380 	.probe = stm32_omm_probe,
381 };
382