1 /* 2 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 10 #include <libfdt.h> 11 12 #include <platform_def.h> 13 14 #include <common/debug.h> 15 #include <drivers/st/stm32_gpio.h> 16 #include <drivers/st/stm32mp1_ddr.h> 17 #include <drivers/st/stm32mp1_ram.h> 18 19 #include <stm32mp_dt.h> 20 21 static int fdt_checked; 22 23 static void *fdt = (void *)(uintptr_t)STM32MP_DTB_BASE; 24 25 /******************************************************************************* 26 * This function checks device tree file with its header. 27 * Returns 0 on success and a negative FDT error code on failure. 28 ******************************************************************************/ 29 int dt_open_and_check(void) 30 { 31 int ret = fdt_check_header(fdt); 32 33 if (ret == 0) { 34 fdt_checked = 1; 35 } 36 37 return ret; 38 } 39 40 /******************************************************************************* 41 * This function gets the address of the DT. 42 * If DT is OK, fdt_addr is filled with DT address. 43 * Returns 1 if success, 0 otherwise. 44 ******************************************************************************/ 45 int fdt_get_address(void **fdt_addr) 46 { 47 if (fdt_checked == 1) { 48 *fdt_addr = fdt; 49 } 50 51 return fdt_checked; 52 } 53 54 /******************************************************************************* 55 * This function check the presence of a node (generic use of fdt library). 56 * Returns true if present, else return false. 57 ******************************************************************************/ 58 bool fdt_check_node(int node) 59 { 60 int len; 61 const char *cchar; 62 63 cchar = fdt_get_name(fdt, node, &len); 64 65 return (cchar != NULL) && (len >= 0); 66 } 67 68 /******************************************************************************* 69 * This function return global node status (generic use of fdt library). 70 ******************************************************************************/ 71 uint8_t fdt_get_status(int node) 72 { 73 uint8_t status = DT_DISABLED; 74 int len; 75 const char *cchar; 76 77 cchar = fdt_getprop(fdt, node, "status", &len); 78 if ((cchar == NULL) || 79 (strncmp(cchar, "okay", (size_t)len) == 0)) { 80 status |= DT_NON_SECURE; 81 } 82 83 cchar = fdt_getprop(fdt, node, "secure-status", &len); 84 if (cchar == NULL) { 85 if (status == DT_NON_SECURE) { 86 status |= DT_SECURE; 87 } 88 } else if (strncmp(cchar, "okay", (size_t)len) == 0) { 89 status |= DT_SECURE; 90 } 91 92 return status; 93 } 94 95 /******************************************************************************* 96 * This function reads a value of a node property (generic use of fdt 97 * library). 98 * Returns value if success, and a default value if property not found. 99 * Default value is passed as parameter. 100 ******************************************************************************/ 101 uint32_t fdt_read_uint32_default(int node, const char *prop_name, 102 uint32_t dflt_value) 103 { 104 const fdt32_t *cuint; 105 int lenp; 106 107 cuint = fdt_getprop(fdt, node, prop_name, &lenp); 108 if (cuint == NULL) { 109 return dflt_value; 110 } 111 112 return fdt32_to_cpu(*cuint); 113 } 114 115 /******************************************************************************* 116 * This function reads a series of parameters in a node property 117 * (generic use of fdt library). 118 * It reads the values inside the device tree, from property name and node. 119 * The number of parameters is also indicated as entry parameter. 120 * Returns 0 on success and a negative FDT error code on failure. 121 * If success, values are stored at the third parameter address. 122 ******************************************************************************/ 123 int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, 124 uint32_t count) 125 { 126 const fdt32_t *cuint; 127 int len; 128 uint32_t i; 129 130 cuint = fdt_getprop(fdt, node, prop_name, &len); 131 if (cuint == NULL) { 132 return -FDT_ERR_NOTFOUND; 133 } 134 135 if ((uint32_t)len != (count * sizeof(uint32_t))) { 136 return -FDT_ERR_BADLAYOUT; 137 } 138 139 for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { 140 *array = fdt32_to_cpu(*cuint); 141 array++; 142 cuint++; 143 } 144 145 return 0; 146 } 147 148 /******************************************************************************* 149 * This function gets the stdout pin configuration information from the DT. 150 * And then calls the sub-function to treat it and set GPIO registers. 151 * Returns 0 on success and a negative FDT error code on failure. 152 ******************************************************************************/ 153 int dt_set_stdout_pinctrl(void) 154 { 155 int node; 156 157 node = dt_get_stdout_node_offset(); 158 if (node < 0) { 159 return -FDT_ERR_NOTFOUND; 160 } 161 162 return dt_set_pinctrl_config(node); 163 } 164 165 /******************************************************************************* 166 * This function fills the generic information from a given node. 167 ******************************************************************************/ 168 void dt_fill_device_info(struct dt_node_info *info, int node) 169 { 170 const fdt32_t *cuint; 171 172 cuint = fdt_getprop(fdt, node, "reg", NULL); 173 if (cuint != NULL) { 174 info->base = fdt32_to_cpu(*cuint); 175 } else { 176 info->base = 0; 177 } 178 179 cuint = fdt_getprop(fdt, node, "clocks", NULL); 180 if (cuint != NULL) { 181 cuint++; 182 info->clock = (int)fdt32_to_cpu(*cuint); 183 } else { 184 info->clock = -1; 185 } 186 187 cuint = fdt_getprop(fdt, node, "resets", NULL); 188 if (cuint != NULL) { 189 cuint++; 190 info->reset = (int)fdt32_to_cpu(*cuint); 191 } else { 192 info->reset = -1; 193 } 194 195 info->status = fdt_get_status(node); 196 } 197 198 /******************************************************************************* 199 * This function retrieve the generic information from DT. 200 * Returns node on success and a negative FDT error code on failure. 201 ******************************************************************************/ 202 int dt_get_node(struct dt_node_info *info, int offset, const char *compat) 203 { 204 int node; 205 206 node = fdt_node_offset_by_compatible(fdt, offset, compat); 207 if (node < 0) { 208 return -FDT_ERR_NOTFOUND; 209 } 210 211 dt_fill_device_info(info, node); 212 213 return node; 214 } 215 216 /******************************************************************************* 217 * This function gets the UART instance info of stdout from the DT. 218 * Returns node on success and a negative FDT error code on failure. 219 ******************************************************************************/ 220 int dt_get_stdout_uart_info(struct dt_node_info *info) 221 { 222 int node; 223 224 node = dt_get_stdout_node_offset(); 225 if (node < 0) { 226 return -FDT_ERR_NOTFOUND; 227 } 228 229 dt_fill_device_info(info, node); 230 231 return node; 232 } 233 234 /******************************************************************************* 235 * This function gets the stdout path node. 236 * It reads the value indicated inside the device tree. 237 * Returns node if success, and a negative value else. 238 ******************************************************************************/ 239 int dt_get_stdout_node_offset(void) 240 { 241 int node; 242 const char *cchar; 243 244 node = fdt_path_offset(fdt, "/chosen"); 245 if (node < 0) { 246 return -FDT_ERR_NOTFOUND; 247 } 248 249 cchar = fdt_getprop(fdt, node, "stdout-path", NULL); 250 if (cchar == NULL) { 251 return -FDT_ERR_NOTFOUND; 252 } 253 254 node = -FDT_ERR_NOTFOUND; 255 if (strchr(cchar, (int)':') != NULL) { 256 const char *name; 257 char *str = (char *)cchar; 258 int len = 0; 259 260 while (strncmp(":", str, 1)) { 261 len++; 262 str++; 263 } 264 265 name = fdt_get_alias_namelen(fdt, cchar, len); 266 267 if (name != NULL) { 268 node = fdt_path_offset(fdt, name); 269 } 270 } else { 271 node = fdt_path_offset(fdt, cchar); 272 } 273 274 return node; 275 } 276 277 /******************************************************************************* 278 * This function gets DDR size information from the DT. 279 * Returns value in bytes on success, and 0 on failure. 280 ******************************************************************************/ 281 uint32_t dt_get_ddr_size(void) 282 { 283 int node; 284 285 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); 286 if (node < 0) { 287 INFO("%s: Cannot read DDR node in DT\n", __func__); 288 return 0; 289 } 290 291 return fdt_read_uint32_default(node, "st,mem-size", 0); 292 } 293 294 /******************************************************************************* 295 * This function gets DDRCTRL base address information from the DT. 296 * Returns value on success, and 0 on failure. 297 ******************************************************************************/ 298 uintptr_t dt_get_ddrctrl_base(void) 299 { 300 int node; 301 uint32_t array[4]; 302 303 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); 304 if (node < 0) { 305 INFO("%s: Cannot read DDR node in DT\n", __func__); 306 return 0; 307 } 308 309 if (fdt_read_uint32_array(node, "reg", array, 4) < 0) { 310 return 0; 311 } 312 313 return array[0]; 314 } 315 316 /******************************************************************************* 317 * This function gets DDRPHYC base address information from the DT. 318 * Returns value on success, and 0 on failure. 319 ******************************************************************************/ 320 uintptr_t dt_get_ddrphyc_base(void) 321 { 322 int node; 323 uint32_t array[4]; 324 325 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); 326 if (node < 0) { 327 INFO("%s: Cannot read DDR node in DT\n", __func__); 328 return 0; 329 } 330 331 if (fdt_read_uint32_array(node, "reg", array, 4) < 0) { 332 return 0; 333 } 334 335 return array[2]; 336 } 337 338 /******************************************************************************* 339 * This function gets PWR base address information from the DT. 340 * Returns value on success, and 0 on failure. 341 ******************************************************************************/ 342 uintptr_t dt_get_pwr_base(void) 343 { 344 int node; 345 const fdt32_t *cuint; 346 347 node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); 348 if (node < 0) { 349 INFO("%s: Cannot read PWR node in DT\n", __func__); 350 return 0; 351 } 352 353 cuint = fdt_getprop(fdt, node, "reg", NULL); 354 if (cuint == NULL) { 355 return 0; 356 } 357 358 return fdt32_to_cpu(*cuint); 359 } 360 361 /******************************************************************************* 362 * This function retrieves board model from DT 363 * Returns string taken from model node, NULL otherwise 364 ******************************************************************************/ 365 const char *dt_get_board_model(void) 366 { 367 int node = fdt_path_offset(fdt, "/"); 368 369 if (node < 0) { 370 return NULL; 371 } 372 373 return (const char *)fdt_getprop(fdt, node, "model", NULL); 374 } 375