blob: 16acef07bea1d9c70d44d9cdf48da2e1fa6fc540 [file] [log] [blame]
Yann Gautier4d429472019-02-14 11:15:20 +01001/*
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 */
23int 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 */
32uint32_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 */
62int 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 */
85int 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 */
113const 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 */
141bool 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 */
162uintptr_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 */
190int 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}