xref: /optee_os/core/drivers/stm32_hpdma.c (revision 0cf1cd13ceb6257e1c66eeb0633a7f209a3343af)
1*0cf1cd13SGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause
2*0cf1cd13SGatien Chevallier /*
3*0cf1cd13SGatien Chevallier  * Copyright (c) 2022-2024, STMicroelectronics
4*0cf1cd13SGatien Chevallier  */
5*0cf1cd13SGatien Chevallier 
6*0cf1cd13SGatien Chevallier #include <arm.h>
7*0cf1cd13SGatien Chevallier #include <config.h>
8*0cf1cd13SGatien Chevallier #include <drivers/clk.h>
9*0cf1cd13SGatien Chevallier #include <drivers/clk_dt.h>
10*0cf1cd13SGatien Chevallier #include <drivers/stm32_gpio.h>
11*0cf1cd13SGatien Chevallier #include <drivers/stm32_rif.h>
12*0cf1cd13SGatien Chevallier #include <io.h>
13*0cf1cd13SGatien Chevallier #include <kernel/boot.h>
14*0cf1cd13SGatien Chevallier #include <kernel/delay.h>
15*0cf1cd13SGatien Chevallier #include <kernel/dt.h>
16*0cf1cd13SGatien Chevallier #include <kernel/dt_driver.h>
17*0cf1cd13SGatien Chevallier #include <kernel/panic.h>
18*0cf1cd13SGatien Chevallier #include <kernel/pm.h>
19*0cf1cd13SGatien Chevallier #include <libfdt.h>
20*0cf1cd13SGatien Chevallier #include <mm/core_memprot.h>
21*0cf1cd13SGatien Chevallier #include <stdbool.h>
22*0cf1cd13SGatien Chevallier #include <stdlib.h>
23*0cf1cd13SGatien Chevallier #include <stm32_util.h>
24*0cf1cd13SGatien Chevallier #include <trace.h>
25*0cf1cd13SGatien Chevallier 
26*0cf1cd13SGatien Chevallier #define _HPDMA_SECCFGR			U(0x000)
27*0cf1cd13SGatien Chevallier #define _HPDMA_PRIVCFGR			U(0x004)
28*0cf1cd13SGatien Chevallier #define _HPDMA_RCFGLOCKR		U(0x008)
29*0cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR(x)		(U(0x054) + U(0x080) * (x))
30*0cf1cd13SGatien Chevallier #define _HPDMA_SEMCR(x)			(U(0x058) + U(0x080) * (x))
31*0cf1cd13SGatien Chevallier 
32*0cf1cd13SGatien Chevallier /*
33*0cf1cd13SGatien Chevallier  * CFGR register bitfields
34*0cf1cd13SGatien Chevallier  */
35*0cf1cd13SGatien Chevallier #define _HPDMA_CFGR_ENABLE		BIT(31)
36*0cf1cd13SGatien Chevallier 
37*0cf1cd13SGatien Chevallier /*
38*0cf1cd13SGatien Chevallier  * CIDCFGR register bitfields
39*0cf1cd13SGatien Chevallier  */
40*0cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR_SEMWL_MASK	GENMASK_32(23, 16)
41*0cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR_SCID_MASK	GENMASK_32(5, 4)
42*0cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR_CONF_MASK	(_CIDCFGR_CFEN |	 \
43*0cf1cd13SGatien Chevallier 					 _CIDCFGR_SEMEN |	 \
44*0cf1cd13SGatien Chevallier 					 _HPDMA_CIDCFGR_SCID_MASK |\
45*0cf1cd13SGatien Chevallier 					 _HPDMA_CIDCFGR_SEMWL_MASK)
46*0cf1cd13SGatien Chevallier 
47*0cf1cd13SGatien Chevallier /*
48*0cf1cd13SGatien Chevallier  * PRIVCFGR register bitfields
49*0cf1cd13SGatien Chevallier  */
50*0cf1cd13SGatien Chevallier #define _HPDMA_PRIVCFGR_MASK		GENMASK_32(15, 0)
51*0cf1cd13SGatien Chevallier 
52*0cf1cd13SGatien Chevallier /*
53*0cf1cd13SGatien Chevallier  * RCFGLOCKR register bitfields
54*0cf1cd13SGatien Chevallier  */
55*0cf1cd13SGatien Chevallier #define _HPDMA_RCFGLOCKR_MASK		GENMASK_32(15, 0)
56*0cf1cd13SGatien Chevallier 
57*0cf1cd13SGatien Chevallier /*
58*0cf1cd13SGatien Chevallier  * SECCFGR register bitfields
59*0cf1cd13SGatien Chevallier  */
60*0cf1cd13SGatien Chevallier #define _HPDMA_SECCFGR_EN		BIT(0)
61*0cf1cd13SGatien Chevallier #define _HPDMA_SECCFGR_MASK		GENMASK_32(15, 0)
62*0cf1cd13SGatien Chevallier 
63*0cf1cd13SGatien Chevallier /*
64*0cf1cd13SGatien Chevallier  * SEMCR register bitfields
65*0cf1cd13SGatien Chevallier  */
66*0cf1cd13SGatien Chevallier #define _HPDMA_SEMCR_SCID_MASK		GENMASK_32(5, 4)
67*0cf1cd13SGatien Chevallier #define _HPDMA_SEMCR_SCID_SHIFT		U(4)
68*0cf1cd13SGatien Chevallier 
69*0cf1cd13SGatien Chevallier /*
70*0cf1cd13SGatien Chevallier  * Miscellaneous
71*0cf1cd13SGatien Chevallier  */
72*0cf1cd13SGatien Chevallier 
73*0cf1cd13SGatien Chevallier #define HPDMA_RIF_CHANNELS		U(16)
74*0cf1cd13SGatien Chevallier 
75*0cf1cd13SGatien Chevallier #define HPDMA_NB_MAX_CID_SUPPORTED	U(3)
76*0cf1cd13SGatien Chevallier 
77*0cf1cd13SGatien Chevallier struct hpdma_pdata {
78*0cf1cd13SGatien Chevallier 	struct clk *hpdma_clock;
79*0cf1cd13SGatien Chevallier 	struct rif_conf_data conf_data;
80*0cf1cd13SGatien Chevallier 	unsigned int nb_channels;
81*0cf1cd13SGatien Chevallier 	vaddr_t base;
82*0cf1cd13SGatien Chevallier 
83*0cf1cd13SGatien Chevallier 	SLIST_ENTRY(hpdma_pdata) link;
84*0cf1cd13SGatien Chevallier };
85*0cf1cd13SGatien Chevallier 
86*0cf1cd13SGatien Chevallier static SLIST_HEAD(, hpdma_pdata) hpdma_list =
87*0cf1cd13SGatien Chevallier 		SLIST_HEAD_INITIALIZER(hpdma_list);
88*0cf1cd13SGatien Chevallier 
89*0cf1cd13SGatien Chevallier /* This function expects HPDMA bus clock is enabled */
90*0cf1cd13SGatien Chevallier static TEE_Result apply_rif_config(struct hpdma_pdata *hpdma_d, bool is_tdcid)
91*0cf1cd13SGatien Chevallier {
92*0cf1cd13SGatien Chevallier 	TEE_Result res = TEE_ERROR_ACCESS_DENIED;
93*0cf1cd13SGatien Chevallier 	uint32_t cidcfgr = 0;
94*0cf1cd13SGatien Chevallier 	unsigned int i = 0;
95*0cf1cd13SGatien Chevallier 
96*0cf1cd13SGatien Chevallier 	for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
97*0cf1cd13SGatien Chevallier 		if (!(BIT(i) & hpdma_d->conf_data.access_mask[0]))
98*0cf1cd13SGatien Chevallier 			continue;
99*0cf1cd13SGatien Chevallier 		/*
100*0cf1cd13SGatien Chevallier 		 * When TDCID, OP-TEE should be the one to set the CID filtering
101*0cf1cd13SGatien Chevallier 		 * configuration. Clearing previous configuration prevents
102*0cf1cd13SGatien Chevallier 		 * undesired events during the only legitimate configuration.
103*0cf1cd13SGatien Chevallier 		 */
104*0cf1cd13SGatien Chevallier 		if (is_tdcid)
105*0cf1cd13SGatien Chevallier 			io_clrbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
106*0cf1cd13SGatien Chevallier 				     _HPDMA_CIDCFGR_CONF_MASK);
107*0cf1cd13SGatien Chevallier 
108*0cf1cd13SGatien Chevallier 		cidcfgr = io_read32(hpdma_d->base + _HPDMA_CIDCFGR(i));
109*0cf1cd13SGatien Chevallier 
110*0cf1cd13SGatien Chevallier 		/* Check if the channel is in semaphore mode */
111*0cf1cd13SGatien Chevallier 		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
112*0cf1cd13SGatien Chevallier 			continue;
113*0cf1cd13SGatien Chevallier 
114*0cf1cd13SGatien Chevallier 		/* If not TDCID, we want to acquire semaphores assigned to us */
115*0cf1cd13SGatien Chevallier 		res = stm32_rif_acquire_semaphore(hpdma_d->base +
116*0cf1cd13SGatien Chevallier 						  _HPDMA_SEMCR(i),
117*0cf1cd13SGatien Chevallier 						  HPDMA_NB_MAX_CID_SUPPORTED);
118*0cf1cd13SGatien Chevallier 		if (res) {
119*0cf1cd13SGatien Chevallier 			EMSG("Couldn't acquire semaphore for channel %u", i);
120*0cf1cd13SGatien Chevallier 			return res;
121*0cf1cd13SGatien Chevallier 		}
122*0cf1cd13SGatien Chevallier 	}
123*0cf1cd13SGatien Chevallier 
124*0cf1cd13SGatien Chevallier 	/* Security and privilege RIF configuration */
125*0cf1cd13SGatien Chevallier 	io_clrsetbits32(hpdma_d->base + _HPDMA_PRIVCFGR, _HPDMA_PRIVCFGR_MASK &
126*0cf1cd13SGatien Chevallier 			hpdma_d->conf_data.access_mask[0],
127*0cf1cd13SGatien Chevallier 			hpdma_d->conf_data.priv_conf[0]);
128*0cf1cd13SGatien Chevallier 	io_clrsetbits32(hpdma_d->base + _HPDMA_SECCFGR, _HPDMA_SECCFGR_MASK &
129*0cf1cd13SGatien Chevallier 			hpdma_d->conf_data.access_mask[0],
130*0cf1cd13SGatien Chevallier 			hpdma_d->conf_data.sec_conf[0]);
131*0cf1cd13SGatien Chevallier 
132*0cf1cd13SGatien Chevallier 	/* Skip CID/semaphore configuration if not in TDCID state. */
133*0cf1cd13SGatien Chevallier 	if (!is_tdcid)
134*0cf1cd13SGatien Chevallier 		goto end;
135*0cf1cd13SGatien Chevallier 
136*0cf1cd13SGatien Chevallier 	for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
137*0cf1cd13SGatien Chevallier 		if (!(BIT(i) & hpdma_d->conf_data.access_mask[0]))
138*0cf1cd13SGatien Chevallier 			continue;
139*0cf1cd13SGatien Chevallier 
140*0cf1cd13SGatien Chevallier 		io_clrsetbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
141*0cf1cd13SGatien Chevallier 				_HPDMA_CIDCFGR_CONF_MASK,
142*0cf1cd13SGatien Chevallier 				hpdma_d->conf_data.cid_confs[i]);
143*0cf1cd13SGatien Chevallier 
144*0cf1cd13SGatien Chevallier 		cidcfgr = io_read32(hpdma_d->base + _HPDMA_CIDCFGR(i));
145*0cf1cd13SGatien Chevallier 
146*0cf1cd13SGatien Chevallier 		/*
147*0cf1cd13SGatien Chevallier 		 * Take semaphore if the resource is in semaphore
148*0cf1cd13SGatien Chevallier 		 * mode and secured.
149*0cf1cd13SGatien Chevallier 		 */
150*0cf1cd13SGatien Chevallier 		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1) ||
151*0cf1cd13SGatien Chevallier 		    !(io_read32(hpdma_d->base + _HPDMA_SECCFGR) & BIT(i))) {
152*0cf1cd13SGatien Chevallier 			res =
153*0cf1cd13SGatien Chevallier 			stm32_rif_release_semaphore(hpdma_d->base +
154*0cf1cd13SGatien Chevallier 						    _HPDMA_SEMCR(i),
155*0cf1cd13SGatien Chevallier 						    HPDMA_NB_MAX_CID_SUPPORTED);
156*0cf1cd13SGatien Chevallier 			if (res) {
157*0cf1cd13SGatien Chevallier 				EMSG("Couldn't release semaphore for res%u", i);
158*0cf1cd13SGatien Chevallier 				return TEE_ERROR_ACCESS_DENIED;
159*0cf1cd13SGatien Chevallier 			}
160*0cf1cd13SGatien Chevallier 		} else {
161*0cf1cd13SGatien Chevallier 			res =
162*0cf1cd13SGatien Chevallier 			stm32_rif_acquire_semaphore(hpdma_d->base +
163*0cf1cd13SGatien Chevallier 						    _HPDMA_SEMCR(i),
164*0cf1cd13SGatien Chevallier 						    HPDMA_NB_MAX_CID_SUPPORTED);
165*0cf1cd13SGatien Chevallier 			if (res) {
166*0cf1cd13SGatien Chevallier 				EMSG("Couldn't acquire semaphore for res%u", i);
167*0cf1cd13SGatien Chevallier 				return TEE_ERROR_ACCESS_DENIED;
168*0cf1cd13SGatien Chevallier 			}
169*0cf1cd13SGatien Chevallier 		}
170*0cf1cd13SGatien Chevallier 	}
171*0cf1cd13SGatien Chevallier 
172*0cf1cd13SGatien Chevallier 	/*
173*0cf1cd13SGatien Chevallier 	 * Lock RIF configuration if configured. This cannot be undone until
174*0cf1cd13SGatien Chevallier 	 * next reset.
175*0cf1cd13SGatien Chevallier 	 */
176*0cf1cd13SGatien Chevallier 	io_clrsetbits32(hpdma_d->base + _HPDMA_RCFGLOCKR, _HPDMA_RCFGLOCKR_MASK,
177*0cf1cd13SGatien Chevallier 			hpdma_d->conf_data.lock_conf[0]);
178*0cf1cd13SGatien Chevallier 
179*0cf1cd13SGatien Chevallier end:
180*0cf1cd13SGatien Chevallier 	if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
181*0cf1cd13SGatien Chevallier 		/* Check that RIF config are applied, panic otherwise */
182*0cf1cd13SGatien Chevallier 		if ((io_read32(hpdma_d->base + _HPDMA_PRIVCFGR) &
183*0cf1cd13SGatien Chevallier 		     hpdma_d->conf_data.access_mask[0]) !=
184*0cf1cd13SGatien Chevallier 		    hpdma_d->conf_data.priv_conf[0])
185*0cf1cd13SGatien Chevallier 			panic("HPDMA channel priv conf is incorrect");
186*0cf1cd13SGatien Chevallier 
187*0cf1cd13SGatien Chevallier 		if ((io_read32(hpdma_d->base + _HPDMA_SECCFGR) &
188*0cf1cd13SGatien Chevallier 		     hpdma_d->conf_data.access_mask[0]) !=
189*0cf1cd13SGatien Chevallier 		    hpdma_d->conf_data.sec_conf[0])
190*0cf1cd13SGatien Chevallier 			panic("HPDMA channel sec conf is incorrect");
191*0cf1cd13SGatien Chevallier 	}
192*0cf1cd13SGatien Chevallier 
193*0cf1cd13SGatien Chevallier 	return TEE_SUCCESS;
194*0cf1cd13SGatien Chevallier }
195*0cf1cd13SGatien Chevallier 
196*0cf1cd13SGatien Chevallier static TEE_Result parse_dt(const void *fdt, int node,
197*0cf1cd13SGatien Chevallier 			   struct hpdma_pdata *hpdma_d)
198*0cf1cd13SGatien Chevallier {
199*0cf1cd13SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
200*0cf1cd13SGatien Chevallier 	unsigned int i = 0;
201*0cf1cd13SGatien Chevallier 	int lenp = 0;
202*0cf1cd13SGatien Chevallier 	const fdt32_t *cuint = NULL;
203*0cf1cd13SGatien Chevallier 	struct dt_node_info info = { };
204*0cf1cd13SGatien Chevallier 	struct io_pa_va addr = { };
205*0cf1cd13SGatien Chevallier 
206*0cf1cd13SGatien Chevallier 	fdt_fill_device_info(fdt, &info, node);
207*0cf1cd13SGatien Chevallier 	assert(info.reg != DT_INFO_INVALID_REG &&
208*0cf1cd13SGatien Chevallier 	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
209*0cf1cd13SGatien Chevallier 
210*0cf1cd13SGatien Chevallier 	addr.pa = info.reg;
211*0cf1cd13SGatien Chevallier 	hpdma_d->base = io_pa_or_va_secure(&addr, info.reg_size);
212*0cf1cd13SGatien Chevallier 
213*0cf1cd13SGatien Chevallier 	/* Gate the IP */
214*0cf1cd13SGatien Chevallier 	res = clk_dt_get_by_index(fdt, node, 0, &hpdma_d->hpdma_clock);
215*0cf1cd13SGatien Chevallier 	if (res)
216*0cf1cd13SGatien Chevallier 		return res;
217*0cf1cd13SGatien Chevallier 
218*0cf1cd13SGatien Chevallier 	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
219*0cf1cd13SGatien Chevallier 	if (!cuint)
220*0cf1cd13SGatien Chevallier 		panic("No RIF configuration available");
221*0cf1cd13SGatien Chevallier 
222*0cf1cd13SGatien Chevallier 	hpdma_d->nb_channels = (unsigned int)(lenp / sizeof(uint32_t));
223*0cf1cd13SGatien Chevallier 	assert(hpdma_d->nb_channels <= HPDMA_RIF_CHANNELS);
224*0cf1cd13SGatien Chevallier 
225*0cf1cd13SGatien Chevallier 	hpdma_d->conf_data.cid_confs = calloc(HPDMA_RIF_CHANNELS,
226*0cf1cd13SGatien Chevallier 					      sizeof(uint32_t));
227*0cf1cd13SGatien Chevallier 	hpdma_d->conf_data.sec_conf = calloc(1, sizeof(uint32_t));
228*0cf1cd13SGatien Chevallier 	hpdma_d->conf_data.priv_conf = calloc(1, sizeof(uint32_t));
229*0cf1cd13SGatien Chevallier 	hpdma_d->conf_data.access_mask = calloc(1, sizeof(uint32_t));
230*0cf1cd13SGatien Chevallier 	hpdma_d->conf_data.lock_conf = calloc(1, sizeof(uint32_t));
231*0cf1cd13SGatien Chevallier 	assert(hpdma_d->conf_data.cid_confs && hpdma_d->conf_data.sec_conf &&
232*0cf1cd13SGatien Chevallier 	       hpdma_d->conf_data.priv_conf && hpdma_d->conf_data.access_mask &&
233*0cf1cd13SGatien Chevallier 	       hpdma_d->conf_data.lock_conf);
234*0cf1cd13SGatien Chevallier 
235*0cf1cd13SGatien Chevallier 	for (i = 0; i < hpdma_d->nb_channels; i++)
236*0cf1cd13SGatien Chevallier 		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), &hpdma_d->conf_data,
237*0cf1cd13SGatien Chevallier 				    HPDMA_NB_MAX_CID_SUPPORTED,
238*0cf1cd13SGatien Chevallier 				    HPDMA_RIF_CHANNELS);
239*0cf1cd13SGatien Chevallier 
240*0cf1cd13SGatien Chevallier 	return TEE_SUCCESS;
241*0cf1cd13SGatien Chevallier }
242*0cf1cd13SGatien Chevallier 
243*0cf1cd13SGatien Chevallier static void stm32_hpdma_pm_resume(struct hpdma_pdata *hpdma)
244*0cf1cd13SGatien Chevallier {
245*0cf1cd13SGatien Chevallier 	if (apply_rif_config(hpdma, true))
246*0cf1cd13SGatien Chevallier 		panic("Failed to resume HPDMA");
247*0cf1cd13SGatien Chevallier }
248*0cf1cd13SGatien Chevallier 
249*0cf1cd13SGatien Chevallier static void stm32_hpdma_pm_suspend(struct hpdma_pdata *hpdma)
250*0cf1cd13SGatien Chevallier {
251*0cf1cd13SGatien Chevallier 	size_t i = 0;
252*0cf1cd13SGatien Chevallier 
253*0cf1cd13SGatien Chevallier 	for (i = 0; i < HPDMA_RIF_CHANNELS; i++)
254*0cf1cd13SGatien Chevallier 		hpdma->conf_data.cid_confs[i] = io_read32(hpdma->base +
255*0cf1cd13SGatien Chevallier 							  _HPDMA_CIDCFGR(i)) &
256*0cf1cd13SGatien Chevallier 						_HPDMA_CIDCFGR_CONF_MASK;
257*0cf1cd13SGatien Chevallier 
258*0cf1cd13SGatien Chevallier 	hpdma->conf_data.priv_conf[0] = io_read32(hpdma->base +
259*0cf1cd13SGatien Chevallier 						  _HPDMA_PRIVCFGR) &
260*0cf1cd13SGatien Chevallier 					_HPDMA_PRIVCFGR_MASK;
261*0cf1cd13SGatien Chevallier 	hpdma->conf_data.sec_conf[0] = io_read32(hpdma->base +
262*0cf1cd13SGatien Chevallier 						 _HPDMA_SECCFGR) &
263*0cf1cd13SGatien Chevallier 				       _HPDMA_SECCFGR_MASK;
264*0cf1cd13SGatien Chevallier 	hpdma->conf_data.lock_conf[0] = io_read32(hpdma->base +
265*0cf1cd13SGatien Chevallier 						  _HPDMA_RCFGLOCKR) &
266*0cf1cd13SGatien Chevallier 					_HPDMA_RCFGLOCKR_MASK;
267*0cf1cd13SGatien Chevallier 
268*0cf1cd13SGatien Chevallier 	/*
269*0cf1cd13SGatien Chevallier 	 * The access mask is modified to restore the conf for all
270*0cf1cd13SGatien Chevallier 	 * resources.
271*0cf1cd13SGatien Chevallier 	 */
272*0cf1cd13SGatien Chevallier 	hpdma->conf_data.access_mask[0] = GENMASK_32(HPDMA_RIF_CHANNELS - 1, 0);
273*0cf1cd13SGatien Chevallier }
274*0cf1cd13SGatien Chevallier 
275*0cf1cd13SGatien Chevallier static TEE_Result
276*0cf1cd13SGatien Chevallier stm32_hpdma_pm(enum pm_op op, unsigned int pm_hint,
277*0cf1cd13SGatien Chevallier 	       const struct pm_callback_handle *pm_handle)
278*0cf1cd13SGatien Chevallier {
279*0cf1cd13SGatien Chevallier 	struct hpdma_pdata *hpdma = pm_handle->handle;
280*0cf1cd13SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
281*0cf1cd13SGatien Chevallier 	bool is_tdcid = false;
282*0cf1cd13SGatien Chevallier 
283*0cf1cd13SGatien Chevallier 	res = stm32_rifsc_check_tdcid(&is_tdcid);
284*0cf1cd13SGatien Chevallier 	if (res)
285*0cf1cd13SGatien Chevallier 		panic();
286*0cf1cd13SGatien Chevallier 
287*0cf1cd13SGatien Chevallier 	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !is_tdcid)
288*0cf1cd13SGatien Chevallier 		return TEE_SUCCESS;
289*0cf1cd13SGatien Chevallier 
290*0cf1cd13SGatien Chevallier 	res = clk_enable(hpdma->hpdma_clock);
291*0cf1cd13SGatien Chevallier 	if (res)
292*0cf1cd13SGatien Chevallier 		return res;
293*0cf1cd13SGatien Chevallier 
294*0cf1cd13SGatien Chevallier 	if (op == PM_OP_RESUME)
295*0cf1cd13SGatien Chevallier 		stm32_hpdma_pm_resume(hpdma);
296*0cf1cd13SGatien Chevallier 	else
297*0cf1cd13SGatien Chevallier 		stm32_hpdma_pm_suspend(hpdma);
298*0cf1cd13SGatien Chevallier 
299*0cf1cd13SGatien Chevallier 	clk_disable(hpdma->hpdma_clock);
300*0cf1cd13SGatien Chevallier 
301*0cf1cd13SGatien Chevallier 	return TEE_SUCCESS;
302*0cf1cd13SGatien Chevallier }
303*0cf1cd13SGatien Chevallier 
304*0cf1cd13SGatien Chevallier static TEE_Result stm32_hpdma_probe(const void *fdt, int node,
305*0cf1cd13SGatien Chevallier 				    const void *compat_data __unused)
306*0cf1cd13SGatien Chevallier {
307*0cf1cd13SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
308*0cf1cd13SGatien Chevallier 	struct hpdma_pdata *hpdma_d = NULL;
309*0cf1cd13SGatien Chevallier 	bool is_tdcid = false;
310*0cf1cd13SGatien Chevallier 
311*0cf1cd13SGatien Chevallier 	res = stm32_rifsc_check_tdcid(&is_tdcid);
312*0cf1cd13SGatien Chevallier 	if (res)
313*0cf1cd13SGatien Chevallier 		return res;
314*0cf1cd13SGatien Chevallier 
315*0cf1cd13SGatien Chevallier 	hpdma_d = calloc(1, sizeof(*hpdma_d));
316*0cf1cd13SGatien Chevallier 	if (!hpdma_d)
317*0cf1cd13SGatien Chevallier 		return TEE_ERROR_OUT_OF_MEMORY;
318*0cf1cd13SGatien Chevallier 
319*0cf1cd13SGatien Chevallier 	res = parse_dt(fdt, node, hpdma_d);
320*0cf1cd13SGatien Chevallier 	if (res) {
321*0cf1cd13SGatien Chevallier 		free(hpdma_d);
322*0cf1cd13SGatien Chevallier 		return res;
323*0cf1cd13SGatien Chevallier 	}
324*0cf1cd13SGatien Chevallier 
325*0cf1cd13SGatien Chevallier 	if (clk_enable(hpdma_d->hpdma_clock))
326*0cf1cd13SGatien Chevallier 		panic("Cannot access hpdma clock");
327*0cf1cd13SGatien Chevallier 
328*0cf1cd13SGatien Chevallier 	res = apply_rif_config(hpdma_d, is_tdcid);
329*0cf1cd13SGatien Chevallier 	if (res)
330*0cf1cd13SGatien Chevallier 		panic("Failed to apply RIF config");
331*0cf1cd13SGatien Chevallier 
332*0cf1cd13SGatien Chevallier 	clk_disable(hpdma_d->hpdma_clock);
333*0cf1cd13SGatien Chevallier 
334*0cf1cd13SGatien Chevallier 	SLIST_INSERT_HEAD(&hpdma_list, hpdma_d, link);
335*0cf1cd13SGatien Chevallier 
336*0cf1cd13SGatien Chevallier 	register_pm_core_service_cb(stm32_hpdma_pm, hpdma_d, "stm32-hpdma");
337*0cf1cd13SGatien Chevallier 
338*0cf1cd13SGatien Chevallier 	return TEE_SUCCESS;
339*0cf1cd13SGatien Chevallier }
340*0cf1cd13SGatien Chevallier 
341*0cf1cd13SGatien Chevallier static const struct dt_device_match stm32_hpdma_match_table[] = {
342*0cf1cd13SGatien Chevallier 	{ .compatible = "st,stm32-dma3" },
343*0cf1cd13SGatien Chevallier 	{ }
344*0cf1cd13SGatien Chevallier };
345*0cf1cd13SGatien Chevallier 
346*0cf1cd13SGatien Chevallier DEFINE_DT_DRIVER(stm32_hpdma_dt_driver) = {
347*0cf1cd13SGatien Chevallier 	.name = "st,stm32-hpdma",
348*0cf1cd13SGatien Chevallier 	.match_table = stm32_hpdma_match_table,
349*0cf1cd13SGatien Chevallier 	.probe = stm32_hpdma_probe,
350*0cf1cd13SGatien Chevallier };
351