xref: /rk3399_ARM-atf/drivers/st/clk/stm32mp_clkfunc.c (revision 447b2b137d7286a1ef451336c6e73fb7fd8999a1)
1 /*
2  * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <errno.h>
8 
9 #include <libfdt.h>
10 
11 #include <platform_def.h>
12 
13 #include <drivers/st/stm32_gpio.h>
14 #include <drivers/st/stm32mp_clkfunc.h>
15 
16 #define DT_STGEN_COMPAT		"st,stm32-stgen"
17 
18 /*
19  * Get the RCC node offset from the device tree
20  * @param fdt: Device tree reference
21  * @return: Node offset or a negative value on error
22  */
23 int fdt_get_rcc_node(void *fdt)
24 {
25 	return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
26 }
27 
28 /*
29  * Get the RCC base address from the device tree
30  * @return: RCC address or 0 on error
31  */
32 uint32_t fdt_rcc_read_addr(void)
33 {
34 	int node;
35 	void *fdt;
36 	const fdt32_t *cuint;
37 
38 	if (fdt_get_address(&fdt) == 0) {
39 		return 0;
40 	}
41 
42 	node = fdt_get_rcc_node(fdt);
43 	if (node < 0) {
44 		return 0;
45 	}
46 
47 	cuint = fdt_getprop(fdt, node, "reg", NULL);
48 	if (cuint == NULL) {
49 		return 0;
50 	}
51 
52 	return fdt32_to_cpu(*cuint);
53 }
54 
55 /*
56  * Read a series of parameters in rcc-clk section in device tree
57  * @param prop_name: Name of the RCC property to be read
58  * @param array: the array to store the property parameters
59  * @param count: number of parameters to be read
60  * @return: 0 on succes or a negative value on error
61  */
62 int fdt_rcc_read_uint32_array(const char *prop_name,
63 			      uint32_t *array, uint32_t count)
64 {
65 	int node;
66 	void *fdt;
67 
68 	if (fdt_get_address(&fdt) == 0) {
69 		return -ENOENT;
70 	}
71 
72 	node = fdt_get_rcc_node(fdt);
73 	if (node < 0) {
74 		return -FDT_ERR_NOTFOUND;
75 	}
76 
77 	return fdt_read_uint32_array(node, prop_name, array, count);
78 }
79 
80 /*
81  * Get the subnode offset in rcc-clk section from its name in device tree
82  * @param name: name of the RCC property
83  * @return: offset on success, and a negative FDT/ERRNO error code on failure.
84  */
85 int fdt_rcc_subnode_offset(const char *name)
86 {
87 	int node, subnode;
88 	void *fdt;
89 
90 	if (fdt_get_address(&fdt) == 0) {
91 		return -ENOENT;
92 	}
93 
94 	node = fdt_get_rcc_node(fdt);
95 	if (node < 0) {
96 		return -FDT_ERR_NOTFOUND;
97 	}
98 
99 	subnode = fdt_subnode_offset(fdt, node, name);
100 	if (subnode <= 0) {
101 		return -FDT_ERR_NOTFOUND;
102 	}
103 
104 	return subnode;
105 }
106 
107 /*
108  * Get the pointer to a rcc-clk property from its name.
109  * @param name: name of the RCC property
110  * @param lenp: stores the length of the property.
111  * @return: pointer to the property on success, and NULL value on failure.
112  */
113 const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp)
114 {
115 	const fdt32_t *cuint;
116 	int node, len;
117 	void *fdt;
118 
119 	if (fdt_get_address(&fdt) == 0) {
120 		return NULL;
121 	}
122 
123 	node = fdt_get_rcc_node(fdt);
124 	if (node < 0) {
125 		return NULL;
126 	}
127 
128 	cuint = fdt_getprop(fdt, node, prop_name, &len);
129 	if (cuint == NULL) {
130 		return NULL;
131 	}
132 
133 	*lenp = len;
134 	return cuint;
135 }
136 
137 /*
138  * Get the secure status for rcc node in device tree.
139  * @return: true if rcc is available from secure world, false if not.
140  */
141 bool fdt_get_rcc_secure_status(void)
142 {
143 	int node;
144 	void *fdt;
145 
146 	if (fdt_get_address(&fdt) == 0) {
147 		return false;
148 	}
149 
150 	node = fdt_get_rcc_node(fdt);
151 	if (node < 0) {
152 		return false;
153 	}
154 
155 	return !!(fdt_get_status(node) & DT_SECURE);
156 }
157 
158 /*
159  * Get the stgen base address.
160  * @return: address of stgen on success, and NULL value on failure.
161  */
162 uintptr_t fdt_get_stgen_base(void)
163 {
164 	int node;
165 	const fdt32_t *cuint;
166 	void *fdt;
167 
168 	if (fdt_get_address(&fdt) == 0) {
169 		return 0;
170 	}
171 
172 	node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT);
173 	if (node < 0) {
174 		return 0;
175 	}
176 
177 	cuint = fdt_getprop(fdt, node, "reg", NULL);
178 	if (cuint == NULL) {
179 		return 0;
180 	}
181 
182 	return fdt32_to_cpu(*cuint);
183 }
184 
185 /*
186  * Get the clock ID of the given node in device tree.
187  * @param node: node offset
188  * @return: Clock ID on success, and a negative FDT/ERRNO error code on failure.
189  */
190 int fdt_get_clock_id(int node)
191 {
192 	const fdt32_t *cuint;
193 	void *fdt;
194 
195 	if (fdt_get_address(&fdt) == 0) {
196 		return -ENOENT;
197 	}
198 
199 	cuint = fdt_getprop(fdt, node, "clocks", NULL);
200 	if (cuint == NULL) {
201 		return -FDT_ERR_NOTFOUND;
202 	}
203 
204 	cuint++;
205 	return (int)fdt32_to_cpu(*cuint);
206 }
207