xref: /optee_os/core/drivers/rstctrl/stm32_rstctrl.c (revision b0323341ea4bb6d3410882fb4ce2dcea3666802c)
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