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