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