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_clk.h> 17 #include <drivers/st/stm32mp1_ddr.h> 18 #include <drivers/st/stm32mp1_ram.h> 19 20 #include <stm32mp_dt.h> 21 22 static int fdt_checked; 23 24 static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE; 25 26 /******************************************************************************* 27 * This function checks device tree file with its header. 28 * Returns 0 on success and a negative FDT error code on failure. 29 ******************************************************************************/ 30 int 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 ******************************************************************************/ 46 int 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). 57 * Returns true if present, else return false. 58 ******************************************************************************/ 59 bool 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 /******************************************************************************* 70 * This function return global node status (generic use of fdt library). 71 ******************************************************************************/ 72 uint8_t fdt_get_status(int node) 73 { 74 uint8_t status = DT_DISABLED; 75 int len; 76 const char *cchar; 77 78 cchar = fdt_getprop(fdt, node, "status", &len); 79 if ((cchar == NULL) || 80 (strncmp(cchar, "okay", (size_t)len) == 0)) { 81 status |= DT_NON_SECURE; 82 } 83 84 cchar = fdt_getprop(fdt, node, "secure-status", &len); 85 if (cchar == NULL) { 86 if (status == DT_NON_SECURE) { 87 status |= DT_SECURE; 88 } 89 } else if (strncmp(cchar, "okay", (size_t)len) == 0) { 90 status |= DT_SECURE; 91 } 92 93 return status; 94 } 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 ******************************************************************************/ 102 uint32_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. 121 * Returns 0 on success and a negative FDT error code on failure. 122 * If success, values are stored at the third parameter address. 123 ******************************************************************************/ 124 int 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 } 148 149 /******************************************************************************* 150 * 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. 152 * Returns 0 on success and a negative FDT error code on failure. 153 ******************************************************************************/ 154 int 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 ******************************************************************************/ 169 void 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 196 info->status = fdt_get_status(node); 197 } 198 199 /******************************************************************************* 200 * This function retrieve the generic information from DT. 201 * Returns node on success and a negative FDT error code on failure. 202 ******************************************************************************/ 203 int 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. 219 * Returns node on success and a negative FDT error code on failure. 220 ******************************************************************************/ 221 int 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 ******************************************************************************/ 240 int 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 /******************************************************************************* 279 * This function gets DDR size information from the DT. 280 * Returns value in bytes on success, and 0 on failure. 281 ******************************************************************************/ 282 uint32_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__); 289 return 0; 290 } 291 292 return fdt_read_uint32_default(node, "st,mem-size", 0); 293 } 294 295 /******************************************************************************* 296 * This function retrieves board model from DT 297 * Returns string taken from model node, NULL otherwise 298 ******************************************************************************/ 299 const 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 } 309