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)
41*a5885a39SGatien Chevallier #define _HPDMA_CIDCFGR_SEMWL_SHIFT U(16)
420cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR_SCID_MASK GENMASK_32(5, 4)
43*a5885a39SGatien Chevallier #define _HPDMA_CIDCFGR_SCID_SHIFT U(4)
440cf1cd13SGatien Chevallier #define _HPDMA_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \
450cf1cd13SGatien Chevallier _CIDCFGR_SEMEN | \
460cf1cd13SGatien Chevallier _HPDMA_CIDCFGR_SCID_MASK |\
470cf1cd13SGatien Chevallier _HPDMA_CIDCFGR_SEMWL_MASK)
480cf1cd13SGatien Chevallier
490cf1cd13SGatien Chevallier /*
500cf1cd13SGatien Chevallier * PRIVCFGR register bitfields
510cf1cd13SGatien Chevallier */
520cf1cd13SGatien Chevallier #define _HPDMA_PRIVCFGR_MASK GENMASK_32(15, 0)
530cf1cd13SGatien Chevallier
540cf1cd13SGatien Chevallier /*
550cf1cd13SGatien Chevallier * RCFGLOCKR register bitfields
560cf1cd13SGatien Chevallier */
570cf1cd13SGatien Chevallier #define _HPDMA_RCFGLOCKR_MASK GENMASK_32(15, 0)
580cf1cd13SGatien Chevallier
590cf1cd13SGatien Chevallier /*
600cf1cd13SGatien Chevallier * SECCFGR register bitfields
610cf1cd13SGatien Chevallier */
620cf1cd13SGatien Chevallier #define _HPDMA_SECCFGR_EN BIT(0)
630cf1cd13SGatien Chevallier #define _HPDMA_SECCFGR_MASK GENMASK_32(15, 0)
640cf1cd13SGatien Chevallier
650cf1cd13SGatien Chevallier /*
660cf1cd13SGatien Chevallier * SEMCR register bitfields
670cf1cd13SGatien Chevallier */
680cf1cd13SGatien Chevallier #define _HPDMA_SEMCR_SCID_MASK GENMASK_32(5, 4)
690cf1cd13SGatien Chevallier #define _HPDMA_SEMCR_SCID_SHIFT U(4)
700cf1cd13SGatien Chevallier
710cf1cd13SGatien Chevallier /*
720cf1cd13SGatien Chevallier * Miscellaneous
730cf1cd13SGatien Chevallier */
740cf1cd13SGatien Chevallier
750cf1cd13SGatien Chevallier #define HPDMA_RIF_CHANNELS U(16)
760cf1cd13SGatien Chevallier
770cf1cd13SGatien Chevallier #define HPDMA_NB_MAX_CID_SUPPORTED U(3)
780cf1cd13SGatien Chevallier
790cf1cd13SGatien Chevallier struct hpdma_pdata {
800cf1cd13SGatien Chevallier struct clk *hpdma_clock;
81307d268bSGatien Chevallier struct rif_conf_data *conf_data;
820cf1cd13SGatien Chevallier unsigned int nb_channels;
830cf1cd13SGatien Chevallier vaddr_t base;
84*a5885a39SGatien Chevallier bool errata_ahbrisab;
850cf1cd13SGatien Chevallier
860cf1cd13SGatien Chevallier SLIST_ENTRY(hpdma_pdata) link;
870cf1cd13SGatien Chevallier };
880cf1cd13SGatien Chevallier
890cf1cd13SGatien Chevallier static SLIST_HEAD(, hpdma_pdata) hpdma_list =
900cf1cd13SGatien Chevallier SLIST_HEAD_INITIALIZER(hpdma_list);
910cf1cd13SGatien Chevallier
handle_available_semaphores(struct hpdma_pdata * hpdma_d)925c2c026aSGatien Chevallier static TEE_Result handle_available_semaphores(struct hpdma_pdata *hpdma_d)
935c2c026aSGatien Chevallier {
945c2c026aSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC;
955c2c026aSGatien Chevallier uint32_t cidcfgr = 0;
965c2c026aSGatien Chevallier unsigned int i = 0;
975c2c026aSGatien Chevallier
985c2c026aSGatien Chevallier for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
995c2c026aSGatien Chevallier if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
1005c2c026aSGatien Chevallier continue;
1015c2c026aSGatien Chevallier
1025c2c026aSGatien Chevallier cidcfgr = io_read32(hpdma_d->base + _HPDMA_CIDCFGR(i));
1035c2c026aSGatien Chevallier
1045c2c026aSGatien Chevallier if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
1055c2c026aSGatien Chevallier continue;
1065c2c026aSGatien Chevallier
1075c2c026aSGatien Chevallier if (!(io_read32(hpdma_d->base + _HPDMA_SECCFGR) & BIT(i))) {
1085c2c026aSGatien Chevallier res =
1095c2c026aSGatien Chevallier stm32_rif_release_semaphore(hpdma_d->base +
1105c2c026aSGatien Chevallier _HPDMA_SEMCR(i),
1115c2c026aSGatien Chevallier HPDMA_NB_MAX_CID_SUPPORTED);
1125c2c026aSGatien Chevallier if (res) {
1135c2c026aSGatien Chevallier EMSG("Cannot release semaphore for resource %u",
1145c2c026aSGatien Chevallier i);
1155c2c026aSGatien Chevallier return res;
1165c2c026aSGatien Chevallier }
1175c2c026aSGatien Chevallier } else {
1185c2c026aSGatien Chevallier res =
1195c2c026aSGatien Chevallier stm32_rif_acquire_semaphore(hpdma_d->base +
1205c2c026aSGatien Chevallier _HPDMA_SEMCR(i),
1215c2c026aSGatien Chevallier HPDMA_NB_MAX_CID_SUPPORTED);
1225c2c026aSGatien Chevallier if (res) {
1235c2c026aSGatien Chevallier EMSG("Cannot acquire semaphore for resource %u",
1245c2c026aSGatien Chevallier i);
1255c2c026aSGatien Chevallier return res;
1265c2c026aSGatien Chevallier }
1275c2c026aSGatien Chevallier }
1285c2c026aSGatien Chevallier }
1295c2c026aSGatien Chevallier
1305c2c026aSGatien Chevallier return TEE_SUCCESS;
1315c2c026aSGatien Chevallier }
1325c2c026aSGatien Chevallier
1330cf1cd13SGatien Chevallier /* This function expects HPDMA bus clock is enabled */
apply_rif_config(struct hpdma_pdata * hpdma_d,bool is_tdcid)1340cf1cd13SGatien Chevallier static TEE_Result apply_rif_config(struct hpdma_pdata *hpdma_d, bool is_tdcid)
1350cf1cd13SGatien Chevallier {
1360cf1cd13SGatien Chevallier TEE_Result res = TEE_ERROR_ACCESS_DENIED;
1370cf1cd13SGatien Chevallier unsigned int i = 0;
1380cf1cd13SGatien Chevallier
139307d268bSGatien Chevallier if (!hpdma_d->conf_data)
140307d268bSGatien Chevallier return TEE_SUCCESS;
141307d268bSGatien Chevallier
1425c2c026aSGatien Chevallier if (is_tdcid) {
1430cf1cd13SGatien Chevallier for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
144307d268bSGatien Chevallier if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
1450cf1cd13SGatien Chevallier continue;
1460cf1cd13SGatien Chevallier /*
1475c2c026aSGatien Chevallier * When TDCID, OP-TEE should be the one to set the CID
1485c2c026aSGatien Chevallier * filtering configuration. Clearing previous
1495c2c026aSGatien Chevallier * configuration prevents undesired events during the
1505c2c026aSGatien Chevallier * only legitimate configuration.
1510cf1cd13SGatien Chevallier */
1520cf1cd13SGatien Chevallier io_clrbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
1530cf1cd13SGatien Chevallier _HPDMA_CIDCFGR_CONF_MASK);
1540cf1cd13SGatien Chevallier }
1555c2c026aSGatien Chevallier } else {
1565c2c026aSGatien Chevallier res = handle_available_semaphores(hpdma_d);
1575c2c026aSGatien Chevallier if (res)
1585c2c026aSGatien Chevallier panic();
1590cf1cd13SGatien Chevallier }
1600cf1cd13SGatien Chevallier
1610cf1cd13SGatien Chevallier /* Security and privilege RIF configuration */
1620cf1cd13SGatien Chevallier io_clrsetbits32(hpdma_d->base + _HPDMA_PRIVCFGR, _HPDMA_PRIVCFGR_MASK &
163307d268bSGatien Chevallier hpdma_d->conf_data->access_mask[0],
164307d268bSGatien Chevallier hpdma_d->conf_data->priv_conf[0]);
1650cf1cd13SGatien Chevallier io_clrsetbits32(hpdma_d->base + _HPDMA_SECCFGR, _HPDMA_SECCFGR_MASK &
166307d268bSGatien Chevallier hpdma_d->conf_data->access_mask[0],
167307d268bSGatien Chevallier hpdma_d->conf_data->sec_conf[0]);
1680cf1cd13SGatien Chevallier
1690cf1cd13SGatien Chevallier /* Skip CID/semaphore configuration if not in TDCID state. */
1700cf1cd13SGatien Chevallier if (!is_tdcid)
1710cf1cd13SGatien Chevallier goto end;
1720cf1cd13SGatien Chevallier
1730cf1cd13SGatien Chevallier for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
174*a5885a39SGatien Chevallier uint32_t cid_conf = hpdma_d->conf_data->cid_confs[i];
175*a5885a39SGatien Chevallier
176307d268bSGatien Chevallier if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
1770cf1cd13SGatien Chevallier continue;
1780cf1cd13SGatien Chevallier
179*a5885a39SGatien Chevallier /*
180*a5885a39SGatien Chevallier * Errata: When CID filtering is enabled on one of RISAB 3/4/5
181*a5885a39SGatien Chevallier * instances, we forbid the use of CID0 for any initiator on the
182*a5885a39SGatien Chevallier * bus to handle transient CID0 transactions on these RAMs.
183*a5885a39SGatien Chevallier */
184*a5885a39SGatien Chevallier if (hpdma_d->errata_ahbrisab &&
185*a5885a39SGatien Chevallier (!(cid_conf & _CIDCFGR_CFEN) ||
186*a5885a39SGatien Chevallier (!(cid_conf & _CIDCFGR_SEMEN) &&
187*a5885a39SGatien Chevallier ((cid_conf & _HPDMA_CIDCFGR_SCID_MASK) >>
188*a5885a39SGatien Chevallier _HPDMA_CIDCFGR_SCID_SHIFT) == RIF_CID0) ||
189*a5885a39SGatien Chevallier (cid_conf & _CIDCFGR_SEMEN &&
190*a5885a39SGatien Chevallier cid_conf & BIT(RIF_CID0 + _HPDMA_CIDCFGR_SEMWL_SHIFT)))) {
191*a5885a39SGatien Chevallier EMSG("HPDMA channel cannot hold CID0 value");
192*a5885a39SGatien Chevallier if (!IS_ENABLED(CFG_INSECURE))
193*a5885a39SGatien Chevallier panic();
194*a5885a39SGatien Chevallier }
195*a5885a39SGatien Chevallier
1960cf1cd13SGatien Chevallier io_clrsetbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
197*a5885a39SGatien Chevallier _HPDMA_CIDCFGR_CONF_MASK, cid_conf);
1980cf1cd13SGatien Chevallier }
1990cf1cd13SGatien Chevallier
2000cf1cd13SGatien Chevallier /*
2010cf1cd13SGatien Chevallier * Lock RIF configuration if configured. This cannot be undone until
2020cf1cd13SGatien Chevallier * next reset.
2030cf1cd13SGatien Chevallier */
2045c2c026aSGatien Chevallier io_setbits32(hpdma_d->base + _HPDMA_RCFGLOCKR,
205307d268bSGatien Chevallier hpdma_d->conf_data->lock_conf[0]);
2060cf1cd13SGatien Chevallier
2075c2c026aSGatien Chevallier res = handle_available_semaphores(hpdma_d);
2085c2c026aSGatien Chevallier if (res)
2095c2c026aSGatien Chevallier panic();
2105c2c026aSGatien Chevallier
2110cf1cd13SGatien Chevallier end:
2120cf1cd13SGatien Chevallier if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
2130cf1cd13SGatien Chevallier /* Check that RIF config are applied, panic otherwise */
2140cf1cd13SGatien Chevallier if ((io_read32(hpdma_d->base + _HPDMA_PRIVCFGR) &
215307d268bSGatien Chevallier hpdma_d->conf_data->access_mask[0]) !=
216307d268bSGatien Chevallier hpdma_d->conf_data->priv_conf[0])
2170cf1cd13SGatien Chevallier panic("HPDMA channel priv conf is incorrect");
2180cf1cd13SGatien Chevallier
2190cf1cd13SGatien Chevallier if ((io_read32(hpdma_d->base + _HPDMA_SECCFGR) &
220307d268bSGatien Chevallier hpdma_d->conf_data->access_mask[0]) !=
221307d268bSGatien Chevallier hpdma_d->conf_data->sec_conf[0])
2220cf1cd13SGatien Chevallier panic("HPDMA channel sec conf is incorrect");
2230cf1cd13SGatien Chevallier }
2240cf1cd13SGatien Chevallier
2250cf1cd13SGatien Chevallier return TEE_SUCCESS;
2260cf1cd13SGatien Chevallier }
2270cf1cd13SGatien Chevallier
parse_dt(const void * fdt,int node,struct hpdma_pdata * hpdma_d)2280cf1cd13SGatien Chevallier static TEE_Result parse_dt(const void *fdt, int node,
2290cf1cd13SGatien Chevallier struct hpdma_pdata *hpdma_d)
2300cf1cd13SGatien Chevallier {
2310cf1cd13SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC;
2320cf1cd13SGatien Chevallier unsigned int i = 0;
2330cf1cd13SGatien Chevallier int lenp = 0;
2340cf1cd13SGatien Chevallier const fdt32_t *cuint = NULL;
2350cf1cd13SGatien Chevallier struct dt_node_info info = { };
2360cf1cd13SGatien Chevallier struct io_pa_va addr = { };
2370cf1cd13SGatien Chevallier
2380cf1cd13SGatien Chevallier fdt_fill_device_info(fdt, &info, node);
2390cf1cd13SGatien Chevallier assert(info.reg != DT_INFO_INVALID_REG &&
2400cf1cd13SGatien Chevallier info.reg_size != DT_INFO_INVALID_REG_SIZE);
2410cf1cd13SGatien Chevallier
2420cf1cd13SGatien Chevallier addr.pa = info.reg;
2430cf1cd13SGatien Chevallier hpdma_d->base = io_pa_or_va_secure(&addr, info.reg_size);
2440cf1cd13SGatien Chevallier
2450cf1cd13SGatien Chevallier /* Gate the IP */
2460cf1cd13SGatien Chevallier res = clk_dt_get_by_index(fdt, node, 0, &hpdma_d->hpdma_clock);
2470cf1cd13SGatien Chevallier if (res)
2480cf1cd13SGatien Chevallier return res;
2490cf1cd13SGatien Chevallier
250*a5885a39SGatien Chevallier hpdma_d->errata_ahbrisab = fdt_getprop(fdt, node, "st,errata-ahbrisab",
251*a5885a39SGatien Chevallier NULL);
252*a5885a39SGatien Chevallier
2530cf1cd13SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
254307d268bSGatien Chevallier if (!cuint) {
255307d268bSGatien Chevallier DMSG("No RIF configuration available");
256307d268bSGatien Chevallier return TEE_SUCCESS;
257307d268bSGatien Chevallier }
258307d268bSGatien Chevallier
259307d268bSGatien Chevallier hpdma_d->conf_data = calloc(1, sizeof(*hpdma_d->conf_data));
260307d268bSGatien Chevallier if (!hpdma_d->conf_data)
261307d268bSGatien Chevallier panic();
2620cf1cd13SGatien Chevallier
2630cf1cd13SGatien Chevallier hpdma_d->nb_channels = (unsigned int)(lenp / sizeof(uint32_t));
2640cf1cd13SGatien Chevallier assert(hpdma_d->nb_channels <= HPDMA_RIF_CHANNELS);
2650cf1cd13SGatien Chevallier
266307d268bSGatien Chevallier hpdma_d->conf_data->cid_confs = calloc(HPDMA_RIF_CHANNELS,
2670cf1cd13SGatien Chevallier sizeof(uint32_t));
268307d268bSGatien Chevallier hpdma_d->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
269307d268bSGatien Chevallier hpdma_d->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
270307d268bSGatien Chevallier hpdma_d->conf_data->access_mask = calloc(1, sizeof(uint32_t));
271307d268bSGatien Chevallier hpdma_d->conf_data->lock_conf = calloc(1, sizeof(uint32_t));
272307d268bSGatien Chevallier if (!hpdma_d->conf_data->cid_confs || !hpdma_d->conf_data->sec_conf ||
273307d268bSGatien Chevallier !hpdma_d->conf_data->priv_conf ||
274307d268bSGatien Chevallier !hpdma_d->conf_data->access_mask || !hpdma_d->conf_data->lock_conf)
275307d268bSGatien Chevallier panic("Missing memory capacity for HPDMA RIF configuration");
2760cf1cd13SGatien Chevallier
2770cf1cd13SGatien Chevallier for (i = 0; i < hpdma_d->nb_channels; i++)
278307d268bSGatien Chevallier stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), hpdma_d->conf_data,
2790cf1cd13SGatien Chevallier HPDMA_RIF_CHANNELS);
2800cf1cd13SGatien Chevallier
2810cf1cd13SGatien Chevallier return TEE_SUCCESS;
2820cf1cd13SGatien Chevallier }
2830cf1cd13SGatien Chevallier
stm32_hpdma_pm_resume(struct hpdma_pdata * hpdma)2840cf1cd13SGatien Chevallier static void stm32_hpdma_pm_resume(struct hpdma_pdata *hpdma)
2850cf1cd13SGatien Chevallier {
2860cf1cd13SGatien Chevallier if (apply_rif_config(hpdma, true))
2870cf1cd13SGatien Chevallier panic("Failed to resume HPDMA");
2880cf1cd13SGatien Chevallier }
2890cf1cd13SGatien Chevallier
stm32_hpdma_pm_suspend(struct hpdma_pdata * hpdma)2900cf1cd13SGatien Chevallier static void stm32_hpdma_pm_suspend(struct hpdma_pdata *hpdma)
2910cf1cd13SGatien Chevallier {
2920cf1cd13SGatien Chevallier size_t i = 0;
2930cf1cd13SGatien Chevallier
2940cf1cd13SGatien Chevallier for (i = 0; i < HPDMA_RIF_CHANNELS; i++)
295307d268bSGatien Chevallier hpdma->conf_data->cid_confs[i] = io_read32(hpdma->base +
2960cf1cd13SGatien Chevallier _HPDMA_CIDCFGR(i)) &
2970cf1cd13SGatien Chevallier _HPDMA_CIDCFGR_CONF_MASK;
2980cf1cd13SGatien Chevallier
299307d268bSGatien Chevallier hpdma->conf_data->priv_conf[0] = io_read32(hpdma->base +
3000cf1cd13SGatien Chevallier _HPDMA_PRIVCFGR) &
3010cf1cd13SGatien Chevallier _HPDMA_PRIVCFGR_MASK;
302307d268bSGatien Chevallier hpdma->conf_data->sec_conf[0] = io_read32(hpdma->base +
3030cf1cd13SGatien Chevallier _HPDMA_SECCFGR) &
3040cf1cd13SGatien Chevallier _HPDMA_SECCFGR_MASK;
305307d268bSGatien Chevallier hpdma->conf_data->lock_conf[0] = io_read32(hpdma->base +
3060cf1cd13SGatien Chevallier _HPDMA_RCFGLOCKR) &
3070cf1cd13SGatien Chevallier _HPDMA_RCFGLOCKR_MASK;
3080cf1cd13SGatien Chevallier
3090cf1cd13SGatien Chevallier /*
3100cf1cd13SGatien Chevallier * The access mask is modified to restore the conf for all
3110cf1cd13SGatien Chevallier * resources.
3120cf1cd13SGatien Chevallier */
313307d268bSGatien Chevallier hpdma->conf_data->access_mask[0] = GENMASK_32(HPDMA_RIF_CHANNELS - 1,
314307d268bSGatien Chevallier 0);
3150cf1cd13SGatien Chevallier }
3160cf1cd13SGatien Chevallier
3170cf1cd13SGatien Chevallier static TEE_Result
stm32_hpdma_pm(enum pm_op op,unsigned int pm_hint,const struct pm_callback_handle * pm_handle)3180cf1cd13SGatien Chevallier stm32_hpdma_pm(enum pm_op op, unsigned int pm_hint,
3190cf1cd13SGatien Chevallier const struct pm_callback_handle *pm_handle)
3200cf1cd13SGatien Chevallier {
3210cf1cd13SGatien Chevallier struct hpdma_pdata *hpdma = pm_handle->handle;
3220cf1cd13SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC;
3230cf1cd13SGatien Chevallier bool is_tdcid = false;
3240cf1cd13SGatien Chevallier
3250cf1cd13SGatien Chevallier res = stm32_rifsc_check_tdcid(&is_tdcid);
3260cf1cd13SGatien Chevallier if (res)
3270cf1cd13SGatien Chevallier panic();
3280cf1cd13SGatien Chevallier
3290cf1cd13SGatien Chevallier if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !is_tdcid)
3300cf1cd13SGatien Chevallier return TEE_SUCCESS;
3310cf1cd13SGatien Chevallier
3320cf1cd13SGatien Chevallier res = clk_enable(hpdma->hpdma_clock);
3330cf1cd13SGatien Chevallier if (res)
3340cf1cd13SGatien Chevallier return res;
3350cf1cd13SGatien Chevallier
3360cf1cd13SGatien Chevallier if (op == PM_OP_RESUME)
3370cf1cd13SGatien Chevallier stm32_hpdma_pm_resume(hpdma);
3380cf1cd13SGatien Chevallier else
3390cf1cd13SGatien Chevallier stm32_hpdma_pm_suspend(hpdma);
3400cf1cd13SGatien Chevallier
3410cf1cd13SGatien Chevallier clk_disable(hpdma->hpdma_clock);
3420cf1cd13SGatien Chevallier
3430cf1cd13SGatien Chevallier return TEE_SUCCESS;
3440cf1cd13SGatien Chevallier }
3450cf1cd13SGatien Chevallier
stm32_hpdma_probe(const void * fdt,int node,const void * compat_data __unused)3460cf1cd13SGatien Chevallier static TEE_Result stm32_hpdma_probe(const void *fdt, int node,
3470cf1cd13SGatien Chevallier const void *compat_data __unused)
3480cf1cd13SGatien Chevallier {
3490cf1cd13SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC;
3500cf1cd13SGatien Chevallier struct hpdma_pdata *hpdma_d = NULL;
3510cf1cd13SGatien Chevallier bool is_tdcid = false;
3520cf1cd13SGatien Chevallier
3530cf1cd13SGatien Chevallier res = stm32_rifsc_check_tdcid(&is_tdcid);
3540cf1cd13SGatien Chevallier if (res)
3550cf1cd13SGatien Chevallier return res;
3560cf1cd13SGatien Chevallier
3570cf1cd13SGatien Chevallier hpdma_d = calloc(1, sizeof(*hpdma_d));
3580cf1cd13SGatien Chevallier if (!hpdma_d)
3590cf1cd13SGatien Chevallier return TEE_ERROR_OUT_OF_MEMORY;
3600cf1cd13SGatien Chevallier
3610cf1cd13SGatien Chevallier res = parse_dt(fdt, node, hpdma_d);
3620cf1cd13SGatien Chevallier if (res) {
3630cf1cd13SGatien Chevallier free(hpdma_d);
3640cf1cd13SGatien Chevallier return res;
3650cf1cd13SGatien Chevallier }
3660cf1cd13SGatien Chevallier
3670cf1cd13SGatien Chevallier if (clk_enable(hpdma_d->hpdma_clock))
3680cf1cd13SGatien Chevallier panic("Cannot access hpdma clock");
3690cf1cd13SGatien Chevallier
3700cf1cd13SGatien Chevallier res = apply_rif_config(hpdma_d, is_tdcid);
3710cf1cd13SGatien Chevallier if (res)
3720cf1cd13SGatien Chevallier panic("Failed to apply RIF config");
3730cf1cd13SGatien Chevallier
3740cf1cd13SGatien Chevallier clk_disable(hpdma_d->hpdma_clock);
3750cf1cd13SGatien Chevallier
3760cf1cd13SGatien Chevallier SLIST_INSERT_HEAD(&hpdma_list, hpdma_d, link);
3770cf1cd13SGatien Chevallier
3780cf1cd13SGatien Chevallier register_pm_core_service_cb(stm32_hpdma_pm, hpdma_d, "stm32-hpdma");
3790cf1cd13SGatien Chevallier
3800cf1cd13SGatien Chevallier return TEE_SUCCESS;
3810cf1cd13SGatien Chevallier }
3820cf1cd13SGatien Chevallier
3830cf1cd13SGatien Chevallier static const struct dt_device_match stm32_hpdma_match_table[] = {
3840cf1cd13SGatien Chevallier { .compatible = "st,stm32-dma3" },
3850cf1cd13SGatien Chevallier { }
3860cf1cd13SGatien Chevallier };
3870cf1cd13SGatien Chevallier
3880cf1cd13SGatien Chevallier DEFINE_DT_DRIVER(stm32_hpdma_dt_driver) = {
3890cf1cd13SGatien Chevallier .name = "st,stm32-hpdma",
3900cf1cd13SGatien Chevallier .match_table = stm32_hpdma_match_table,
3910cf1cd13SGatien Chevallier .probe = stm32_hpdma_probe,
3920cf1cd13SGatien Chevallier };
393