11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2a4f139d7SJerome Forissier /* 3a4f139d7SJerome Forissier * Copyright (c) 2016, Linaro Limited 4a4f139d7SJerome Forissier */ 5a4f139d7SJerome Forissier 67ba16abbSJerome Forissier #include <assert.h> 7a4f139d7SJerome Forissier #include <kernel/dt.h> 89e3c57c8SEtienne Carriere #include <kernel/dt_driver.h> 97acb3a47SLudovic Barre #include <kernel/interrupt.h> 10bce4951cSJens Wiklander #include <kernel/linker.h> 119fe4c797SJerome Forissier #include <libfdt.h> 127ba16abbSJerome Forissier #include <mm/core_memprot.h> 137ba16abbSJerome Forissier #include <mm/core_mmu.h> 14a4f139d7SJerome Forissier #include <string.h> 157ba16abbSJerome Forissier #include <trace.h> 16a4f139d7SJerome Forissier 17a4f139d7SJerome Forissier const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs) 18a4f139d7SJerome Forissier { 19a4f139d7SJerome Forissier const struct dt_device_match *dm; 20a4f139d7SJerome Forissier const struct dt_driver *drv; 21a4f139d7SJerome Forissier 22db783ff8SEtienne Carriere for_each_dt_driver(drv) { 23db783ff8SEtienne Carriere for (dm = drv->match_table; dm; dm++) { 24db783ff8SEtienne Carriere if (!dm->compatible) { 25db783ff8SEtienne Carriere break; 26db783ff8SEtienne Carriere } 27a4f139d7SJerome Forissier if (!fdt_node_check_compatible(fdt, offs, 28db783ff8SEtienne Carriere dm->compatible)) { 29a4f139d7SJerome Forissier return drv; 30db783ff8SEtienne Carriere } 31db783ff8SEtienne Carriere } 32db783ff8SEtienne Carriere } 33a4f139d7SJerome Forissier 34a4f139d7SJerome Forissier return NULL; 35a4f139d7SJerome Forissier } 36a4f139d7SJerome Forissier 3750f3b323SPeng Fan bool dt_have_prop(const void *fdt, int offs, const char *propname) 3850f3b323SPeng Fan { 3950f3b323SPeng Fan const void *prop; 4050f3b323SPeng Fan 4150f3b323SPeng Fan prop = fdt_getprop(fdt, offs, propname, NULL); 4250f3b323SPeng Fan 4350f3b323SPeng Fan return prop; 4450f3b323SPeng Fan } 4550f3b323SPeng Fan 4695cdc5e0SCedric Neveux int dt_disable_status(void *fdt, int node) 4795cdc5e0SCedric Neveux { 4895cdc5e0SCedric Neveux const char *prop = NULL; 4995cdc5e0SCedric Neveux int len = 0; 5095cdc5e0SCedric Neveux 5195cdc5e0SCedric Neveux prop = fdt_getprop(fdt, node, "status", &len); 5295cdc5e0SCedric Neveux if (!prop) { 5395cdc5e0SCedric Neveux if (fdt_setprop_string(fdt, node, "status", "disabled")) 5495cdc5e0SCedric Neveux return -1; 5595cdc5e0SCedric Neveux } else { 5695cdc5e0SCedric Neveux /* 5795cdc5e0SCedric Neveux * Status is there, modify it. 5895cdc5e0SCedric Neveux * Ask to set "disabled" value to the property. The value 5995cdc5e0SCedric Neveux * will be automatically truncated with "len" size by the 6095cdc5e0SCedric Neveux * fdt_setprop_inplace function. 6195cdc5e0SCedric Neveux * Setting a value different from "ok" or "okay" will disable 6295cdc5e0SCedric Neveux * the property. 6395cdc5e0SCedric Neveux * Setting a truncated value of "disabled" with the original 6495cdc5e0SCedric Neveux * property "len" is preferred to not increase the DT size and 6595cdc5e0SCedric Neveux * losing time in recalculating the overall DT offsets. 6695cdc5e0SCedric Neveux * If original length of the status property is larger than 6795cdc5e0SCedric Neveux * "disabled", the property will start with "disabled" and be 6895cdc5e0SCedric Neveux * completed with the rest of the original property. 6995cdc5e0SCedric Neveux */ 7095cdc5e0SCedric Neveux if (fdt_setprop_inplace(fdt, node, "status", "disabled", len)) 7195cdc5e0SCedric Neveux return -1; 7295cdc5e0SCedric Neveux } 7395cdc5e0SCedric Neveux 7495cdc5e0SCedric Neveux return 0; 7595cdc5e0SCedric Neveux } 7695cdc5e0SCedric Neveux 7795cdc5e0SCedric Neveux int dt_enable_secure_status(void *fdt, int node) 7895cdc5e0SCedric Neveux { 7995cdc5e0SCedric Neveux if (dt_disable_status(fdt, node)) { 8095cdc5e0SCedric Neveux EMSG("Unable to disable Normal Status"); 8195cdc5e0SCedric Neveux return -1; 8295cdc5e0SCedric Neveux } 8395cdc5e0SCedric Neveux 8495cdc5e0SCedric Neveux if (fdt_setprop_string(fdt, node, "secure-status", "okay")) 8595cdc5e0SCedric Neveux return -1; 8695cdc5e0SCedric Neveux 8795cdc5e0SCedric Neveux return 0; 8895cdc5e0SCedric Neveux } 8995cdc5e0SCedric Neveux 90a5d5bbc8SVesa Jääskeläinen int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, 91a5d5bbc8SVesa Jääskeläinen enum dt_map_dev_directive mapping) 927ba16abbSJerome Forissier { 937ba16abbSJerome Forissier enum teecore_memtypes mtype; 947ba16abbSJerome Forissier paddr_t pbase; 957ba16abbSJerome Forissier vaddr_t vbase; 96df7cecc0SLionel Debieve size_t sz; 977ba16abbSJerome Forissier int st; 987ba16abbSJerome Forissier 997ba16abbSJerome Forissier assert(cpu_mmu_enabled()); 1007ba16abbSJerome Forissier 101f354a5d8SGatien Chevallier st = fdt_get_status(fdt, offs); 1027ba16abbSJerome Forissier if (st == DT_STATUS_DISABLED) 1037ba16abbSJerome Forissier return -1; 1047ba16abbSJerome Forissier 105f354a5d8SGatien Chevallier pbase = fdt_reg_base_address(fdt, offs); 106c0cfb36cSEtienne Carriere if (pbase == DT_INFO_INVALID_REG) 1077ba16abbSJerome Forissier return -1; 108f354a5d8SGatien Chevallier sz = fdt_reg_size(fdt, offs); 109df7cecc0SLionel Debieve if (sz == DT_INFO_INVALID_REG_SIZE) 1107ba16abbSJerome Forissier return -1; 1117ba16abbSJerome Forissier 112a5d5bbc8SVesa Jääskeläinen switch (mapping) { 113a5d5bbc8SVesa Jääskeläinen case DT_MAP_AUTO: 1147ba16abbSJerome Forissier if ((st & DT_STATUS_OK_SEC) && !(st & DT_STATUS_OK_NSEC)) 1157ba16abbSJerome Forissier mtype = MEM_AREA_IO_SEC; 1167ba16abbSJerome Forissier else 1177ba16abbSJerome Forissier mtype = MEM_AREA_IO_NSEC; 118a5d5bbc8SVesa Jääskeläinen break; 119a5d5bbc8SVesa Jääskeläinen case DT_MAP_SECURE: 120a5d5bbc8SVesa Jääskeläinen mtype = MEM_AREA_IO_SEC; 121a5d5bbc8SVesa Jääskeläinen break; 122a5d5bbc8SVesa Jääskeläinen case DT_MAP_NON_SECURE: 123a5d5bbc8SVesa Jääskeläinen mtype = MEM_AREA_IO_NSEC; 124a5d5bbc8SVesa Jääskeläinen break; 125a5d5bbc8SVesa Jääskeläinen default: 126a5d5bbc8SVesa Jääskeläinen panic("Invalid mapping specified"); 127a5d5bbc8SVesa Jääskeläinen break; 128a5d5bbc8SVesa Jääskeläinen } 1297ba16abbSJerome Forissier 1307ba16abbSJerome Forissier /* Check if we have a mapping, create one if needed */ 131bc9618c0SAnton Rybakov vbase = (vaddr_t)core_mmu_add_mapping(mtype, pbase, sz); 132bc9618c0SAnton Rybakov if (!vbase) { 1337ba16abbSJerome Forissier EMSG("Failed to map %zu bytes at PA 0x%"PRIxPA, 13423b1daf4SPeng Fan (size_t)sz, pbase); 1357ba16abbSJerome Forissier return -1; 1367ba16abbSJerome Forissier } 1377ba16abbSJerome Forissier 1387ba16abbSJerome Forissier *base = vbase; 1397ba16abbSJerome Forissier *size = sz; 1407ba16abbSJerome Forissier return 0; 1417ba16abbSJerome Forissier } 1427ba16abbSJerome Forissier 1439fe4c797SJerome Forissier /* Read a physical address (n=1 or 2 cells) */ 144f354a5d8SGatien Chevallier static paddr_t fdt_read_paddr(const uint32_t *cell, int n) 1459fe4c797SJerome Forissier { 1469fe4c797SJerome Forissier paddr_t addr; 1479fe4c797SJerome Forissier 1489fe4c797SJerome Forissier if (n < 1 || n > 2) 1499fe4c797SJerome Forissier goto bad; 1509fe4c797SJerome Forissier 1519fe4c797SJerome Forissier addr = fdt32_to_cpu(*cell); 1529fe4c797SJerome Forissier cell++; 1539fe4c797SJerome Forissier if (n == 2) { 1549fe4c797SJerome Forissier #ifdef ARM32 1559fe4c797SJerome Forissier if (addr) { 1569fe4c797SJerome Forissier /* High order 32 bits can't be nonzero */ 1579fe4c797SJerome Forissier goto bad; 1589fe4c797SJerome Forissier } 1599fe4c797SJerome Forissier addr = fdt32_to_cpu(*cell); 1609fe4c797SJerome Forissier #else 1619fe4c797SJerome Forissier addr = (addr << 32) | fdt32_to_cpu(*cell); 1629fe4c797SJerome Forissier #endif 1639fe4c797SJerome Forissier } 1649fe4c797SJerome Forissier 1659fe4c797SJerome Forissier return addr; 1669fe4c797SJerome Forissier bad: 167c0cfb36cSEtienne Carriere return DT_INFO_INVALID_REG; 1689fe4c797SJerome Forissier 1699fe4c797SJerome Forissier } 1709fe4c797SJerome Forissier 171f354a5d8SGatien Chevallier paddr_t fdt_reg_base_address(const void *fdt, int offs) 1729fe4c797SJerome Forissier { 1739fe4c797SJerome Forissier const void *reg; 1749fe4c797SJerome Forissier int ncells; 1759fe4c797SJerome Forissier int len; 17634deb103SPeng Fan int parent; 17734deb103SPeng Fan 17834deb103SPeng Fan parent = fdt_parent_offset(fdt, offs); 17934deb103SPeng Fan if (parent < 0) 180c0cfb36cSEtienne Carriere return DT_INFO_INVALID_REG; 1819fe4c797SJerome Forissier 1829fe4c797SJerome Forissier reg = fdt_getprop(fdt, offs, "reg", &len); 1839fe4c797SJerome Forissier if (!reg) 184c0cfb36cSEtienne Carriere return DT_INFO_INVALID_REG; 1859fe4c797SJerome Forissier 18634deb103SPeng Fan ncells = fdt_address_cells(fdt, parent); 1879fe4c797SJerome Forissier if (ncells < 0) 188c0cfb36cSEtienne Carriere return DT_INFO_INVALID_REG; 1899fe4c797SJerome Forissier 190f354a5d8SGatien Chevallier return fdt_read_paddr(reg, ncells); 1919fe4c797SJerome Forissier } 1929fe4c797SJerome Forissier 193a2e8c036SGatien Chevallier static size_t fdt_read_size(const uint32_t *cell, int n) 194a2e8c036SGatien Chevallier { 195a2e8c036SGatien Chevallier uint32_t sz = 0; 196a2e8c036SGatien Chevallier 197a2e8c036SGatien Chevallier sz = fdt32_to_cpu(*cell); 198a2e8c036SGatien Chevallier if (n == 2) { 199a2e8c036SGatien Chevallier if (sz) 200a2e8c036SGatien Chevallier return DT_INFO_INVALID_REG_SIZE; 201a2e8c036SGatien Chevallier 202a2e8c036SGatien Chevallier cell++; 203a2e8c036SGatien Chevallier sz = fdt32_to_cpu(*cell); 204a2e8c036SGatien Chevallier } 205a2e8c036SGatien Chevallier 206a2e8c036SGatien Chevallier return sz; 207a2e8c036SGatien Chevallier } 208a2e8c036SGatien Chevallier 209f354a5d8SGatien Chevallier size_t fdt_reg_size(const void *fdt, int offs) 2109fe4c797SJerome Forissier { 2119fe4c797SJerome Forissier const uint32_t *reg; 2129fe4c797SJerome Forissier int n; 2139fe4c797SJerome Forissier int len; 21434deb103SPeng Fan int parent; 21534deb103SPeng Fan 21634deb103SPeng Fan parent = fdt_parent_offset(fdt, offs); 21734deb103SPeng Fan if (parent < 0) 2181527e616SMarek Vasut return DT_INFO_INVALID_REG_SIZE; 2199fe4c797SJerome Forissier 2209fe4c797SJerome Forissier reg = (const uint32_t *)fdt_getprop(fdt, offs, "reg", &len); 2219fe4c797SJerome Forissier if (!reg) 222df7cecc0SLionel Debieve return DT_INFO_INVALID_REG_SIZE; 2239fe4c797SJerome Forissier 22434deb103SPeng Fan n = fdt_address_cells(fdt, parent); 2259fe4c797SJerome Forissier if (n < 1 || n > 2) 226df7cecc0SLionel Debieve return DT_INFO_INVALID_REG_SIZE; 2279fe4c797SJerome Forissier 2289fe4c797SJerome Forissier reg += n; 2299fe4c797SJerome Forissier 23034deb103SPeng Fan n = fdt_size_cells(fdt, parent); 2319fe4c797SJerome Forissier if (n < 1 || n > 2) 232df7cecc0SLionel Debieve return DT_INFO_INVALID_REG_SIZE; 2339fe4c797SJerome Forissier 234a2e8c036SGatien Chevallier return fdt_read_size(reg, n); 2359fe4c797SJerome Forissier } 2369fe4c797SJerome Forissier 2379fe4c797SJerome Forissier static bool is_okay(const char *st, int len) 2389fe4c797SJerome Forissier { 2399fe4c797SJerome Forissier return !strncmp(st, "ok", len) || !strncmp(st, "okay", len); 2409fe4c797SJerome Forissier } 2419fe4c797SJerome Forissier 242f354a5d8SGatien Chevallier int fdt_get_status(const void *fdt, int offs) 2439fe4c797SJerome Forissier { 2449fe4c797SJerome Forissier const char *prop; 2459fe4c797SJerome Forissier int st = 0; 2469fe4c797SJerome Forissier int len; 2479fe4c797SJerome Forissier 2489fe4c797SJerome Forissier prop = fdt_getprop(fdt, offs, "status", &len); 2499fe4c797SJerome Forissier if (!prop || is_okay(prop, len)) { 2509fe4c797SJerome Forissier /* If status is not specified, it defaults to "okay" */ 2519fe4c797SJerome Forissier st |= DT_STATUS_OK_NSEC; 2529fe4c797SJerome Forissier } 2539fe4c797SJerome Forissier 2549fe4c797SJerome Forissier prop = fdt_getprop(fdt, offs, "secure-status", &len); 2559fe4c797SJerome Forissier if (!prop) { 2569fe4c797SJerome Forissier /* 2579fe4c797SJerome Forissier * When secure-status is not specified it defaults to the same 2589fe4c797SJerome Forissier * value as status 2599fe4c797SJerome Forissier */ 2609fe4c797SJerome Forissier if (st & DT_STATUS_OK_NSEC) 2619fe4c797SJerome Forissier st |= DT_STATUS_OK_SEC; 2629fe4c797SJerome Forissier } else { 2639fe4c797SJerome Forissier if (is_okay(prop, len)) 2649fe4c797SJerome Forissier st |= DT_STATUS_OK_SEC; 2659fe4c797SJerome Forissier } 2669fe4c797SJerome Forissier 2679fe4c797SJerome Forissier return st; 2689fe4c797SJerome Forissier } 269c0cfb36cSEtienne Carriere 270f354a5d8SGatien Chevallier void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, int offs) 271c0cfb36cSEtienne Carriere { 272c0cfb36cSEtienne Carriere struct dt_node_info dinfo = { 273c0cfb36cSEtienne Carriere .reg = DT_INFO_INVALID_REG, 27406fd21ddSLionel Debieve .reg_size = DT_INFO_INVALID_REG_SIZE, 275c0cfb36cSEtienne Carriere .clock = DT_INFO_INVALID_CLOCK, 276c0cfb36cSEtienne Carriere .reset = DT_INFO_INVALID_RESET, 2777acb3a47SLudovic Barre .interrupt = DT_INFO_INVALID_INTERRUPT, 278c0cfb36cSEtienne Carriere }; 279c0cfb36cSEtienne Carriere const fdt32_t *cuint; 280c0cfb36cSEtienne Carriere 281f354a5d8SGatien Chevallier dinfo.reg = fdt_reg_base_address(fdt, offs); 282f354a5d8SGatien Chevallier dinfo.reg_size = fdt_reg_size(fdt, offs); 283c0cfb36cSEtienne Carriere 284c0cfb36cSEtienne Carriere cuint = fdt_getprop(fdt, offs, "clocks", NULL); 285c0cfb36cSEtienne Carriere if (cuint) { 286c0cfb36cSEtienne Carriere cuint++; 287c0cfb36cSEtienne Carriere dinfo.clock = (int)fdt32_to_cpu(*cuint); 288c0cfb36cSEtienne Carriere } 289c0cfb36cSEtienne Carriere 290c0cfb36cSEtienne Carriere cuint = fdt_getprop(fdt, offs, "resets", NULL); 291c0cfb36cSEtienne Carriere if (cuint) { 292c0cfb36cSEtienne Carriere cuint++; 293c0cfb36cSEtienne Carriere dinfo.reset = (int)fdt32_to_cpu(*cuint); 294c0cfb36cSEtienne Carriere } 295c0cfb36cSEtienne Carriere 296702fe5a7SClément Léger dinfo.interrupt = dt_get_irq_type_prio(fdt, offs, &dinfo.type, 297702fe5a7SClément Léger &dinfo.prio); 2987acb3a47SLudovic Barre 299f354a5d8SGatien Chevallier dinfo.status = fdt_get_status(fdt, offs); 300c0cfb36cSEtienne Carriere 301c0cfb36cSEtienne Carriere *info = dinfo; 302c0cfb36cSEtienne Carriere } 303876826f3SGabriel Fernandez 304f354a5d8SGatien Chevallier int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, 305876826f3SGabriel Fernandez uint32_t *array, size_t count) 306876826f3SGabriel Fernandez { 307876826f3SGabriel Fernandez const fdt32_t *cuint = NULL; 308876826f3SGabriel Fernandez int len = 0; 309876826f3SGabriel Fernandez uint32_t i = 0; 310876826f3SGabriel Fernandez 311876826f3SGabriel Fernandez cuint = fdt_getprop(fdt, node, prop_name, &len); 312876826f3SGabriel Fernandez if (!cuint) 31373e27bfaSGatien Chevallier return len; 314876826f3SGabriel Fernandez 315876826f3SGabriel Fernandez if ((uint32_t)len != (count * sizeof(uint32_t))) 316876826f3SGabriel Fernandez return -FDT_ERR_BADLAYOUT; 317876826f3SGabriel Fernandez 318876826f3SGabriel Fernandez for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { 319876826f3SGabriel Fernandez *array = fdt32_to_cpu(*cuint); 320876826f3SGabriel Fernandez array++; 321876826f3SGabriel Fernandez cuint++; 322876826f3SGabriel Fernandez } 323876826f3SGabriel Fernandez 324876826f3SGabriel Fernandez return 0; 325876826f3SGabriel Fernandez } 326876826f3SGabriel Fernandez 3277c3a6b7bSGatien Chevallier int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, 3287c3a6b7bSGatien Chevallier int index, uint32_t *value) 3297c3a6b7bSGatien Chevallier { 3307c3a6b7bSGatien Chevallier const fdt32_t *cuint = NULL; 3317c3a6b7bSGatien Chevallier int len = 0; 3327c3a6b7bSGatien Chevallier 3337c3a6b7bSGatien Chevallier cuint = fdt_getprop(fdt, node, prop_name, &len); 3347c3a6b7bSGatien Chevallier if (!cuint) 3357c3a6b7bSGatien Chevallier return len; 3367c3a6b7bSGatien Chevallier 3377c3a6b7bSGatien Chevallier if ((uint32_t)len < (sizeof(uint32_t) * (index + 1))) 3387c3a6b7bSGatien Chevallier return -FDT_ERR_BADLAYOUT; 3397c3a6b7bSGatien Chevallier 3407c3a6b7bSGatien Chevallier *value = fdt32_to_cpu(cuint[index]); 3417c3a6b7bSGatien Chevallier 3427c3a6b7bSGatien Chevallier return 0; 3437c3a6b7bSGatien Chevallier } 3447c3a6b7bSGatien Chevallier 345f354a5d8SGatien Chevallier int fdt_read_uint32(const void *fdt, int node, const char *prop_name, 346876826f3SGabriel Fernandez uint32_t *value) 347876826f3SGabriel Fernandez { 348f354a5d8SGatien Chevallier return fdt_read_uint32_array(fdt, node, prop_name, value, 1); 349876826f3SGabriel Fernandez } 350876826f3SGabriel Fernandez 351f354a5d8SGatien Chevallier uint32_t fdt_read_uint32_default(const void *fdt, int node, 352876826f3SGabriel Fernandez const char *prop_name, uint32_t dflt_value) 353876826f3SGabriel Fernandez { 3547c3a6b7bSGatien Chevallier uint32_t ret = dflt_value; 355876826f3SGabriel Fernandez 3567c3a6b7bSGatien Chevallier fdt_read_uint32_index(fdt, node, prop_name, 0, &ret); 357876826f3SGabriel Fernandez 3587c3a6b7bSGatien Chevallier return ret; 359876826f3SGabriel Fernandez } 36007ced948SGatien Chevallier 36107ced948SGatien Chevallier int fdt_get_reg_props_by_index(const void *fdt, int node, int index, 36207ced948SGatien Chevallier paddr_t *base, size_t *size) 36307ced948SGatien Chevallier { 36407ced948SGatien Chevallier const fdt32_t *prop = NULL; 36507ced948SGatien Chevallier int parent = 0; 36607ced948SGatien Chevallier int len = 0; 36707ced948SGatien Chevallier int address_cells = 0; 36807ced948SGatien Chevallier int size_cells = 0; 36907ced948SGatien Chevallier int cell = 0; 37007ced948SGatien Chevallier 37107ced948SGatien Chevallier parent = fdt_parent_offset(fdt, node); 37207ced948SGatien Chevallier if (parent < 0) 37307ced948SGatien Chevallier return parent; 37407ced948SGatien Chevallier 37507ced948SGatien Chevallier address_cells = fdt_address_cells(fdt, parent); 37607ced948SGatien Chevallier if (address_cells < 0) 37707ced948SGatien Chevallier return address_cells; 37807ced948SGatien Chevallier 37907ced948SGatien Chevallier size_cells = fdt_size_cells(fdt, parent); 38007ced948SGatien Chevallier if (size_cells < 0) 38107ced948SGatien Chevallier return size_cells; 38207ced948SGatien Chevallier 38307ced948SGatien Chevallier cell = index * (address_cells + size_cells); 38407ced948SGatien Chevallier 38507ced948SGatien Chevallier prop = fdt_getprop(fdt, node, "reg", &len); 38607ced948SGatien Chevallier if (!prop) 38707ced948SGatien Chevallier return len; 38807ced948SGatien Chevallier 38907ced948SGatien Chevallier if (((cell + address_cells + size_cells) * (int)sizeof(uint32_t)) > len) 39007ced948SGatien Chevallier return -FDT_ERR_BADVALUE; 39107ced948SGatien Chevallier 39207ced948SGatien Chevallier if (base) { 39307ced948SGatien Chevallier *base = fdt_read_paddr(&prop[cell], address_cells); 39407ced948SGatien Chevallier if (*base == DT_INFO_INVALID_REG) 39507ced948SGatien Chevallier return -FDT_ERR_BADVALUE; 39607ced948SGatien Chevallier } 39707ced948SGatien Chevallier 39807ced948SGatien Chevallier if (size) { 39907ced948SGatien Chevallier *size = fdt_read_size(&prop[cell + address_cells], size_cells); 40007ced948SGatien Chevallier if (*size == DT_INFO_INVALID_REG_SIZE) 40107ced948SGatien Chevallier return -FDT_ERR_BADVALUE; 40207ced948SGatien Chevallier } 40307ced948SGatien Chevallier 40407ced948SGatien Chevallier return 0; 40507ced948SGatien Chevallier } 40607ced948SGatien Chevallier 40707ced948SGatien Chevallier int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, 40807ced948SGatien Chevallier paddr_t *base, size_t *size) 40907ced948SGatien Chevallier { 41007ced948SGatien Chevallier int index = 0; 41107ced948SGatien Chevallier 41207ced948SGatien Chevallier index = fdt_stringlist_search(fdt, node, "reg-names", name); 41307ced948SGatien Chevallier if (index < 0) 41407ced948SGatien Chevallier return index; 41507ced948SGatien Chevallier 41607ced948SGatien Chevallier return fdt_get_reg_props_by_index(fdt, node, index, base, size); 41707ced948SGatien Chevallier } 418*4e45454aSJens Wiklander 419*4e45454aSJens Wiklander int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name, 420*4e45454aSJens Wiklander uint64_t *num) 421*4e45454aSJens Wiklander { 422*4e45454aSJens Wiklander const void *prop = NULL; 423*4e45454aSJens Wiklander int len = 0; 424*4e45454aSJens Wiklander 425*4e45454aSJens Wiklander prop = fdt_getprop(fdt, nodeoffset, name, &len); 426*4e45454aSJens Wiklander if (!prop) 427*4e45454aSJens Wiklander return len; 428*4e45454aSJens Wiklander 429*4e45454aSJens Wiklander switch (len) { 430*4e45454aSJens Wiklander case sizeof(uint32_t): 431*4e45454aSJens Wiklander *num = fdt32_ld(prop); 432*4e45454aSJens Wiklander return 0; 433*4e45454aSJens Wiklander case sizeof(uint64_t): 434*4e45454aSJens Wiklander *num = fdt64_ld(prop); 435*4e45454aSJens Wiklander return 0; 436*4e45454aSJens Wiklander default: 437*4e45454aSJens Wiklander return -FDT_ERR_BADVALUE; 438*4e45454aSJens Wiklander } 439*4e45454aSJens Wiklander } 440