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