static int tps65090_decode_config(struct tps65090_config *config) { #ifdef CONFIG_OF_CONTROL const void *blob = gd->fdt_blob; int node, parent; int i2c_bus; node = fdtdec_next_compatible(blob, 0, COMPAT_TI_TPS65090); if (node < 0) { debug("%s: Node not found\n", __func__); return -1; } parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("%s: Cannot find node parent\n", __func__); return -1; } i2c_bus = i2c_get_bus_num_fdt(blob, parent); if (i2c_bus < 0) return -1; config->bus = i2c_bus; config->addr = fdtdec_get_addr(blob, node, "reg"); #else config->bus = CONFIG_TPS65090_I2C_BUS; config->addr = TPS65090_I2C_ADDR; #endif return 0; }
/** * Decode TPM configuration. * * @param dev Returns a configuration of TPM device * @return 0 if ok, -1 on error */ static int tpm_decode_config(struct tpm *dev) { #ifdef CONFIG_OF_CONTROL const void *blob = gd->fdt_blob; int node, parent; int i2c_bus; node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); if (node < 0) { node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9645_TPM); } if (node < 0) { debug("%s: Node not found\n", __func__); return -1; } parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("%s: Cannot find node parent\n", __func__); return -1; } i2c_bus = i2c_get_bus_num_fdt(blob, parent); if (i2c_bus < 0) return -1; dev->i2c_bus = i2c_bus; dev->slave_addr = fdtdec_get_addr(blob, node, "reg"); #else dev->i2c_bus = CONFIG_INFINEON_TPM_I2C_BUS; dev->slave_addr = CONFIG_INFINEON_TPM_I2C_ADDR; #endif return 0; }
int fdtparse_get_interrupt_parent(const void *fdt, int nodeoffset) { int len; const struct fdt_property *interrupt_parent; fdt32_t *cell; uint32_t parent_phandle; int parent_offset; /* Use "interrupt-parent" from node, or node's parent */ do { interrupt_parent = fdt_get_property(fdt, nodeoffset, "interrupt-parent", &len); } while ((len < 0) && (nodeoffset = fdt_parent_offset(fdt, nodeoffset)) >= 0); if (len < 0) { return len; } /* Cell must be big enough to hold phandle */ if (len < sizeof(fdt32_t)) { return -FDT_ERR_BADPHANDLE; } cell = (fdt32_t *) interrupt_parent->data; parent_phandle = fdt32_to_cpu(cell[0]); parent_offset = fdt_node_offset_by_phandle(fdt, parent_phandle); if (parent_offset < 0) { return parent_offset; } return parent_offset; }
static void check_path(struct fdt_header *fdt, const char *path) { char *parentpath; int nodeoffset, parentoffset, parentpathoffset, pathparentlen; pathparentlen = path_parent_len(path); parentpath = alloca(pathparentlen + 1); strncpy(parentpath, path, pathparentlen); parentpath[pathparentlen] = '\0'; verbose_printf("Path: \"%s\"\tParent: \"%s\"\n", path, parentpath); nodeoffset = fdt_path_offset(fdt, path); if (nodeoffset < 0) FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset)); parentpathoffset = fdt_path_offset(fdt, parentpath); if (parentpathoffset < 0) FAIL("fdt_path_offset(%s): %s", parentpath, fdt_strerror(parentpathoffset)); parentoffset = fdt_parent_offset(fdt, nodeoffset); if (parentoffset < 0) FAIL("fdt_parent_offset(): %s", fdt_strerror(parentoffset)); if (parentoffset != parentpathoffset) FAIL("fdt_parent_offset() returns %d instead of %d", parentoffset, parentpathoffset); }
int mkbp_tps65090_init(void) { const void *blob = gd->fdt_blob; int node, parent; node = fdtdec_next_compatible(blob, 0, COMPAT_TI_TPS65090); if (node < 0) { debug("%s: Node not found\n", __func__); return -ENOENT; } parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("%s: Cannot find node parent\n", __func__); return -1; } if (fdt_node_check_compatible(blob, parent, fdtdec_get_compatible(COMPAT_GOOGLE_MKBP))) { debug("%s: TPS65090 not behind MKBP\n", __func__); return -ENOENT; } mkbp_dev = board_get_mkbp_dev(); if (!mkbp_dev) { debug("%s: no mkbp device: cannot init tps65090\n", __func__); return -1; } debug("%s: accessing tps65090 through MKBP\n", __func__); return 0; }
status_t of_get_next_device(int *_cookie, int root, const char *type, char *path, size_t pathSize) { int next; int err; int startoffset = *_cookie ? *_cookie : -1; // iterate by property value next = fdt_node_offset_by_prop_value(gFDT, startoffset, "device_type", type, strlen(type) + 1); TRACE(("of_get_next_device(c:%d, %d, '%s', %p, %zd) soffset=%d next=%d\n", *_cookie, root, type, path, pathSize, startoffset, fdt2of(next))); if (next < 0) return B_ENTRY_NOT_FOUND; // make sure root is the parent int parent = next; while (root && parent) { parent = fdt_parent_offset(gFDT, parent); if (parent == root) break; if (parent <= 0) return B_ENTRY_NOT_FOUND; } *_cookie = next; err = fdt_get_path(gFDT, next, path, pathSize); if (err < 0) return B_ERROR; return B_OK; }
/* Update portal containter to match LAW setup of portal in phy map */ void fdt_portal(void *blob, const char *compat, const char *container, u64 addr, u32 size) { int off; off = fdt_node_offset_by_compatible(blob, -1, compat); if (off < 0) return ; off = fdt_parent_offset(blob, off); /* if non-zero assume we have a container */ if (off > 0) { char buf[60]; const char *p, *name; u32 *range; int len; /* fixup ranges */ range = fdt_getprop_w(blob, off, "ranges", &len); if (range == NULL) { printf("ERROR: container for %s has no ranges", compat); return ; } range[0] = 0; if (len == 16) { range[1] = addr >> 32; range[2] = addr & 0xffffffff; range[3] = size; } else {
static uint32_t get_adjusted_address_int(const char *dtb, int node, uint32_t addr) { // iterate through the sr array, looking for a region where: // sr[n].soc_node is a parent of node // addr is within the required range // then call self with return addr - child_addr + parent_addr // or just addr if nothing found if(node == fdt_path_offset(dtb, "/")) return addr; for(int i = 0; i < sr_items; i++) { if(sr[i].soc_node == node) { if(addr >= sr[i].child_addr && addr < (sr[i].child_addr + sr[i].length)) { addr = addr - sr[i].child_addr + sr[i].parent_addr; break; } } } node = fdt_parent_offset(dtb, node); if(node >= 0) return get_adjusted_address_int(dtb, node, addr); else return addr; }
int fdt_get_resource(const void *fdt, int node, const char *property, unsigned int index, struct fdt_resource *res) { const fdt32_t *ptr, *end; int na, ns, len, parent; unsigned int i = 0; parent = fdt_parent_offset(fdt, node); if (parent < 0) return parent; na = fdt_address_cells(fdt, parent); ns = fdt_size_cells(fdt, parent); ptr = fdt_getprop(fdt, node, property, &len); if (!ptr) return len; end = ptr + len / sizeof(*ptr); while (ptr + na + ns <= end) { if (i == index) { res->start = res->end = fdtdec_get_number(ptr, na); res->end += fdtdec_get_number(&ptr[na], ns) - 1; return 0; } ptr += na + ns; i++; } return -FDT_ERR_NOTFOUND; }
static uint32_t get_adjusted_address(const char *dtb, int node, uint32_t addr) { node = fdt_parent_offset(dtb, node); if(node >= 0) return get_adjusted_address_int(dtb, node, addr); else return addr; }
/* FIXME: Optimize. */ int32_t dt_nr_cells(void *fdt, int node, const char *name) { const int32_t *nr_cells; node = fdt_parent_offset(fdt, node); do { int lenp; nr_cells = dt_get_property(fdt, node, name, &lenp); if (nr_cells) { return fdt32_to_cpu(*nr_cells); } node = fdt_parent_offset(fdt, node); } while (node >= 0); return -1; }
/** * Decode EC interface details from the device tree and allocate a suitable * device. * * @param blob Device tree blob * @param node Node to decode from * @param devp Returns a pointer to the new allocated device * @return 0 if ok, -1 on error */ static int cros_ec_decode_fdt(const void *blob, int node, struct cros_ec_dev **devp) { enum fdt_compat_id compat; struct cros_ec_dev *dev; int parent; /* See what type of parent we are inside (this is expensive) */ parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("%s: Cannot find node parent\n", __func__); return -1; } dev = &static_dev; dev->node = node; dev->parent_node = parent; compat = fdtdec_lookup(blob, parent); switch (compat) { #ifdef CONFIG_CROS_EC_SPI case COMPAT_SAMSUNG_EXYNOS_SPI: dev->interface = CROS_EC_IF_SPI; if (cros_ec_spi_decode_fdt(dev, blob)) return -1; break; #endif #ifdef CONFIG_CROS_EC_I2C case COMPAT_SAMSUNG_S3C2440_I2C: dev->interface = CROS_EC_IF_I2C; if (cros_ec_i2c_decode_fdt(dev, blob)) return -1; break; #endif #ifdef CONFIG_CROS_EC_LPC case COMPAT_INTEL_LPC: dev->interface = CROS_EC_IF_LPC; break; #endif #ifdef CONFIG_CROS_EC_SANDBOX case COMPAT_SANDBOX_HOST_EMULATION: dev->interface = CROS_EC_IF_SANDBOX; break; #endif default: debug("%s: Unknown compat id %d\n", __func__, compat); return -1; } fdtdec_decode_gpio(blob, node, "ec-interrupt", &dev->ec_int); dev->optimise_flash_write = fdtdec_get_bool(blob, node, "optimise-flash-write"); *devp = dev; return 0; }
int board_usb_init(int index, enum usb_init_type init) { int node, phy_node; const char *mode; bool matched = false; const void *blob = gd->fdt_blob; u32 grf_phy_offset; /* find the usb_otg node */ node = fdt_node_offset_by_compatible(blob, -1, "rockchip,rk3288-usb"); while (node > 0) { mode = fdt_getprop(blob, node, "dr_mode", NULL); if (mode && strcmp(mode, "otg") == 0) { matched = true; break; } node = fdt_node_offset_by_compatible(blob, node, "rockchip,rk3288-usb"); } if (!matched) { debug("Not found usb_otg device\n"); return -ENODEV; } rk3288_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); node = fdtdec_lookup_phandle(blob, node, "phys"); if (node <= 0) { debug("Not found usb phy device\n"); return -ENODEV; } phy_node = fdt_parent_offset(blob, node); if (phy_node <= 0) { debug("Not found usb phy device\n"); return -ENODEV; } rk3288_otg_data.phy_of_node = phy_node; grf_phy_offset = fdtdec_get_addr(blob, node, "reg"); /* find the grf node */ node = fdt_node_offset_by_compatible(blob, -1, "rockchip,rk3288-grf"); if (node <= 0) { debug("Not found grf device\n"); return -ENODEV; } rk3288_otg_data.regs_phy = grf_phy_offset + fdtdec_get_addr(blob, node, "reg"); return dwc2_udc_probe(&rk3288_otg_data); }
/* Return the parent of this node or 0. */ static phandle_t ofw_fdt_parent(ofw_t ofw, phandle_t node) { int offset, paroffset; offset = fdt_phandle_offset(node); if (offset < 0) return (0); paroffset = fdt_parent_offset(fdtp, offset); return (fdt_offset_phandle(paroffset)); }
static int rk808_parse_dt(const void* blob) { int node, parent, nd; u32 i2c_bus_addr, bus; int ret; fdt_addr_t addr; struct fdt_gpio_state gpios[2]; node = fdt_node_offset_by_compatible(blob, 0, COMPAT_ROCKCHIP_RK808); if (node < 0) { printf("can't find dts node for rk808\n"); return -ENODEV; } if (!fdt_device_is_available(blob,node)) { debug("device rk808 is disabled\n"); return -1; } addr = fdtdec_get_addr(blob, node, "reg"); fdtdec_decode_gpios(blob, node, "gpios", gpios, 2); parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("%s: Cannot find node parent\n", __func__); return -1; } i2c_bus_addr = fdtdec_get_addr(blob, parent, "reg"); bus = i2c_get_bus_num_fdt(i2c_bus_addr); ret = rk808_i2c_probe(bus, addr); if (ret < 0) { debug("pmic rk808 i2c probe failed\n"); return ret; } nd = fdt_get_regulator_node(blob, node); if (nd < 0) printf("%s: Cannot find regulators\n", __func__); else fdt_regulator_match(blob, nd, rk808_reg_matches, RK808_NUM_REGULATORS); rk808.pmic = pmic_alloc(); rk808.node = node; rk808.pmic->hw.i2c.addr = addr; rk808.pmic->bus = bus; rk808.pwr_hold.gpio = rk_gpio_base_to_bank(gpios[1].gpio & RK_GPIO_BANK_MASK) | (gpios[1].gpio & RK_GPIO_PIN_MASK); rk808.pwr_hold.flags = !(gpios[1].flags & OF_GPIO_ACTIVE_LOW); debug("rk808 i2c_bus:%d addr:0x%02x\n", rk808.pmic->bus, rk808.pmic->hw.i2c.addr); return 0; }
int pmic_init(unsigned char bus) { static const char name[] = "MAX77686_PMIC"; //struct pmic *p = pmic_alloc(); #ifdef CONFIG_OF_CONTROL const void *blob = gd->fdt_blob; int node, parent, tmp; #endif //if (!p) { // printf("%s: POWER allocation error!\n", __func__); // return -ENOMEM; //} #ifdef CONFIG_OF_CONTROL node = fdtdec_next_compatible(blob, 0, COMPAT_MAXIM_MAX77686_PMIC); if (node < 0) { debug("PMIC: No node for PMIC Chip in device tree\n"); debug("node = %d\n", node); return -1; } parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("%s: Cannot find node parent\n", __func__); return -1; } /* tmp since p->bus is unsigned */ tmp = i2c_get_bus_num_fdt(parent); if (tmp < 0) { debug("%s: Cannot find I2C bus\n", __func__); return -1; } //p->bus = tmp; //p->hw.i2c.addr = fdtdec_get_int(blob, node, "reg", 9); fdtdec_get_int(blob, node, "reg", 9); #else p->bus = bus; p->hw.i2c.addr = MAX77686_I2C_ADDR; #endif //p->name = name; //p->interface = PMIC_I2C; //p->number_of_regs = PMIC_NUM_OF_REGS; //p->hw.i2c.tx_num = 1; puts("Board PMIC init\n"); return 0; }
fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node, const char *prop_name, int index, fdt_size_t *sizep) { int parent; debug("%s: ", __func__); parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("(no parent found)\n"); return FDT_ADDR_T_NONE; } return fdtdec_get_addr_size_auto_parent(blob, parent, node, prop_name, index, sizep); }
int ricoh619_parse_dt(const void* blob) { int node, parent, nd; u32 i2c_bus_addr, bus; int ret; fdt_addr_t addr; node = fdt_node_offset_by_compatible(blob, 0, COMPAT_RICOH_RICOH619); if (node < 0) { printf("can't find dts node for ricoh619\n"); return -ENODEV; } if (!fdt_device_is_available(blob,node)) { debug("device ricoh619 is disabled\n"); return -1; } addr = fdtdec_get_addr(blob, node, "reg"); parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("%s: Cannot find node parent\n", __func__); return -1; } i2c_bus_addr = fdtdec_get_addr(blob, parent, "reg"); bus = i2c_get_bus_num_fdt(i2c_bus_addr); ret = ricoh619_i2c_probe(bus, addr); if (ret < 0) { debug("pmic ricoh619 i2c probe failed\n"); return ret; } nd = fdt_get_regulator_node(blob, node); if (nd < 0) printf("%s: Cannot find regulators\n", __func__); else fdt_regulator_match(blob, nd, ricoh619_regulator_matches, RICOH619_NUM_REGULATORS); ricoh619.pmic = pmic_alloc(); ricoh619.node = node; ricoh619.pmic->hw.i2c.addr = addr; ricoh619.pmic->bus = bus; debug("ricoh619 i2c_bus:%d addr:0x%02x\n", ricoh619.pmic->bus, ricoh619.pmic->hw.i2c.addr); return 0; }
int tps65090_init(void) { struct pmic *p; int bus; int addr; const void *blob = gd->fdt_blob; int node, parent; node = fdtdec_next_compatible(blob, 0, COMPAT_TI_TPS65090); if (node < 0) { debug("PMIC: No node for PMIC Chip in device tree\n"); debug("node = %d\n", node); return -ENODEV; } parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("%s: Cannot find node parent\n", __func__); return -EINVAL; } bus = i2c_get_bus_num_fdt(parent); if (p->bus < 0) { debug("%s: Cannot find I2C bus\n", __func__); return -ENOENT; } addr = fdtdec_get_int(blob, node, "reg", TPS65090_I2C_ADDR); p = pmic_alloc(); if (!p) { printf("%s: POWER allocation error!\n", __func__); return -ENOMEM; } p->name = TPS65090_NAME; p->bus = bus; p->interface = PMIC_I2C; p->number_of_regs = TPS65090_NUM_REGS; p->hw.i2c.addr = addr; p->hw.i2c.tx_num = 1; p->chrg = &power_chrg_pmic_ops; puts("TPS65090 PMIC init\n"); return 0; }
int main(int argc, char *argv[]) { void *fdt; int err; test_init(argc, argv); fdt = load_blob_arg(argc, argv); check_path(fdt, "/subnode@1"); check_path(fdt, "/subnode@2"); check_path(fdt, "/subnode@1/subsubnode"); check_path(fdt, "/subnode@2/subsubnode@0"); err = fdt_parent_offset(fdt, 0); if (err != -FDT_ERR_NOTFOUND) FAIL("fdt_parent_offset(/) returns %d instead of " "-FDT_ERR_NOTFOUND", err); PASS(); }
fdt_addr_t fdtdec_get_addr_size(const void *blob, int node, const char *prop_name, fdt_size_t *sizep) { const fdt32_t *ptr, *end; int parent, na, ns, len; fdt_addr_t addr; debug("%s: %s: ", __func__, prop_name); parent = fdt_parent_offset(blob, node); if (parent < 0) { debug("(no parent found)\n"); return FDT_ADDR_T_NONE; } na = fdt_address_cells(blob, parent); ns = fdt_size_cells(blob, parent); ptr = fdt_getprop(blob, node, prop_name, &len); if (!ptr) { debug("(not found)\n"); return FDT_ADDR_T_NONE; } end = ptr + len / sizeof(*ptr); if (ptr + na + ns > end) { debug("(not enough data: expected %d bytes, got %d bytes)\n", (na + ns) * 4, len); return FDT_ADDR_T_NONE; } addr = fdtdec_get_number(ptr, na); if (sizep) { *sizep = fdtdec_get_number(ptr + na, ns); debug("addr=%pa, size=%pa\n", &addr, sizep); } else { debug("%pa\n", &addr); } return addr; }
/* We currently assume a fixed address/size. Enforce that here. */ static void check_cells(const void *dt, int node, int address, int size) { const struct fdt_property *p; int parent; int len; int n; parent = fdt_parent_offset(dt, node); if (node < 0) { fprintf(stderr, "missing parent node for %s\n", fdt_get_name(dt, node, NULL)); exit(1); } p = fdt_get_property(dt, parent, "#address-cells", &len); if (!p || len != 4) { fprintf(stderr, "Invalid or missing #address-cells for %s\n", fdt_get_name(dt, node, NULL)); exit(1); } n = fdt32_to_cpu(*(uint32_t *)p->data); if (n != address) { fprintf(stderr, "Incorrect #address-cells for %s (expected %d got %d)\n", fdt_get_name(dt, node, NULL), address, n); exit(1); } p = fdt_get_property(dt, parent, "#size-cells", &len); if (!p || len != 4) { fprintf(stderr, "Invalid or missing #size-cells for %s\n", fdt_get_name(dt, node, NULL)); exit(1); } n = fdt32_to_cpu(*(uint32_t *)p->data); if (n != size) { fprintf(stderr, "Incorrect #size-cells for %s (expected %d got %d)\n", fdt_get_name(dt, node, NULL), size, n); exit(1); } }
/* Verify parent MPU6000 exists */ static int mpu6000_accel_probe(const char *name) { const void *blob = fdtparse_get_blob(); int offset, parent_offset, ret; char *parent; struct obj *parent_obj; offset = fdt_path_offset(blob, name); if (offset < 0) { return 0; } if (fdt_node_check_compatible(blob, offset, MPU6000_ACCEL_COMPAT)) { return 0; } parent_offset = fdt_parent_offset(blob, offset); if (parent_offset < 0) { return 0; } parent = fdtparse_get_path(blob, parent_offset); if (!parent) { return 0; } /* Attempt to get parent MPU6000 */ parent_obj = device_get(parent); if (parent_obj) { /* Found it! Good to go! */ device_put(parent_obj); ret = 1; } else { /* No MPU6000, no MPU6000 accelerometer */ ret = 0; } free(parent); return ret; }
paddr_t _fdt_reg_base_address(const void *fdt, int offs) { const void *reg; int ncells; int len; int parent; parent = fdt_parent_offset(fdt, offs); if (parent < 0) return (paddr_t)-1; reg = fdt_getprop(fdt, offs, "reg", &len); if (!reg) return (paddr_t)-1; ncells = fdt_address_cells(fdt, parent); if (ncells < 0) return (paddr_t)-1; return _fdt_read_paddr(reg, ncells); }
static uint64 fdt_get_range_offset(const void* fdt, int32 node) { // Obtain the offset of the device by searching // for the first ranges start in parents. // It could be possible that there are multiple // offset ranges in several parents + children. // Lets hope that no system designer is that insane. int depth = fdt_node_depth(fdt, node); int32 examineNode = node; uint64 pathOffset = 0x0; while (depth > 0) { int len; const void* prop; prop = fdt_getprop(fdt, examineNode, "ranges", &len); if (prop) { int32 regAddressCells = 1; int32 regSizeCells = 1; fdt_get_cell_count(fdt, examineNode, regAddressCells, regSizeCells); const uint32 *p = (const uint32 *)prop; // All we are interested in is the start offset if (regAddressCells == 2) pathOffset = fdt64_to_cpu(*(uint64_t *)p); else pathOffset = fdt32_to_cpu(*(uint32_t *)p); break; } int32 parentNode = fdt_parent_offset(fdt, examineNode); depth = fdt_node_depth(fdt, parentNode); examineNode = parentNode; } TRACE("%s: range offset: 0x%" B_PRIx64 "\n", __func__, pathOffset); return pathOffset; }
ssize_t _fdt_reg_size(const void *fdt, int offs) { const uint32_t *reg; uint32_t sz; int n; int len; int parent; parent = fdt_parent_offset(fdt, offs); if (parent < 0) return (paddr_t)-1; reg = (const uint32_t *)fdt_getprop(fdt, offs, "reg", &len); if (!reg) return -1; n = fdt_address_cells(fdt, parent); if (n < 1 || n > 2) return -1; reg += n; n = fdt_size_cells(fdt, parent); if (n < 1 || n > 2) return -1; sz = fdt32_to_cpu(*reg); if (n == 2) { if (sz) return -1; reg++; sz = fdt32_to_cpu(*reg); } return sz; }
/* * fdt_get_reg - Fill buffer by information from DT */ static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf, const u32 *cell, int n) { int i = 0, b, banks; int parent_offset = fdt_parent_offset(fdt, nodeoffset); int address_cells = fdt_address_cells(fdt, parent_offset); int size_cells = fdt_size_cells(fdt, parent_offset); char *p = buf; phys_addr_t val; phys_size_t vals; debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n", __func__, address_cells, size_cells, buf, cell); /* Check memory bank setup */ banks = n % (address_cells + size_cells); if (banks) panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n", n, address_cells, size_cells); banks = n / (address_cells + size_cells); for (b = 0; b < banks; b++) { debug("%s: Bank #%d:\n", __func__, b); if (address_cells == 2) { val = cell[i + 1]; val <<= 32; val |= cell[i]; val = fdt64_to_cpu(val); debug("%s: addr64=%llx, ptr=%p, cell=%p\n", __func__, val, p, &cell[i]); *(phys_addr_t *)p = val; } else { debug("%s: addr32=%x, ptr=%p\n", __func__, fdt32_to_cpu(cell[i]), p); *(phys_addr_t *)p = fdt32_to_cpu(cell[i]); } p += sizeof(phys_addr_t); i += address_cells; debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i, sizeof(phys_addr_t)); if (size_cells == 2) { vals = cell[i + 1]; vals <<= 32; vals |= cell[i]; vals = fdt64_to_cpu(vals); debug("%s: size64=%llx, ptr=%p, cell=%p\n", __func__, vals, p, &cell[i]); *(phys_size_t *)p = vals; } else { debug("%s: size32=%x, ptr=%p\n", __func__, fdt32_to_cpu(cell[i]), p); *(phys_size_t *)p = fdt32_to_cpu(cell[i]); } p += sizeof(phys_size_t); i += size_cells; debug("%s: ps=%p, i=%x, size=%zu\n", __func__, p, i, sizeof(phys_size_t)); } /* Return the first address size */ return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t)); }
int board_usb_init(int index, enum usb_init_type init) { struct fdtdec_phandle_args args; struct udevice *dev; const void *blob = gd->fdt_blob; struct clk clk; struct phy phy; int node; int phy_provider; int ret; /* find the usb otg node */ node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); if (node < 0) { debug("Not found usb_otg device\n"); return -ENODEV; } if (!fdtdec_get_is_enabled(blob, node)) { debug("stm32 usbotg is disabled in the device tree\n"); return -ENODEV; } /* Enable clock */ ret = fdtdec_parse_phandle_with_args(blob, node, "clocks", "#clock-cells", 0, 0, &args); if (ret) { debug("usbotg has no clocks defined in the device tree\n"); return ret; } ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev); if (ret) return ret; if (args.args_count != 1) { debug("Can't find clock ID in the device tree\n"); return -ENODATA; } clk.dev = dev; clk.id = args.args[0]; ret = clk_enable(&clk); if (ret) { debug("Failed to enable usbotg clock\n"); return ret; } /* Reset */ ret = fdtdec_parse_phandle_with_args(blob, node, "resets", "#reset-cells", 0, 0, &args); if (ret) { debug("usbotg has no resets defined in the device tree\n"); goto clk_err; } ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, &dev); if (ret || args.args_count != 1) goto clk_err; usbotg_reset.dev = dev; usbotg_reset.id = args.args[0]; reset_assert(&usbotg_reset); udelay(2); reset_deassert(&usbotg_reset); /* Get USB PHY */ ret = fdtdec_parse_phandle_with_args(blob, node, "phys", "#phy-cells", 0, 0, &args); if (!ret) { phy_provider = fdt_parent_offset(blob, args.node); ret = uclass_get_device_by_of_offset(UCLASS_PHY, phy_provider, &dev); if (ret) goto clk_err; phy.dev = dev; phy.id = fdtdec_get_uint(blob, args.node, "reg", -1); ret = generic_phy_power_on(&phy); if (ret) { debug("unable to power on the phy\n"); goto clk_err; } ret = generic_phy_init(&phy); if (ret) { debug("failed to init usb phy\n"); goto phy_power_err; } } /* Parse and store data needed for gadget */ stm32mp_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); if (stm32mp_otg_data.regs_otg == FDT_ADDR_T_NONE) { debug("usbotg: can't get base address\n"); ret = -ENODATA; goto phy_init_err; } stm32mp_otg_data.rx_fifo_sz = fdtdec_get_int(blob, node, "g-rx-fifo-size", 0); stm32mp_otg_data.np_tx_fifo_sz = fdtdec_get_int(blob, node, "g-np-tx-fifo-size", 0); stm32mp_otg_data.tx_fifo_sz = fdtdec_get_int(blob, node, "g-tx-fifo-size", 0); /* Enable voltage level detector */ if (!(fdtdec_parse_phandle_with_args(blob, node, "usb33d-supply", NULL, 0, 0, &args))) { if (!uclass_get_device_by_of_offset(UCLASS_REGULATOR, args.node, &dev)) { ret = regulator_set_enable(dev, true); if (ret) { debug("Failed to enable usb33d\n"); goto phy_init_err; } } } /* Enable vbus sensing */ setbits_le32(stm32mp_otg_data.regs_otg + STM32MP_GGPIO, STM32MP_GGPIO_VBUS_SENSING); return dwc2_udc_probe(&stm32mp_otg_data); phy_init_err: generic_phy_exit(&phy); phy_power_err: generic_phy_power_off(&phy); clk_err: clk_disable(&clk); return ret; }
static void *fdt_wrapper_get_parent(const void *devp) { return offset_devp(fdt_parent_offset(fdt, devp_offset(devp))); }
phys_addr_t fdt_get_device_reg(const void* fdt, int node, bool physical) { const void *prop = NULL; int len; uint64 baseDevice = 0x0; int32 regAddressCells = 1; int32 regSizeCells = 1; fdt_get_cell_count(fdt, node, regAddressCells, regSizeCells); // TODO: check for virtual-reg, and don't -= fdt_get_range_offset? // XXX: not sure #address-cells & #size-cells actually apply to virtual-reg if (!physical) { prop = fdt_getprop(fdt, node, "virtual-reg", &len); if (prop != NULL) { baseDevice = fdt32_to_cpu(*(uint32_t *)prop); return baseDevice; } } prop = fdt_getprop(fdt, node, "reg", &len); if (!prop) { dprintf("%s: reg property not found on node in FDT!\n", __func__); return 0; } const uint32 *p = (const uint32 *)prop; // soc base address cells if (regAddressCells == 2) baseDevice = fdt64_to_cpu(*(uint64_t *)p); else baseDevice = fdt32_to_cpu(*(uint32_t *)p); //p += regAddressCells; // subtract the range offset (X) on the parent node (ranges = X Y Z) baseDevice -= fdt_get_range_offset(fdt, node); // find the start of the parent (X) and add to base (regs = X Y) int parentNode = fdt_parent_offset(fdt, node); if (!parentNode) return baseDevice; fdt_get_cell_count(fdt, parentNode, regAddressCells, regSizeCells); prop = fdt_getprop(fdt, parentNode, "reg", &len); if (!prop) return baseDevice; p = (const uint32 *)prop; uint64 parentReg = 0x0; // soc base address cells if (regAddressCells == 2) parentReg = fdt64_to_cpu(*(uint64_t *)p); else parentReg = fdt32_to_cpu(*(uint32_t *)p); // add parent reg base to property baseDevice += parentReg; return baseDevice; }