xref: /optee_os/core/drivers/stm32_hpdma.c (revision 5c2c026a8b96184e24dc4f1e0b34ab7c0e572552)
10cf1cd13SGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause
20cf1cd13SGatien Chevallier /*
30cf1cd13SGatien Chevallier  * Copyright (c) 2022-2024, STMicroelectronics
40cf1cd13SGatien Chevallier  */
50cf1cd13SGatien Chevallier 
60cf1cd13SGatien Chevallier #include <arm.h>
70cf1cd13SGatien Chevallier #include <config.h>
80cf1cd13SGatien Chevallier #include <drivers/clk.h>
90cf1cd13SGatien Chevallier #include <drivers/clk_dt.h>
100cf1cd13SGatien Chevallier #include <drivers/stm32_gpio.h>
110cf1cd13SGatien Chevallier #include <drivers/stm32_rif.h>
120cf1cd13SGatien Chevallier #include <io.h>
130cf1cd13SGatien Chevallier #include <kernel/boot.h>
140cf1cd13SGatien Chevallier #include <kernel/delay.h>
150cf1cd13SGatien Chevallier #include <kernel/dt.h>
160cf1cd13SGatien Chevallier #include <kernel/dt_driver.h>
170cf1cd13SGatien Chevallier #include <kernel/panic.h>
180cf1cd13SGatien Chevallier #include <kernel/pm.h>
190cf1cd13SGatien Chevallier #include <libfdt.h>
200cf1cd13SGatien Chevallier #include <mm/core_memprot.h>
210cf1cd13SGatien Chevallier #include <stdbool.h>
220cf1cd13SGatien Chevallier #include <stdlib.h>
230cf1cd13SGatien Chevallier #include <stm32_util.h>
240cf1cd13SGatien Chevallier #include <trace.h>
250cf1cd13SGatien Chevallier 
260cf1cd13SGatien Chevallier #define _HPDMA_SECCFGR			U(0x000)
270cf1cd13SGatien Chevallier #define _HPDMA_PRIVCFGR			U(0x004)
280cf1cd13SGatien Chevallier #define _HPDMA_RCFGLOCKR		U(0x008)
290cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR(x)		(U(0x054) + U(0x080) * (x))
300cf1cd13SGatien Chevallier #define _HPDMA_SEMCR(x)			(U(0x058) + U(0x080) * (x))
310cf1cd13SGatien Chevallier 
320cf1cd13SGatien Chevallier /*
330cf1cd13SGatien Chevallier  * CFGR register bitfields
340cf1cd13SGatien Chevallier  */
350cf1cd13SGatien Chevallier #define _HPDMA_CFGR_ENABLE		BIT(31)
360cf1cd13SGatien Chevallier 
370cf1cd13SGatien Chevallier /*
380cf1cd13SGatien Chevallier  * CIDCFGR register bitfields
390cf1cd13SGatien Chevallier  */
400cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR_SEMWL_MASK	GENMASK_32(23, 16)
410cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR_SCID_MASK	GENMASK_32(5, 4)
420cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR_CONF_MASK	(_CIDCFGR_CFEN |	 \
430cf1cd13SGatien Chevallier 					 _CIDCFGR_SEMEN |	 \
440cf1cd13SGatien Chevallier 					 _HPDMA_CIDCFGR_SCID_MASK |\
450cf1cd13SGatien Chevallier 					 _HPDMA_CIDCFGR_SEMWL_MASK)
460cf1cd13SGatien Chevallier 
470cf1cd13SGatien Chevallier /*
480cf1cd13SGatien Chevallier  * PRIVCFGR register bitfields
490cf1cd13SGatien Chevallier  */
500cf1cd13SGatien Chevallier #define _HPDMA_PRIVCFGR_MASK		GENMASK_32(15, 0)
510cf1cd13SGatien Chevallier 
520cf1cd13SGatien Chevallier /*
530cf1cd13SGatien Chevallier  * RCFGLOCKR register bitfields
540cf1cd13SGatien Chevallier  */
550cf1cd13SGatien Chevallier #define _HPDMA_RCFGLOCKR_MASK		GENMASK_32(15, 0)
560cf1cd13SGatien Chevallier 
570cf1cd13SGatien Chevallier /*
580cf1cd13SGatien Chevallier  * SECCFGR register bitfields
590cf1cd13SGatien Chevallier  */
600cf1cd13SGatien Chevallier #define _HPDMA_SECCFGR_EN		BIT(0)
610cf1cd13SGatien Chevallier #define _HPDMA_SECCFGR_MASK		GENMASK_32(15, 0)
620cf1cd13SGatien Chevallier 
630cf1cd13SGatien Chevallier /*
640cf1cd13SGatien Chevallier  * SEMCR register bitfields
650cf1cd13SGatien Chevallier  */
660cf1cd13SGatien Chevallier #define _HPDMA_SEMCR_SCID_MASK		GENMASK_32(5, 4)
670cf1cd13SGatien Chevallier #define _HPDMA_SEMCR_SCID_SHIFT		U(4)
680cf1cd13SGatien Chevallier 
690cf1cd13SGatien Chevallier /*
700cf1cd13SGatien Chevallier  * Miscellaneous
710cf1cd13SGatien Chevallier  */
720cf1cd13SGatien Chevallier 
730cf1cd13SGatien Chevallier #define HPDMA_RIF_CHANNELS		U(16)
740cf1cd13SGatien Chevallier 
750cf1cd13SGatien Chevallier #define HPDMA_NB_MAX_CID_SUPPORTED	U(3)
760cf1cd13SGatien Chevallier 
770cf1cd13SGatien Chevallier struct hpdma_pdata {
780cf1cd13SGatien Chevallier 	struct clk *hpdma_clock;
79307d268bSGatien Chevallier 	struct rif_conf_data *conf_data;
800cf1cd13SGatien Chevallier 	unsigned int nb_channels;
810cf1cd13SGatien Chevallier 	vaddr_t base;
820cf1cd13SGatien Chevallier 
830cf1cd13SGatien Chevallier 	SLIST_ENTRY(hpdma_pdata) link;
840cf1cd13SGatien Chevallier };
850cf1cd13SGatien Chevallier 
860cf1cd13SGatien Chevallier static SLIST_HEAD(, hpdma_pdata) hpdma_list =
870cf1cd13SGatien Chevallier 		SLIST_HEAD_INITIALIZER(hpdma_list);
880cf1cd13SGatien Chevallier 
89*5c2c026aSGatien Chevallier static TEE_Result handle_available_semaphores(struct hpdma_pdata *hpdma_d)
90*5c2c026aSGatien Chevallier {
91*5c2c026aSGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
92*5c2c026aSGatien Chevallier 	uint32_t cidcfgr = 0;
93*5c2c026aSGatien Chevallier 	unsigned int i = 0;
94*5c2c026aSGatien Chevallier 
95*5c2c026aSGatien Chevallier 	for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
96*5c2c026aSGatien Chevallier 		if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
97*5c2c026aSGatien Chevallier 			continue;
98*5c2c026aSGatien Chevallier 
99*5c2c026aSGatien Chevallier 		cidcfgr = io_read32(hpdma_d->base + _HPDMA_CIDCFGR(i));
100*5c2c026aSGatien Chevallier 
101*5c2c026aSGatien Chevallier 		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
102*5c2c026aSGatien Chevallier 			continue;
103*5c2c026aSGatien Chevallier 
104*5c2c026aSGatien Chevallier 		if (!(io_read32(hpdma_d->base + _HPDMA_SECCFGR) & BIT(i))) {
105*5c2c026aSGatien Chevallier 			res =
106*5c2c026aSGatien Chevallier 			stm32_rif_release_semaphore(hpdma_d->base +
107*5c2c026aSGatien Chevallier 						    _HPDMA_SEMCR(i),
108*5c2c026aSGatien Chevallier 						    HPDMA_NB_MAX_CID_SUPPORTED);
109*5c2c026aSGatien Chevallier 			if (res) {
110*5c2c026aSGatien Chevallier 				EMSG("Cannot release semaphore for resource %u",
111*5c2c026aSGatien Chevallier 				     i);
112*5c2c026aSGatien Chevallier 				return res;
113*5c2c026aSGatien Chevallier 			}
114*5c2c026aSGatien Chevallier 		} else {
115*5c2c026aSGatien Chevallier 			res =
116*5c2c026aSGatien Chevallier 			stm32_rif_acquire_semaphore(hpdma_d->base +
117*5c2c026aSGatien Chevallier 						    _HPDMA_SEMCR(i),
118*5c2c026aSGatien Chevallier 						    HPDMA_NB_MAX_CID_SUPPORTED);
119*5c2c026aSGatien Chevallier 			if (res) {
120*5c2c026aSGatien Chevallier 				EMSG("Cannot acquire semaphore for resource %u",
121*5c2c026aSGatien Chevallier 				     i);
122*5c2c026aSGatien Chevallier 				return res;
123*5c2c026aSGatien Chevallier 			}
124*5c2c026aSGatien Chevallier 		}
125*5c2c026aSGatien Chevallier 	}
126*5c2c026aSGatien Chevallier 
127*5c2c026aSGatien Chevallier 	return TEE_SUCCESS;
128*5c2c026aSGatien Chevallier }
129*5c2c026aSGatien Chevallier 
1300cf1cd13SGatien Chevallier /* This function expects HPDMA bus clock is enabled */
1310cf1cd13SGatien Chevallier static TEE_Result apply_rif_config(struct hpdma_pdata *hpdma_d, bool is_tdcid)
1320cf1cd13SGatien Chevallier {
1330cf1cd13SGatien Chevallier 	TEE_Result res = TEE_ERROR_ACCESS_DENIED;
1340cf1cd13SGatien Chevallier 	unsigned int i = 0;
1350cf1cd13SGatien Chevallier 
136307d268bSGatien Chevallier 	if (!hpdma_d->conf_data)
137307d268bSGatien Chevallier 		return TEE_SUCCESS;
138307d268bSGatien Chevallier 
139*5c2c026aSGatien Chevallier 	if (is_tdcid) {
1400cf1cd13SGatien Chevallier 		for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
141307d268bSGatien Chevallier 			if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
1420cf1cd13SGatien Chevallier 				continue;
1430cf1cd13SGatien Chevallier 			/*
144*5c2c026aSGatien Chevallier 			 * When TDCID, OP-TEE should be the one to set the CID
145*5c2c026aSGatien Chevallier 			 * filtering configuration. Clearing previous
146*5c2c026aSGatien Chevallier 			 * configuration prevents undesired events during the
147*5c2c026aSGatien Chevallier 			 * only legitimate configuration.
1480cf1cd13SGatien Chevallier 			 */
1490cf1cd13SGatien Chevallier 			io_clrbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
1500cf1cd13SGatien Chevallier 				     _HPDMA_CIDCFGR_CONF_MASK);
1510cf1cd13SGatien Chevallier 		}
152*5c2c026aSGatien Chevallier 	} else {
153*5c2c026aSGatien Chevallier 		res = handle_available_semaphores(hpdma_d);
154*5c2c026aSGatien Chevallier 		if (res)
155*5c2c026aSGatien Chevallier 			panic();
1560cf1cd13SGatien Chevallier 	}
1570cf1cd13SGatien Chevallier 
1580cf1cd13SGatien Chevallier 	/* Security and privilege RIF configuration */
1590cf1cd13SGatien Chevallier 	io_clrsetbits32(hpdma_d->base + _HPDMA_PRIVCFGR, _HPDMA_PRIVCFGR_MASK &
160307d268bSGatien Chevallier 			hpdma_d->conf_data->access_mask[0],
161307d268bSGatien Chevallier 			hpdma_d->conf_data->priv_conf[0]);
1620cf1cd13SGatien Chevallier 	io_clrsetbits32(hpdma_d->base + _HPDMA_SECCFGR, _HPDMA_SECCFGR_MASK &
163307d268bSGatien Chevallier 			hpdma_d->conf_data->access_mask[0],
164307d268bSGatien Chevallier 			hpdma_d->conf_data->sec_conf[0]);
1650cf1cd13SGatien Chevallier 
1660cf1cd13SGatien Chevallier 	/* Skip CID/semaphore configuration if not in TDCID state. */
1670cf1cd13SGatien Chevallier 	if (!is_tdcid)
1680cf1cd13SGatien Chevallier 		goto end;
1690cf1cd13SGatien Chevallier 
1700cf1cd13SGatien Chevallier 	for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
171307d268bSGatien Chevallier 		if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
1720cf1cd13SGatien Chevallier 			continue;
1730cf1cd13SGatien Chevallier 
1740cf1cd13SGatien Chevallier 		io_clrsetbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
1750cf1cd13SGatien Chevallier 				_HPDMA_CIDCFGR_CONF_MASK,
176307d268bSGatien Chevallier 				hpdma_d->conf_data->cid_confs[i]);
1770cf1cd13SGatien Chevallier 	}
1780cf1cd13SGatien Chevallier 
1790cf1cd13SGatien Chevallier 	/*
1800cf1cd13SGatien Chevallier 	 * Lock RIF configuration if configured. This cannot be undone until
1810cf1cd13SGatien Chevallier 	 * next reset.
1820cf1cd13SGatien Chevallier 	 */
183*5c2c026aSGatien Chevallier 	io_setbits32(hpdma_d->base + _HPDMA_RCFGLOCKR,
184307d268bSGatien Chevallier 		     hpdma_d->conf_data->lock_conf[0]);
1850cf1cd13SGatien Chevallier 
186*5c2c026aSGatien Chevallier 	res = handle_available_semaphores(hpdma_d);
187*5c2c026aSGatien Chevallier 	if (res)
188*5c2c026aSGatien Chevallier 		panic();
189*5c2c026aSGatien Chevallier 
1900cf1cd13SGatien Chevallier end:
1910cf1cd13SGatien Chevallier 	if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
1920cf1cd13SGatien Chevallier 		/* Check that RIF config are applied, panic otherwise */
1930cf1cd13SGatien Chevallier 		if ((io_read32(hpdma_d->base + _HPDMA_PRIVCFGR) &
194307d268bSGatien Chevallier 		     hpdma_d->conf_data->access_mask[0]) !=
195307d268bSGatien Chevallier 		    hpdma_d->conf_data->priv_conf[0])
1960cf1cd13SGatien Chevallier 			panic("HPDMA channel priv conf is incorrect");
1970cf1cd13SGatien Chevallier 
1980cf1cd13SGatien Chevallier 		if ((io_read32(hpdma_d->base + _HPDMA_SECCFGR) &
199307d268bSGatien Chevallier 		     hpdma_d->conf_data->access_mask[0]) !=
200307d268bSGatien Chevallier 		    hpdma_d->conf_data->sec_conf[0])
2010cf1cd13SGatien Chevallier 			panic("HPDMA channel sec conf is incorrect");
2020cf1cd13SGatien Chevallier 	}
2030cf1cd13SGatien Chevallier 
2040cf1cd13SGatien Chevallier 	return TEE_SUCCESS;
2050cf1cd13SGatien Chevallier }
2060cf1cd13SGatien Chevallier 
2070cf1cd13SGatien Chevallier static TEE_Result parse_dt(const void *fdt, int node,
2080cf1cd13SGatien Chevallier 			   struct hpdma_pdata *hpdma_d)
2090cf1cd13SGatien Chevallier {
2100cf1cd13SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
2110cf1cd13SGatien Chevallier 	unsigned int i = 0;
2120cf1cd13SGatien Chevallier 	int lenp = 0;
2130cf1cd13SGatien Chevallier 	const fdt32_t *cuint = NULL;
2140cf1cd13SGatien Chevallier 	struct dt_node_info info = { };
2150cf1cd13SGatien Chevallier 	struct io_pa_va addr = { };
2160cf1cd13SGatien Chevallier 
2170cf1cd13SGatien Chevallier 	fdt_fill_device_info(fdt, &info, node);
2180cf1cd13SGatien Chevallier 	assert(info.reg != DT_INFO_INVALID_REG &&
2190cf1cd13SGatien Chevallier 	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
2200cf1cd13SGatien Chevallier 
2210cf1cd13SGatien Chevallier 	addr.pa = info.reg;
2220cf1cd13SGatien Chevallier 	hpdma_d->base = io_pa_or_va_secure(&addr, info.reg_size);
2230cf1cd13SGatien Chevallier 
2240cf1cd13SGatien Chevallier 	/* Gate the IP */
2250cf1cd13SGatien Chevallier 	res = clk_dt_get_by_index(fdt, node, 0, &hpdma_d->hpdma_clock);
2260cf1cd13SGatien Chevallier 	if (res)
2270cf1cd13SGatien Chevallier 		return res;
2280cf1cd13SGatien Chevallier 
2290cf1cd13SGatien Chevallier 	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
230307d268bSGatien Chevallier 	if (!cuint) {
231307d268bSGatien Chevallier 		DMSG("No RIF configuration available");
232307d268bSGatien Chevallier 		return TEE_SUCCESS;
233307d268bSGatien Chevallier 	}
234307d268bSGatien Chevallier 
235307d268bSGatien Chevallier 	hpdma_d->conf_data = calloc(1, sizeof(*hpdma_d->conf_data));
236307d268bSGatien Chevallier 	if (!hpdma_d->conf_data)
237307d268bSGatien Chevallier 		panic();
2380cf1cd13SGatien Chevallier 
2390cf1cd13SGatien Chevallier 	hpdma_d->nb_channels = (unsigned int)(lenp / sizeof(uint32_t));
2400cf1cd13SGatien Chevallier 	assert(hpdma_d->nb_channels <= HPDMA_RIF_CHANNELS);
2410cf1cd13SGatien Chevallier 
242307d268bSGatien Chevallier 	hpdma_d->conf_data->cid_confs = calloc(HPDMA_RIF_CHANNELS,
2430cf1cd13SGatien Chevallier 					       sizeof(uint32_t));
244307d268bSGatien Chevallier 	hpdma_d->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
245307d268bSGatien Chevallier 	hpdma_d->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
246307d268bSGatien Chevallier 	hpdma_d->conf_data->access_mask = calloc(1, sizeof(uint32_t));
247307d268bSGatien Chevallier 	hpdma_d->conf_data->lock_conf = calloc(1, sizeof(uint32_t));
248307d268bSGatien Chevallier 	if (!hpdma_d->conf_data->cid_confs || !hpdma_d->conf_data->sec_conf ||
249307d268bSGatien Chevallier 	    !hpdma_d->conf_data->priv_conf ||
250307d268bSGatien Chevallier 	    !hpdma_d->conf_data->access_mask || !hpdma_d->conf_data->lock_conf)
251307d268bSGatien Chevallier 		panic("Missing memory capacity for HPDMA RIF configuration");
2520cf1cd13SGatien Chevallier 
2530cf1cd13SGatien Chevallier 	for (i = 0; i < hpdma_d->nb_channels; i++)
254307d268bSGatien Chevallier 		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), hpdma_d->conf_data,
2550cf1cd13SGatien Chevallier 				    HPDMA_RIF_CHANNELS);
2560cf1cd13SGatien Chevallier 
2570cf1cd13SGatien Chevallier 	return TEE_SUCCESS;
2580cf1cd13SGatien Chevallier }
2590cf1cd13SGatien Chevallier 
2600cf1cd13SGatien Chevallier static void stm32_hpdma_pm_resume(struct hpdma_pdata *hpdma)
2610cf1cd13SGatien Chevallier {
2620cf1cd13SGatien Chevallier 	if (apply_rif_config(hpdma, true))
2630cf1cd13SGatien Chevallier 		panic("Failed to resume HPDMA");
2640cf1cd13SGatien Chevallier }
2650cf1cd13SGatien Chevallier 
2660cf1cd13SGatien Chevallier static void stm32_hpdma_pm_suspend(struct hpdma_pdata *hpdma)
2670cf1cd13SGatien Chevallier {
2680cf1cd13SGatien Chevallier 	size_t i = 0;
2690cf1cd13SGatien Chevallier 
2700cf1cd13SGatien Chevallier 	for (i = 0; i < HPDMA_RIF_CHANNELS; i++)
271307d268bSGatien Chevallier 		hpdma->conf_data->cid_confs[i] = io_read32(hpdma->base +
2720cf1cd13SGatien Chevallier 							  _HPDMA_CIDCFGR(i)) &
2730cf1cd13SGatien Chevallier 						_HPDMA_CIDCFGR_CONF_MASK;
2740cf1cd13SGatien Chevallier 
275307d268bSGatien Chevallier 	hpdma->conf_data->priv_conf[0] = io_read32(hpdma->base +
2760cf1cd13SGatien Chevallier 						  _HPDMA_PRIVCFGR) &
2770cf1cd13SGatien Chevallier 					_HPDMA_PRIVCFGR_MASK;
278307d268bSGatien Chevallier 	hpdma->conf_data->sec_conf[0] = io_read32(hpdma->base +
2790cf1cd13SGatien Chevallier 						 _HPDMA_SECCFGR) &
2800cf1cd13SGatien Chevallier 				       _HPDMA_SECCFGR_MASK;
281307d268bSGatien Chevallier 	hpdma->conf_data->lock_conf[0] = io_read32(hpdma->base +
2820cf1cd13SGatien Chevallier 						  _HPDMA_RCFGLOCKR) &
2830cf1cd13SGatien Chevallier 					_HPDMA_RCFGLOCKR_MASK;
2840cf1cd13SGatien Chevallier 
2850cf1cd13SGatien Chevallier 	/*
2860cf1cd13SGatien Chevallier 	 * The access mask is modified to restore the conf for all
2870cf1cd13SGatien Chevallier 	 * resources.
2880cf1cd13SGatien Chevallier 	 */
289307d268bSGatien Chevallier 	hpdma->conf_data->access_mask[0] = GENMASK_32(HPDMA_RIF_CHANNELS - 1,
290307d268bSGatien Chevallier 						      0);
2910cf1cd13SGatien Chevallier }
2920cf1cd13SGatien Chevallier 
2930cf1cd13SGatien Chevallier static TEE_Result
2940cf1cd13SGatien Chevallier stm32_hpdma_pm(enum pm_op op, unsigned int pm_hint,
2950cf1cd13SGatien Chevallier 	       const struct pm_callback_handle *pm_handle)
2960cf1cd13SGatien Chevallier {
2970cf1cd13SGatien Chevallier 	struct hpdma_pdata *hpdma = pm_handle->handle;
2980cf1cd13SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
2990cf1cd13SGatien Chevallier 	bool is_tdcid = false;
3000cf1cd13SGatien Chevallier 
3010cf1cd13SGatien Chevallier 	res = stm32_rifsc_check_tdcid(&is_tdcid);
3020cf1cd13SGatien Chevallier 	if (res)
3030cf1cd13SGatien Chevallier 		panic();
3040cf1cd13SGatien Chevallier 
3050cf1cd13SGatien Chevallier 	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !is_tdcid)
3060cf1cd13SGatien Chevallier 		return TEE_SUCCESS;
3070cf1cd13SGatien Chevallier 
3080cf1cd13SGatien Chevallier 	res = clk_enable(hpdma->hpdma_clock);
3090cf1cd13SGatien Chevallier 	if (res)
3100cf1cd13SGatien Chevallier 		return res;
3110cf1cd13SGatien Chevallier 
3120cf1cd13SGatien Chevallier 	if (op == PM_OP_RESUME)
3130cf1cd13SGatien Chevallier 		stm32_hpdma_pm_resume(hpdma);
3140cf1cd13SGatien Chevallier 	else
3150cf1cd13SGatien Chevallier 		stm32_hpdma_pm_suspend(hpdma);
3160cf1cd13SGatien Chevallier 
3170cf1cd13SGatien Chevallier 	clk_disable(hpdma->hpdma_clock);
3180cf1cd13SGatien Chevallier 
3190cf1cd13SGatien Chevallier 	return TEE_SUCCESS;
3200cf1cd13SGatien Chevallier }
3210cf1cd13SGatien Chevallier 
3220cf1cd13SGatien Chevallier static TEE_Result stm32_hpdma_probe(const void *fdt, int node,
3230cf1cd13SGatien Chevallier 				    const void *compat_data __unused)
3240cf1cd13SGatien Chevallier {
3250cf1cd13SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
3260cf1cd13SGatien Chevallier 	struct hpdma_pdata *hpdma_d = NULL;
3270cf1cd13SGatien Chevallier 	bool is_tdcid = false;
3280cf1cd13SGatien Chevallier 
3290cf1cd13SGatien Chevallier 	res = stm32_rifsc_check_tdcid(&is_tdcid);
3300cf1cd13SGatien Chevallier 	if (res)
3310cf1cd13SGatien Chevallier 		return res;
3320cf1cd13SGatien Chevallier 
3330cf1cd13SGatien Chevallier 	hpdma_d = calloc(1, sizeof(*hpdma_d));
3340cf1cd13SGatien Chevallier 	if (!hpdma_d)
3350cf1cd13SGatien Chevallier 		return TEE_ERROR_OUT_OF_MEMORY;
3360cf1cd13SGatien Chevallier 
3370cf1cd13SGatien Chevallier 	res = parse_dt(fdt, node, hpdma_d);
3380cf1cd13SGatien Chevallier 	if (res) {
3390cf1cd13SGatien Chevallier 		free(hpdma_d);
3400cf1cd13SGatien Chevallier 		return res;
3410cf1cd13SGatien Chevallier 	}
3420cf1cd13SGatien Chevallier 
3430cf1cd13SGatien Chevallier 	if (clk_enable(hpdma_d->hpdma_clock))
3440cf1cd13SGatien Chevallier 		panic("Cannot access hpdma clock");
3450cf1cd13SGatien Chevallier 
3460cf1cd13SGatien Chevallier 	res = apply_rif_config(hpdma_d, is_tdcid);
3470cf1cd13SGatien Chevallier 	if (res)
3480cf1cd13SGatien Chevallier 		panic("Failed to apply RIF config");
3490cf1cd13SGatien Chevallier 
3500cf1cd13SGatien Chevallier 	clk_disable(hpdma_d->hpdma_clock);
3510cf1cd13SGatien Chevallier 
3520cf1cd13SGatien Chevallier 	SLIST_INSERT_HEAD(&hpdma_list, hpdma_d, link);
3530cf1cd13SGatien Chevallier 
3540cf1cd13SGatien Chevallier 	register_pm_core_service_cb(stm32_hpdma_pm, hpdma_d, "stm32-hpdma");
3550cf1cd13SGatien Chevallier 
3560cf1cd13SGatien Chevallier 	return TEE_SUCCESS;
3570cf1cd13SGatien Chevallier }
3580cf1cd13SGatien Chevallier 
3590cf1cd13SGatien Chevallier static const struct dt_device_match stm32_hpdma_match_table[] = {
3600cf1cd13SGatien Chevallier 	{ .compatible = "st,stm32-dma3" },
3610cf1cd13SGatien Chevallier 	{ }
3620cf1cd13SGatien Chevallier };
3630cf1cd13SGatien Chevallier 
3640cf1cd13SGatien Chevallier DEFINE_DT_DRIVER(stm32_hpdma_dt_driver) = {
3650cf1cd13SGatien Chevallier 	.name = "st,stm32-hpdma",
3660cf1cd13SGatien Chevallier 	.match_table = stm32_hpdma_match_table,
3670cf1cd13SGatien Chevallier 	.probe = stm32_hpdma_probe,
3680cf1cd13SGatien Chevallier };
369