int main(int argc, char *argv[]) { void *fdt; int n1, n2, n3, n4, n5; uint32_t h1, h2, h4, h5; test_init(argc, argv); fdt = load_blob_arg(argc, argv); n1 = fdt_path_offset(fdt, "/node1"); if (n1 < 0) FAIL("fdt_path_offset(/node1): %s", fdt_strerror(n1)); n2 = fdt_path_offset(fdt, "/node2"); if (n2 < 0) FAIL("fdt_path_offset(/node2): %s", fdt_strerror(n2)); n3 = fdt_path_offset(fdt, "/node3"); if (n3 < 0) FAIL("fdt_path_offset(/node3): %s", fdt_strerror(n3)); n4 = fdt_path_offset(fdt, "/node4"); if (n4 < 0) FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4)); n5 = fdt_path_offset(fdt, "/node5"); if (n5 < 0) FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5)); h1 = fdt_get_phandle(fdt, n1); h2 = fdt_get_phandle(fdt, n2); h4 = fdt_get_phandle(fdt, n4); h5 = fdt_get_phandle(fdt, n5); if (h1 != 0x2000) FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x", h1, 0x2000); if (h2 != 0x1) FAIL("/node2 has wrong phandle, 0x%x instead of 0x%x", h2, 0x1); if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0)) FAIL("/node4 has bad phandle, 0x%x", h4); if ((h5 == 0) || (h5 == -1)) FAIL("/node5 has bad phandle, 0x%x", h5); if ((h5 == h4) || (h5 == h2) || (h5 == h1)) FAIL("/node5 has duplicate phandle, 0x%x", h5); check_ref(fdt, n1, h2); check_ref(fdt, n2, h1); check_ref(fdt, n3, h4); PASS(); }
void ft_fixup_num_cores(void *blob) { int off, num_cores, del_cores; del_cores = 0; num_cores = cpu_numcores(); off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); while (off != -FDT_ERR_NOTFOUND) { u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0); u32 phys_cpu_id = thread_to_core(*reg); if (!is_core_valid(phys_cpu_id) || is_core_disabled(phys_cpu_id)) { int ph = fdt_get_phandle(blob, off); /* Delete the cpu node once there are no cpu handles */ if (-FDT_ERR_NOTFOUND == ft_del_cpuhandle(blob, ph)) { fdt_del_node(blob, off); del_cores++; } /* either we deleted some cpu handles or the cpu node * so we reset the offset back to the start since we * can't trust the offsets anymore */ off = -1; } off = fdt_node_offset_by_prop_value(blob, off, "device_type", "cpu", 4); } debug ("%x core system found\n", num_cores); debug ("deleted %d extra core entry entries from device tree\n", del_cores); }
int fdt_generate_phandle(const void *fdt, uint32_t *phandle) { uint32_t max = 0; int offset = -1; while (true) { uint32_t value; offset = fdt_next_node(fdt, offset, NULL); if (offset < 0) { if (offset == -FDT_ERR_NOTFOUND) break; return offset; } value = fdt_get_phandle(fdt, offset); if (value > max) max = value; } if (max == FDT_MAX_PHANDLE) return -FDT_ERR_NOPHANDLES; if (phandle) *phandle = max + 1; return 0; }
uint32_t fdt_get_max_phandle(const void *fdt) { uint32_t max_phandle = 0; int offset; for (offset = fdt_next_node(fdt, -1, NULL);; offset = fdt_next_node(fdt, offset, NULL)) { uint32_t phandle; if (offset == -FDT_ERR_NOTFOUND) return max_phandle; if (offset < 0) return (uint32_t)-1; phandle = fdt_get_phandle(fdt, offset); if (phandle == (uint32_t)-1) continue; if (phandle > max_phandle) max_phandle = phandle; } return 0; }
static void powernv_populate_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) { const char compatible[] = "bt\0ipmi-bt"; uint32_t io_base; uint32_t io_regs[] = { cpu_to_be32(1), 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ cpu_to_be32(3) }; uint32_t irq; char *name; int node; io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); io_regs[1] = cpu_to_be32(io_base); irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); node = fdt_add_subnode(fdt, lpc_off, name); _FDT(node); g_free(name); _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); _FDT((fdt_setprop(fdt, node, "compatible", compatible, sizeof(compatible)))); /* Mark it as reserved to avoid Linux trying to claim it */ _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", fdt_get_phandle(fdt, lpc_off)))); }
static void powernv_populate_serial(ISADevice *d, void *fdt, int lpc_off) { const char compatible[] = "ns16550\0pnpPNP,501"; uint32_t io_base = d->ioport_id; uint32_t io_regs[] = { cpu_to_be32(1), cpu_to_be32(io_base), cpu_to_be32(8) }; char *name; int node; name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); node = fdt_add_subnode(fdt, lpc_off, name); _FDT(node); g_free(name); _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); _FDT((fdt_setprop(fdt, node, "compatible", compatible, sizeof(compatible)))); _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", fdt_get_phandle(fdt, lpc_off)))); /* This is needed by Linux */ _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); }
static void ft_fixup_port(void *blob, struct fm_eth_info *info, char *prop) { int off, ph; phys_addr_t paddr = CONFIG_SYS_CCSRBAR_PHYS + info->compat_offset; u64 dtsec1_addr = (u64)CONFIG_SYS_CCSRBAR_PHYS + CONFIG_SYS_FSL_FM1_DTSEC1_OFFSET; off = fdt_node_offset_by_compat_reg(blob, prop, paddr); if (info->enabled) { fdt_fixup_phy_connection(blob, off, info->enet_if); board_ft_fman_fixup_port(blob, prop, paddr, info->port, off); return ; } /* board code might have caused offset to change */ off = fdt_node_offset_by_compat_reg(blob, prop, paddr); /* Don't disable FM1-DTSEC1 MAC as its used for MDIO */ if (paddr != dtsec1_addr) { /* disable the mac node */ fdt_setprop_string(blob, off, "status", "disabled"); } /* disable the node point to the mac */ ph = fdt_get_phandle(blob, off); do_fixup_by_prop(blob, "fsl,fman-mac", &ph, sizeof(ph), "status", "disabled", strlen("disabled") + 1, 1); }
/* * Get max phandle */ static uint32_t fdt_max_phandle(void *fdtp) { int o, depth; uint32_t max_phandle, phandle; depth = 1; o = fdt_path_offset(fdtp, "/"); max_phandle = fdt_get_phandle(fdtp, o); for (depth = 0; (o >= 0) && (depth >= 0); o = fdt_next_node(fdtp, o, &depth)) { phandle = fdt_get_phandle(fdtp, o); if (max_phandle < phandle) max_phandle = phandle; } return max_phandle; }
int dev_read_phandle(struct udevice *dev) { ofnode node = dev_ofnode(dev); if (ofnode_is_np(node)) return ofnode_to_np(node)->phandle; else return fdt_get_phandle(gd->fdt_blob, ofnode_to_offset(node)); }
static void ft_fixup_port(void *blob, struct fm_eth_info *info, char *prop) { int off; uint32_t ph; phys_addr_t paddr = CONFIG_SYS_CCSRBAR_PHYS + info->compat_offset; u64 dtsec1_addr = (u64)CONFIG_SYS_CCSRBAR_PHYS + CONFIG_SYS_FSL_FM1_DTSEC1_OFFSET; off = fdt_node_offset_by_compat_reg(blob, prop, paddr); if (info->enabled) { fdt_fixup_phy_connection(blob, off, info->enet_if); board_ft_fman_fixup_port(blob, prop, paddr, info->port, off); return ; } #ifdef CONFIG_SYS_FMAN_V3 /* * Physically FM1_DTSEC9 and FM1_10GEC1 use the same dual-role MAC, when * FM1_10GEC1 is enabled and FM1_DTSEC9 is disabled, ensure that the * dual-role MAC is not disabled, ditto for other dual-role MACs. */ if (((info->port == FM1_DTSEC9) && (PORT_IS_ENABLED(FM1_10GEC1))) || ((info->port == FM1_DTSEC10) && (PORT_IS_ENABLED(FM1_10GEC2))) || ((info->port == FM1_DTSEC1) && (PORT_IS_ENABLED(FM1_10GEC1))) || ((info->port == FM1_DTSEC1) && (PORT_IS_ENABLED(FM1_10GEC3))) || ((info->port == FM1_DTSEC2) && (PORT_IS_ENABLED(FM1_10GEC4))) || ((info->port == FM1_10GEC1) && (PORT_IS_ENABLED(FM1_DTSEC1))) || ((info->port == FM1_10GEC1) && (PORT_IS_ENABLED(FM1_DTSEC9))) || ((info->port == FM1_10GEC2) && (PORT_IS_ENABLED(FM1_DTSEC10))) || ((info->port == FM1_10GEC3) && (PORT_IS_ENABLED(FM1_DTSEC1))) || ((info->port == FM1_10GEC4) && (PORT_IS_ENABLED(FM1_DTSEC2))) #if (CONFIG_SYS_NUM_FMAN == 2) || ((info->port == FM2_DTSEC9) && (PORT_IS_ENABLED(FM2_10GEC1))) || ((info->port == FM2_DTSEC10) && (PORT_IS_ENABLED(FM2_10GEC2))) || ((info->port == FM2_10GEC1) && (PORT_IS_ENABLED(FM2_DTSEC9))) || ((info->port == FM2_10GEC2) && (PORT_IS_ENABLED(FM2_DTSEC10))) #endif ) return; #endif /* board code might have caused offset to change */ off = fdt_node_offset_by_compat_reg(blob, prop, paddr); /* Don't disable FM1-DTSEC1 MAC as its used for MDIO */ if (paddr != dtsec1_addr) fdt_status_disabled(blob, off); /* disable the MAC node */ /* disable the fsl,dpa-ethernet node that points to the MAC */ ph = fdt_get_phandle(blob, off); do_fixup_by_prop(blob, "fsl,fman-mac", &ph, sizeof(ph), "status", "disabled", strlen("disabled") + 1, 1); }
uint32_t qemu_fdt_get_phandle(void *fdt, const char *path) { uint32_t r; r = fdt_get_phandle(fdt, findnode_nofail(fdt, path)); if (r == 0) { error_report("%s: Couldn't get phandle for %s: %s", __func__, path, fdt_strerror(r)); exit(1); } return r; }
uint32_t qemu_devtree_get_phandle(void *fdt, const char *path) { uint32_t r; r = fdt_get_phandle(fdt, findnode_nofail(fdt, path)); if (r == 0) { fprintf(stderr, "%s: Couldn't get phandle for %s: %s\n", __func__, path, fdt_strerror(r)); exit(1); } return r; }
static int ft_fixup_clocks(void *fdt, const char **names, u32 *rates, int num) { int offs, node_offs, ret, i; uint32_t phandle; offs = fdt_path_offset(fdt, "/ocp/l4@4a000000/cm_core_aon@5000/clocks"); if (offs < 0) { debug("Could not find cm_core_aon clocks node path offset : %s\n", fdt_strerror(offs)); return offs; } for (i = 0; i < num; i++) { node_offs = fdt_subnode_offset(fdt, offs, names[i]); if (node_offs < 0) { debug("Could not find clock sub-node %s: %s\n", names[i], fdt_strerror(node_offs)); return offs; } phandle = fdt_get_phandle(fdt, node_offs); if (!phandle) { debug("Could not find phandle for clock %s\n", names[i]); return -1; } ret = fdt_setprop_u32(fdt, node_offs, "assigned-clocks", phandle); if (ret < 0) { debug("Could not add assigned-clocks property to clock node %s: %s\n", names[i], fdt_strerror(ret)); return ret; } ret = fdt_setprop_u32(fdt, node_offs, "assigned-clock-rates", rates[i]); if (ret < 0) { debug("Could not add assigned-clock-rates property to clock node %s: %s\n", names[i], fdt_strerror(ret)); return ret; } } return 0; }
static uint32_t find_int_controller(void *fdt) { /* Find the FDT node corresponding to the interrupt controller * for virtio-mmio devices. We do this by scanning the fdt for * a node with the right compatibility, since we know there is * only one GIC on a vexpress board. * We return the phandle of the node, or 0 if none was found. */ const char *compat = "arm,cortex-a9-gic"; int offset; offset = fdt_node_offset_by_compatible(fdt, -1, compat); if (offset >= 0) { return fdt_get_phandle(fdt, offset); } return 0; }
STATIC INT32 fdt_alloc_phandle ( IN VOID *Fdt ) { INT32 Offset; INT32 Phandle; Phandle = 0; for (Offset = fdt_next_node (Fdt, -1, NULL); Offset >= 0; Offset = fdt_next_node (Fdt, Offset, NULL)) { Phandle = MAX (Phandle, fdt_get_phandle (Fdt, Offset)); } return Phandle + 1; }
/* * This function updates the mmu-masters property on the SMMU * node as per the SMMU binding-- phandle and list of stream IDs * for each MMU master. */ void append_mmu_masters(void *blob, const char *smmu_path, const char *master_name, u32 *stream_ids, int count) { u32 phandle; int smmu_nodeoffset; int master_nodeoffset; int i; /* get phandle of mmu master device */ master_nodeoffset = fdt_path_offset(blob, master_name); if (master_nodeoffset < 0) { printf("\n%s: ERROR: master not found\n", __func__); return; } phandle = fdt_get_phandle(blob, master_nodeoffset); if (!phandle) { /* if master has no phandle, create one */ phandle = fdt_create_phandle(blob, master_nodeoffset); if (!phandle) { printf("\n%s: ERROR: unable to create phandle\n", __func__); return; } } /* append it to mmu-masters */ smmu_nodeoffset = fdt_path_offset(blob, smmu_path); if (fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", phandle) < 0) { printf("\n%s: ERROR: unable to update SMMU node\n", __func__); return; } /* for each stream ID, append to mmu-masters */ for (i = 0; i < count; i++) { fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters", stream_ids[i]); } /* fix up #stream-id-cells with stream ID count */ if (fdt_setprop_u32(blob, master_nodeoffset, "#stream-id-cells", count) < 0) printf("\n%s: ERROR: unable to update #stream-id-cells\n", __func__); }
static QEMUDevice *qdev_create(QEMUDeviceClass *dc, const void *dt, int node_offset) { QEMUDevice *dev = qemu_mallocz(sizeof(*dc)); dev->dc = dc; dev->properties = qdev_copy_properties(dc->properties); if (dc->num_irqs) { dev->irqp = qemu_mallocz(dc->num_irqs * sizeof(qemu_irq *)); dev->irq = qemu_mallocz(dc->num_irqs * sizeof(qemu_irq)); } dev->node_offset = node_offset; dev->dt = dt; dev->phandle = fdt_get_phandle(dt, node_offset); dev->next = first_device; first_device = dev; return dev; }
/* * Handle __fixups__ node in overlay DTB */ static int fdt_overlay_do_fixups(void *main_fdtp, void *overlay_fdtp) { int main_symbols_o, symbol_o, overlay_fixups_o; int fixup_prop_o; int len; const char *fixups, *name; const char *symbol_path; uint32_t phandle; main_symbols_o = fdt_path_offset(main_fdtp, "/__symbols__"); overlay_fixups_o = fdt_path_offset(overlay_fdtp, "/__fixups__"); if (main_symbols_o < 0) return (-1); if (overlay_fixups_o < 0) return (-1); for (fixup_prop_o = fdt_first_property_offset(overlay_fdtp, overlay_fixups_o); fixup_prop_o >= 0; fixup_prop_o = fdt_next_property_offset(overlay_fdtp, fixup_prop_o)) { fixups = fdt_getprop_by_offset(overlay_fdtp, fixup_prop_o, &name, &len); symbol_path = fdt_getprop(main_fdtp, main_symbols_o, name, NULL); if (symbol_path == NULL) { printf("couldn't find \"%s\" symbol in main dtb\n", name); return (-1); } symbol_o = fdt_path_offset(main_fdtp, symbol_path); if (symbol_o < 0) { printf("couldn't find \"%s\" path in main dtb\n", symbol_path); return (-1); } phandle = fdt_get_phandle(main_fdtp, symbol_o); if (fdt_do_one_fixup(overlay_fdtp, fixups, len, phandle) < 0) return (-1); } return (0); }
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) { int offset; if ((phandle == 0) || (phandle == -1)) return -FDT_ERR_BADPHANDLE; FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we * potentially scan each property of a node in * fdt_get_phandle(), then if that didn't find what * we want, we scan over them again making our way to the next * node. Still it's the easiest to implement approach; * performance can come later. */ for (offset = fdt_next_node(fdt, -1, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { if (fdt_get_phandle(fdt, offset) == phandle) return offset; } return offset; /* error from fdt_next_node() */ }
static __init int remove_gic(void *fdt) { const unsigned int cpu_ehci_int = 2; const unsigned int cpu_uart_int = 4; const unsigned int cpu_eth_int = 6; int gic_off, cpu_off, uart_off, eth_off, ehci_off, err; uint32_t cfg, cpu_phandle; /* leave the GIC node intact if a GIC is present */ cfg = __raw_readl((uint32_t *)SEAD_CONFIG); if (cfg & SEAD_CONFIG_GIC_PRESENT) return 0; gic_off = fdt_node_offset_by_compatible(fdt, -1, "mti,gic"); if (gic_off < 0) { pr_err("unable to find DT GIC node: %d\n", gic_off); return gic_off; } err = fdt_nop_node(fdt, gic_off); if (err) { pr_err("unable to nop GIC node\n"); return err; } cpu_off = fdt_node_offset_by_compatible(fdt, -1, "mti,cpu-interrupt-controller"); if (cpu_off < 0) { pr_err("unable to find CPU intc node: %d\n", cpu_off); return cpu_off; } cpu_phandle = fdt_get_phandle(fdt, cpu_off); if (!cpu_phandle) { pr_err("unable to get CPU intc phandle\n"); return -EINVAL; } uart_off = fdt_node_offset_by_compatible(fdt, -1, "ns16550a"); while (uart_off >= 0) { err = fdt_setprop_u32(fdt, uart_off, "interrupt-parent", cpu_phandle); if (err) { pr_warn("unable to set UART interrupt-parent: %d\n", err); return err; } err = fdt_setprop_u32(fdt, uart_off, "interrupts", cpu_uart_int); if (err) { pr_err("unable to set UART interrupts property: %d\n", err); return err; } uart_off = fdt_node_offset_by_compatible(fdt, uart_off, "ns16550a"); } if (uart_off != -FDT_ERR_NOTFOUND) { pr_err("error searching for UART DT node: %d\n", uart_off); return uart_off; } eth_off = fdt_node_offset_by_compatible(fdt, -1, "smsc,lan9115"); if (eth_off < 0) { pr_err("unable to find ethernet DT node: %d\n", eth_off); return eth_off; } err = fdt_setprop_u32(fdt, eth_off, "interrupt-parent", cpu_phandle); if (err) { pr_err("unable to set ethernet interrupt-parent: %d\n", err); return err; } err = fdt_setprop_u32(fdt, eth_off, "interrupts", cpu_eth_int); if (err) { pr_err("unable to set ethernet interrupts property: %d\n", err); return err; } ehci_off = fdt_node_offset_by_compatible(fdt, -1, "generic-ehci"); if (ehci_off < 0) { pr_err("unable to find EHCI DT node: %d\n", ehci_off); return ehci_off; } err = fdt_setprop_u32(fdt, ehci_off, "interrupt-parent", cpu_phandle); if (err) { pr_err("unable to set EHCI interrupt-parent: %d\n", err); return err; } err = fdt_setprop_u32(fdt, ehci_off, "interrupts", cpu_ehci_int); if (err) { pr_err("unable to set EHCI interrupts property: %d\n", err); return err; } return 0; }