1569d17b0SEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
2569d17b0SEtienne Carriere /*
3569d17b0SEtienne Carriere * Copyright (c) 2021-2022, Linaro Limited
4569d17b0SEtienne Carriere * Copyright (c) 2018-2022, STMicroelectronics
5569d17b0SEtienne Carriere */
6569d17b0SEtienne Carriere
7569d17b0SEtienne Carriere #include <drivers/rstctrl.h>
8569d17b0SEtienne Carriere #include <mm/core_memprot.h>
9569d17b0SEtienne Carriere #include <stm32_util.h>
10569d17b0SEtienne Carriere
113ef177b4SGabriel Fernandez #include "stm32_rstctrl.h"
12569d17b0SEtienne Carriere
133ef177b4SGabriel Fernandez static struct stm32_reset_data *stm32_reset_pdata;
14569d17b0SEtienne Carriere
15569d17b0SEtienne Carriere static SLIST_HEAD(, stm32_rstline) stm32_rst_list =
16569d17b0SEtienne Carriere SLIST_HEAD_INITIALIZER(stm32_rst_list);
17569d17b0SEtienne Carriere
find_rstctrl_device(unsigned int control_id)18569d17b0SEtienne Carriere static struct stm32_rstline *find_rstctrl_device(unsigned int control_id)
19569d17b0SEtienne Carriere {
20569d17b0SEtienne Carriere struct stm32_rstline *stm32_rstline = NULL;
21569d17b0SEtienne Carriere
22569d17b0SEtienne Carriere SLIST_FOREACH(stm32_rstline, &stm32_rst_list, link)
23569d17b0SEtienne Carriere if (stm32_rstline->id == control_id)
24569d17b0SEtienne Carriere break;
25569d17b0SEtienne Carriere
26569d17b0SEtienne Carriere return stm32_rstline;
27569d17b0SEtienne Carriere }
28569d17b0SEtienne Carriere
293ef177b4SGabriel Fernandez static struct
find_or_allocate_rstline(unsigned int binding_id,const struct stm32_reset_data * pdata)303ef177b4SGabriel Fernandez stm32_rstline *find_or_allocate_rstline(unsigned int binding_id,
313ef177b4SGabriel Fernandez const struct stm32_reset_data *pdata)
32569d17b0SEtienne Carriere {
33569d17b0SEtienne Carriere struct stm32_rstline *stm32_rstline = find_rstctrl_device(binding_id);
34569d17b0SEtienne Carriere
35569d17b0SEtienne Carriere if (stm32_rstline)
36569d17b0SEtienne Carriere return stm32_rstline;
37569d17b0SEtienne Carriere
38569d17b0SEtienne Carriere stm32_rstline = calloc(1, sizeof(*stm32_rstline));
39569d17b0SEtienne Carriere if (stm32_rstline) {
403ef177b4SGabriel Fernandez assert(pdata->get_rstctrl_ops);
413ef177b4SGabriel Fernandez
42569d17b0SEtienne Carriere stm32_rstline->id = binding_id;
43*b0323341SGabriel Fernandez stm32_rstline->data = pdata;
443ef177b4SGabriel Fernandez stm32_rstline->rstctrl.ops = pdata->get_rstctrl_ops(binding_id);
453ef177b4SGabriel Fernandez
46569d17b0SEtienne Carriere SLIST_INSERT_HEAD(&stm32_rst_list, stm32_rstline, link);
47569d17b0SEtienne Carriere }
48569d17b0SEtienne Carriere
49569d17b0SEtienne Carriere return stm32_rstline;
50569d17b0SEtienne Carriere }
51569d17b0SEtienne Carriere
to_stm32_rstline(struct rstctrl * rstctrl)523ef177b4SGabriel Fernandez struct stm32_rstline *to_stm32_rstline(struct rstctrl *rstctrl)
533ef177b4SGabriel Fernandez {
543ef177b4SGabriel Fernandez assert(rstctrl);
553ef177b4SGabriel Fernandez
563ef177b4SGabriel Fernandez return container_of(rstctrl, struct stm32_rstline, rstctrl);
573ef177b4SGabriel Fernandez }
583ef177b4SGabriel Fernandez
stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id)592f35a7bcSEtienne Carriere struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id)
602f35a7bcSEtienne Carriere {
613ef177b4SGabriel Fernandez struct stm32_rstline *rstline = NULL;
623ef177b4SGabriel Fernandez
633ef177b4SGabriel Fernandez rstline = find_or_allocate_rstline(binding_id, stm32_reset_pdata);
642f35a7bcSEtienne Carriere
652f35a7bcSEtienne Carriere assert(rstline);
662f35a7bcSEtienne Carriere return &rstline->rstctrl;
672f35a7bcSEtienne Carriere }
682f35a7bcSEtienne Carriere
stm32_rstctrl_get_dev(struct dt_pargs * arg,void * priv_data,struct rstctrl ** out_device)69b357d34fSEtienne Carriere static TEE_Result stm32_rstctrl_get_dev(struct dt_pargs *arg,
703ef177b4SGabriel Fernandez void *priv_data,
71b357d34fSEtienne Carriere struct rstctrl **out_device)
72569d17b0SEtienne Carriere {
73569d17b0SEtienne Carriere struct stm32_rstline *stm32_rstline = NULL;
74569d17b0SEtienne Carriere uintptr_t control_id = 0;
75569d17b0SEtienne Carriere
76b357d34fSEtienne Carriere if (arg->args_count != 1)
77b357d34fSEtienne Carriere return TEE_ERROR_BAD_PARAMETERS;
78b357d34fSEtienne Carriere
79569d17b0SEtienne Carriere control_id = arg->args[0];
80569d17b0SEtienne Carriere
813ef177b4SGabriel Fernandez stm32_rstline = find_or_allocate_rstline(control_id, priv_data);
82b357d34fSEtienne Carriere if (!stm32_rstline)
83b357d34fSEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY;
84569d17b0SEtienne Carriere
85b357d34fSEtienne Carriere *out_device = &stm32_rstline->rstctrl;
86b357d34fSEtienne Carriere
87b357d34fSEtienne Carriere return TEE_SUCCESS;
88569d17b0SEtienne Carriere }
89569d17b0SEtienne Carriere
stm32_rstctrl_provider_probe(const void * fdt,int offs,const void * compat_data)903ef177b4SGabriel Fernandez TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs,
913ef177b4SGabriel Fernandez const void *compat_data)
92569d17b0SEtienne Carriere {
93569d17b0SEtienne Carriere struct dt_node_info info = { };
94569d17b0SEtienne Carriere
953ef177b4SGabriel Fernandez stm32_reset_pdata = (struct stm32_reset_data *)compat_data;
96569d17b0SEtienne Carriere
97f354a5d8SGatien Chevallier fdt_fill_device_info(fdt, &info, offs);
98569d17b0SEtienne Carriere
99569d17b0SEtienne Carriere assert(info.reg == RCC_BASE &&
100569d17b0SEtienne Carriere info.reg_size != DT_INFO_INVALID_REG_SIZE);
101569d17b0SEtienne Carriere
102569d17b0SEtienne Carriere return rstctrl_register_provider(fdt, offs, stm32_rstctrl_get_dev,
1033ef177b4SGabriel Fernandez stm32_reset_pdata);
104569d17b0SEtienne Carriere }
105