blob: 0b6a0d32f2ccc74da519ecd00963f28384da8b68 [file] [log] [blame]
Yann Gautier9aea69e2018-07-24 17:13:36 +02001/*
Yann Gautier038bff22019-01-17 19:17:47 +01002 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
Yann Gautier9aea69e2018-07-24 17:13:36 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
Yann Gautier038bff22019-01-17 19:17:47 +01008#include <errno.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009
Yann Gautier9aea69e2018-07-24 17:13:36 +020010#include <libfdt.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011
Yann Gautier9aea69e2018-07-24 17:13:36 +020012#include <platform_def.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013
14#include <common/debug.h>
15#include <drivers/st/stm32_gpio.h>
16#include <drivers/st/stm32mp1_clk.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000017#include <drivers/st/stm32mp1_ddr.h>
18#include <drivers/st/stm32mp1_ram.h>
19
Yann Gautieree8f5422019-02-14 11:13:25 +010020#include <stm32mp_dt.h>
21
Yann Gautier9aea69e2018-07-24 17:13:36 +020022static int fdt_checked;
23
Yann Gautiera2e2a302019-02-14 11:13:39 +010024static void *fdt = (void *)(uintptr_t)STM32MP_DTB_BASE;
Yann Gautier9aea69e2018-07-24 17:13:36 +020025
26/*******************************************************************************
27 * This function checks device tree file with its header.
Yann Gautier038bff22019-01-17 19:17:47 +010028 * Returns 0 on success and a negative FDT error code on failure.
Yann Gautier9aea69e2018-07-24 17:13:36 +020029 ******************************************************************************/
30int dt_open_and_check(void)
31{
32 int ret = fdt_check_header(fdt);
33
34 if (ret == 0) {
35 fdt_checked = 1;
36 }
37
38 return ret;
39}
40
41/*******************************************************************************
42 * This function gets the address of the DT.
43 * If DT is OK, fdt_addr is filled with DT address.
44 * Returns 1 if success, 0 otherwise.
45 ******************************************************************************/
46int fdt_get_address(void **fdt_addr)
47{
48 if (fdt_checked == 1) {
49 *fdt_addr = fdt;
50 }
51
52 return fdt_checked;
53}
54
55/*******************************************************************************
56 * This function check the presence of a node (generic use of fdt library).
Yann Gautier038bff22019-01-17 19:17:47 +010057 * Returns true if present, else return false.
Yann Gautier9aea69e2018-07-24 17:13:36 +020058 ******************************************************************************/
59bool fdt_check_node(int node)
60{
61 int len;
62 const char *cchar;
63
64 cchar = fdt_get_name(fdt, node, &len);
65
66 return (cchar != NULL) && (len >= 0);
67}
68
69/*******************************************************************************
Yann Gautier038bff22019-01-17 19:17:47 +010070 * This function return global node status (generic use of fdt library).
Yann Gautier9aea69e2018-07-24 17:13:36 +020071 ******************************************************************************/
Yann Gautieree8f5422019-02-14 11:13:25 +010072uint8_t fdt_get_status(int node)
Yann Gautier9aea69e2018-07-24 17:13:36 +020073{
Yann Gautieree8f5422019-02-14 11:13:25 +010074 uint8_t status = DT_DISABLED;
Yann Gautier9aea69e2018-07-24 17:13:36 +020075 int len;
76 const char *cchar;
77
78 cchar = fdt_getprop(fdt, node, "status", &len);
Yann Gautier038bff22019-01-17 19:17:47 +010079 if ((cchar == NULL) ||
80 (strncmp(cchar, "okay", (size_t)len) == 0)) {
81 status |= DT_NON_SECURE;
Yann Gautier9aea69e2018-07-24 17:13:36 +020082 }
83
Yann Gautier9aea69e2018-07-24 17:13:36 +020084 cchar = fdt_getprop(fdt, node, "secure-status", &len);
85 if (cchar == NULL) {
Yann Gautier038bff22019-01-17 19:17:47 +010086 if (status == DT_NON_SECURE) {
87 status |= DT_SECURE;
88 }
89 } else if (strncmp(cchar, "okay", (size_t)len) == 0) {
90 status |= DT_SECURE;
Yann Gautier9aea69e2018-07-24 17:13:36 +020091 }
92
Yann Gautier038bff22019-01-17 19:17:47 +010093 return status;
Yann Gautier9aea69e2018-07-24 17:13:36 +020094}
95
96/*******************************************************************************
97 * This function reads a value of a node property (generic use of fdt
98 * library).
99 * Returns value if success, and a default value if property not found.
100 * Default value is passed as parameter.
101 ******************************************************************************/
102uint32_t fdt_read_uint32_default(int node, const char *prop_name,
103 uint32_t dflt_value)
104{
105 const fdt32_t *cuint;
106 int lenp;
107
108 cuint = fdt_getprop(fdt, node, prop_name, &lenp);
109 if (cuint == NULL) {
110 return dflt_value;
111 }
112
113 return fdt32_to_cpu(*cuint);
114}
115
116/*******************************************************************************
117 * This function reads a series of parameters in a node property
118 * (generic use of fdt library).
119 * It reads the values inside the device tree, from property name and node.
120 * The number of parameters is also indicated as entry parameter.
Yann Gautier038bff22019-01-17 19:17:47 +0100121 * Returns 0 on success and a negative FDT error code on failure.
Yann Gautier9aea69e2018-07-24 17:13:36 +0200122 * If success, values are stored at the third parameter address.
123 ******************************************************************************/
124int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array,
125 uint32_t count)
126{
127 const fdt32_t *cuint;
128 int len;
129 uint32_t i;
130
131 cuint = fdt_getprop(fdt, node, prop_name, &len);
132 if (cuint == NULL) {
133 return -FDT_ERR_NOTFOUND;
134 }
135
136 if ((uint32_t)len != (count * sizeof(uint32_t))) {
137 return -FDT_ERR_BADLAYOUT;
138 }
139
140 for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
141 *array = fdt32_to_cpu(*cuint);
142 array++;
143 cuint++;
144 }
145
146 return 0;
147}
Yann Gautierd0ca7f42018-07-13 21:33:09 +0200148
149/*******************************************************************************
Yann Gautier69035a82018-07-05 16:48:16 +0200150 * This function gets the stdout pin configuration information from the DT.
151 * And then calls the sub-function to treat it and set GPIO registers.
Yann Gautier038bff22019-01-17 19:17:47 +0100152 * Returns 0 on success and a negative FDT error code on failure.
Yann Gautier69035a82018-07-05 16:48:16 +0200153 ******************************************************************************/
154int dt_set_stdout_pinctrl(void)
155{
156 int node;
157
158 node = dt_get_stdout_node_offset();
159 if (node < 0) {
160 return -FDT_ERR_NOTFOUND;
161 }
162
163 return dt_set_pinctrl_config(node);
164}
165
166/*******************************************************************************
167 * This function fills the generic information from a given node.
168 ******************************************************************************/
169void dt_fill_device_info(struct dt_node_info *info, int node)
170{
171 const fdt32_t *cuint;
172
173 cuint = fdt_getprop(fdt, node, "reg", NULL);
174 if (cuint != NULL) {
175 info->base = fdt32_to_cpu(*cuint);
176 } else {
177 info->base = 0;
178 }
179
180 cuint = fdt_getprop(fdt, node, "clocks", NULL);
181 if (cuint != NULL) {
182 cuint++;
183 info->clock = (int)fdt32_to_cpu(*cuint);
184 } else {
185 info->clock = -1;
186 }
187
188 cuint = fdt_getprop(fdt, node, "resets", NULL);
189 if (cuint != NULL) {
190 cuint++;
191 info->reset = (int)fdt32_to_cpu(*cuint);
192 } else {
193 info->reset = -1;
194 }
195
Yann Gautier038bff22019-01-17 19:17:47 +0100196 info->status = fdt_get_status(node);
Yann Gautier69035a82018-07-05 16:48:16 +0200197}
198
199/*******************************************************************************
200 * This function retrieve the generic information from DT.
Yann Gautier038bff22019-01-17 19:17:47 +0100201 * Returns node on success and a negative FDT error code on failure.
Yann Gautier69035a82018-07-05 16:48:16 +0200202 ******************************************************************************/
203int dt_get_node(struct dt_node_info *info, int offset, const char *compat)
204{
205 int node;
206
207 node = fdt_node_offset_by_compatible(fdt, offset, compat);
208 if (node < 0) {
209 return -FDT_ERR_NOTFOUND;
210 }
211
212 dt_fill_device_info(info, node);
213
214 return node;
215}
216
217/*******************************************************************************
218 * This function gets the UART instance info of stdout from the DT.
Yann Gautier038bff22019-01-17 19:17:47 +0100219 * Returns node on success and a negative FDT error code on failure.
Yann Gautier69035a82018-07-05 16:48:16 +0200220 ******************************************************************************/
221int dt_get_stdout_uart_info(struct dt_node_info *info)
222{
223 int node;
224
225 node = dt_get_stdout_node_offset();
226 if (node < 0) {
227 return -FDT_ERR_NOTFOUND;
228 }
229
230 dt_fill_device_info(info, node);
231
232 return node;
233}
234
235/*******************************************************************************
236 * This function gets the stdout path node.
237 * It reads the value indicated inside the device tree.
238 * Returns node if success, and a negative value else.
239 ******************************************************************************/
240int dt_get_stdout_node_offset(void)
241{
242 int node;
243 const char *cchar;
244
245 node = fdt_path_offset(fdt, "/chosen");
246 if (node < 0) {
247 return -FDT_ERR_NOTFOUND;
248 }
249
250 cchar = fdt_getprop(fdt, node, "stdout-path", NULL);
251 if (cchar == NULL) {
252 return -FDT_ERR_NOTFOUND;
253 }
254
255 node = -FDT_ERR_NOTFOUND;
256 if (strchr(cchar, (int)':') != NULL) {
257 const char *name;
258 char *str = (char *)cchar;
259 int len = 0;
260
261 while (strncmp(":", str, 1)) {
262 len++;
263 str++;
264 }
265
266 name = fdt_get_alias_namelen(fdt, cchar, len);
267
268 if (name != NULL) {
269 node = fdt_path_offset(fdt, name);
270 }
271 } else {
272 node = fdt_path_offset(fdt, cchar);
273 }
274
275 return node;
276}
277
278/*******************************************************************************
Yann Gautiercaf575b2018-07-24 17:18:19 +0200279 * This function gets DDR size information from the DT.
Yann Gautier038bff22019-01-17 19:17:47 +0100280 * Returns value in bytes on success, and 0 on failure.
Yann Gautiercaf575b2018-07-24 17:18:19 +0200281 ******************************************************************************/
282uint32_t dt_get_ddr_size(void)
283{
284 int node;
285
286 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
287 if (node < 0) {
288 INFO("%s: Cannot read DDR node in DT\n", __func__);
Yann Gautier038bff22019-01-17 19:17:47 +0100289 return 0;
Yann Gautiercaf575b2018-07-24 17:18:19 +0200290 }
291
Yann Gautier038bff22019-01-17 19:17:47 +0100292 return fdt_read_uint32_default(node, "st,mem-size", 0);
Yann Gautiercaf575b2018-07-24 17:18:19 +0200293}
294
295/*******************************************************************************
Yann Gautier69035a82018-07-05 16:48:16 +0200296 * This function retrieves board model from DT
297 * Returns string taken from model node, NULL otherwise
298 ******************************************************************************/
299const char *dt_get_board_model(void)
300{
301 int node = fdt_path_offset(fdt, "/");
302
303 if (node < 0) {
304 return NULL;
305 }
306
307 return (const char *)fdt_getprop(fdt, node, "model", NULL);
308}