1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2021-2022, Linaro Limited
4  * Copyright (c) 2018-2022, STMicroelectronics
5  */
6 
7 #include <drivers/rstctrl.h>
8 #include <mm/core_memprot.h>
9 #include <stm32_util.h>
10 
11 #include "stm32_rstctrl.h"
12 
13 static struct stm32_reset_data *stm32_reset_pdata;
14 
15 static SLIST_HEAD(, stm32_rstline) stm32_rst_list =
16 	SLIST_HEAD_INITIALIZER(stm32_rst_list);
17 
find_rstctrl_device(unsigned int control_id)18 static struct stm32_rstline *find_rstctrl_device(unsigned int control_id)
19 {
20 	struct stm32_rstline *stm32_rstline = NULL;
21 
22 	SLIST_FOREACH(stm32_rstline, &stm32_rst_list, link)
23 		if (stm32_rstline->id == control_id)
24 			break;
25 
26 	return stm32_rstline;
27 }
28 
29 static struct
find_or_allocate_rstline(unsigned int binding_id,const struct stm32_reset_data * pdata)30 stm32_rstline *find_or_allocate_rstline(unsigned int binding_id,
31 					const struct stm32_reset_data *pdata)
32 {
33 	struct stm32_rstline *stm32_rstline = find_rstctrl_device(binding_id);
34 
35 	if (stm32_rstline)
36 		return stm32_rstline;
37 
38 	stm32_rstline = calloc(1, sizeof(*stm32_rstline));
39 	if (stm32_rstline) {
40 		assert(pdata->get_rstctrl_ops);
41 
42 		stm32_rstline->id = binding_id;
43 		stm32_rstline->data = pdata;
44 		stm32_rstline->rstctrl.ops = pdata->get_rstctrl_ops(binding_id);
45 
46 		SLIST_INSERT_HEAD(&stm32_rst_list, stm32_rstline, link);
47 	}
48 
49 	return stm32_rstline;
50 }
51 
to_stm32_rstline(struct rstctrl * rstctrl)52 struct stm32_rstline *to_stm32_rstline(struct rstctrl *rstctrl)
53 {
54 	assert(rstctrl);
55 
56 	return container_of(rstctrl, struct stm32_rstline, rstctrl);
57 }
58 
stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id)59 struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id)
60 {
61 	struct stm32_rstline *rstline = NULL;
62 
63 	rstline = find_or_allocate_rstline(binding_id, stm32_reset_pdata);
64 
65 	assert(rstline);
66 	return &rstline->rstctrl;
67 }
68 
stm32_rstctrl_get_dev(struct dt_pargs * arg,void * priv_data,struct rstctrl ** out_device)69 static TEE_Result stm32_rstctrl_get_dev(struct dt_pargs *arg,
70 					void *priv_data,
71 					struct rstctrl **out_device)
72 {
73 	struct stm32_rstline *stm32_rstline = NULL;
74 	uintptr_t control_id = 0;
75 
76 	if (arg->args_count != 1)
77 		return TEE_ERROR_BAD_PARAMETERS;
78 
79 	control_id = arg->args[0];
80 
81 	stm32_rstline = find_or_allocate_rstline(control_id, priv_data);
82 	if (!stm32_rstline)
83 		return TEE_ERROR_OUT_OF_MEMORY;
84 
85 	*out_device = &stm32_rstline->rstctrl;
86 
87 	return TEE_SUCCESS;
88 }
89 
stm32_rstctrl_provider_probe(const void * fdt,int offs,const void * compat_data)90 TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs,
91 					const void *compat_data)
92 {
93 	struct dt_node_info info = { };
94 
95 	stm32_reset_pdata = (struct stm32_reset_data *)compat_data;
96 
97 	fdt_fill_device_info(fdt, &info, offs);
98 
99 	assert(info.reg == RCC_BASE &&
100 	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
101 
102 	return rstctrl_register_provider(fdt, offs, stm32_rstctrl_get_dev,
103 					 stm32_reset_pdata);
104 }
105