phandle_t ofw_bus_find_compatible(phandle_t node, const char *onecompat) { phandle_t child, ret; void *compat; int len; /* * Traverse all children of 'start' node, and find first with * matching 'compatible' property. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { len = OF_getprop_alloc(child, "compatible", 1, &compat); if (len >= 0) { ret = ofw_bus_node_is_compatible(compat, len, onecompat); free(compat, M_OFWPROP); if (ret != 0) return (child); } ret = ofw_bus_find_compatible(child, onecompat); if (ret != 0) return (ret); } return (0); }
mii_fdt_phy_config_t * mii_fdt_get_config(device_t phydev) { mii_fdt_phy_config_t *cfg; device_t miibus, macdev; pcell_t val; miibus = device_get_parent(phydev); macdev = device_get_parent(miibus); cfg = malloc(sizeof(*cfg), M_OFWPROP, M_ZERO | M_WAITOK); /* * If we can't find our parent MAC's node, there's nothing more we can * fill in; cfg is already full of zero/default values, return it. */ if ((cfg->macnode = ofw_bus_get_node(macdev)) == -1) return (cfg); cfg->con_type = mii_fdt_get_contype(cfg->macnode); /* * If we can't find our own PHY node, there's nothing more we can fill * in, just return what we've got. */ if ((cfg->phynode = mii_fdt_get_phynode(cfg->macnode)) == -1) return (cfg); if (OF_getencprop(cfg->phynode, "max-speed", &val, sizeof(val)) > 0) cfg->max_speed = val; if (ofw_bus_node_is_compatible(cfg->phynode, "ethernet-phy-ieee802.3-c45")) cfg->flags |= MIIF_FDT_COMPAT_CLAUSE45; if (OF_hasprop(cfg->phynode, "broken-turn-around")) cfg->flags |= MIIF_FDT_BROKEN_TURNAROUND; if (OF_hasprop(cfg->phynode, "enet-phy-lane-swap")) cfg->flags |= MIIF_FDT_LANE_SWAP; if (OF_hasprop(cfg->phynode, "enet-phy-lane-no-swap")) cfg->flags |= MIIF_FDT_NO_LANE_SWAP; if (OF_hasprop(cfg->phynode, "eee-broken-100tx")) cfg->flags |= MIIF_FDT_EEE_BROKEN_100TX; if (OF_hasprop(cfg->phynode, "eee-broken-1000t")) cfg->flags |= MIIF_FDT_EEE_BROKEN_1000T; if (OF_hasprop(cfg->phynode, "eee-broken-10gt")) cfg->flags |= MIIF_FDT_EEE_BROKEN_10GT; if (OF_hasprop(cfg->phynode, "eee-broken-1000kx")) cfg->flags |= MIIF_FDT_EEE_BROKEN_1000KX; if (OF_hasprop(cfg->phynode, "eee-broken-10gkx4")) cfg->flags |= MIIF_FDT_EEE_BROKEN_10GKX4; if (OF_hasprop(cfg->phynode, "eee-broken-10gkr")) cfg->flags |= MIIF_FDT_EEE_BROKEN_10GKR; return (cfg); }
static int rk30_gpio_init(void) { phandle_t child, parent, root, ctrl; pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS]; struct gpio_ctrl_entry *e; int len, rv; root = OF_finddevice("/"); len = 0; parent = root; /* Traverse through entire tree to find nodes with 'gpios' prop */ for (child = OF_child(parent); child != 0; child = OF_peer(child)) { /* Find a 'leaf'. Start the search from this node. */ while (OF_child(child)) { parent = child; child = OF_child(child); } if ((len = OF_getproplen(child, "gpios")) > 0) { if (len > sizeof(gpios)) return (ENXIO); /* Get 'gpios' property. */ OF_getprop(child, "gpios", &gpios, len); e = (struct gpio_ctrl_entry *)&gpio_controllers; /* Find and call a handler. */ for (; e->compat; e++) { /* * First cell of 'gpios' property should * contain a ref. to a node defining GPIO * controller. */ ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0])); if (ofw_bus_node_is_compatible(ctrl, e->compat)) /* Call a handler. */ if ((rv = e->handler(ctrl, (pcell_t *)&gpios, len))) return (rv); } } if (OF_peer(child) == 0) { /* No more siblings. */ child = parent; parent = OF_parent(child); } } return (0); }
static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) { if (!ofw_bus_node_is_compatible(node, "lpc,pic")) return (ENXIO); *interrupt = fdt32_to_cpu(intr[0]); *trig = INTR_TRIGGER_CONFORM; *pol = INTR_POLARITY_CONFORM; return (0); }
static const struct ofw_compat_data * aw_ccu_search_compatible(void) { const struct ofw_compat_data *compat; phandle_t root; root = OF_finddevice("/"); for (compat = compat_data; compat->ocd_str != NULL; compat++) if (ofw_bus_node_is_compatible(root, compat->ocd_str)) break; return (compat); }
int ofw_bus_is_compatible(device_t dev, const char *onecompat) { phandle_t node; const char *compat; int len; if ((compat = ofw_bus_get_compat(dev)) == NULL) return (0); if ((node = ofw_bus_get_node(dev)) == -1) return (0); /* Get total 'compatible' prop len */ if ((len = OF_getproplen(node, "compatible")) <= 0) return (0); return (ofw_bus_node_is_compatible(compat, len, onecompat)); }
phandle_t ofw_bus_find_compatible(phandle_t node, const char *onecompat) { phandle_t child, ret; /* * Traverse all children of 'start' node, and find first with * matching 'compatible' property. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { if (ofw_bus_node_is_compatible(child, onecompat) != 0) return (child); ret = ofw_bus_find_compatible(child, onecompat); if (ret != 0) return (ret); } return (0); }
static void bcm2835_cpufreq_identify(driver_t *driver, device_t parent) { const struct ofw_compat_data *compat; phandle_t root; root = OF_finddevice("/"); for (compat = compat_data; compat->ocd_str != NULL; compat++) if (ofw_bus_node_is_compatible(root, compat->ocd_str)) break; if (compat->ocd_data == 0) return; DPRINTF("driver=%p, parent=%p\n", driver, parent); if (device_find_child(parent, "bcm2835_cpufreq", -1) != NULL) return; if (BUS_ADD_CHILD(parent, 0, "bcm2835_cpufreq", -1) == NULL) device_printf(parent, "add child failed\n"); }
static int bman_portals_fdt_probe(device_t dev) { phandle_t node; if (ofw_bus_is_compatible(dev, "simple-bus")) { node = ofw_bus_get_node(dev); for (node = OF_child(node); node > 0; node = OF_peer(node)) { if (ofw_bus_node_is_compatible(node, "fsl,bman-portal")) break; } if (node <= 0) return (ENXIO); } else if (!ofw_bus_is_compatible(dev, "fsl,bman-portals")) return (ENXIO); device_set_desc(dev, BMAN_PORT_DEVSTR); return (BUS_PROBE_DEFAULT); }
static boolean_t alpine_validate_cpu(u_int id, phandle_t child, u_int addr_cell, pcell_t *reg) { return ofw_bus_node_is_compatible(child, "arm,cortex-a15"); }
static int qman_portals_fdt_attach(device_t dev) { struct dpaa_portals_softc *sc; phandle_t node, child, cpu_node; vm_paddr_t portal_pa, portal_par_pa; vm_size_t portal_size; uint32_t addr, paddr, size; ihandle_t cpu; int cpu_num, cpus, intr_rid; struct dpaa_portals_devinfo di; struct ofw_bus_devinfo ofw_di = {}; cell_t *range; int nrange; int i; cpus = 0; sc = device_get_softc(dev); sc->sc_dev = dev; node = ofw_bus_get_node(dev); /* Get this node's range */ get_addr_props(ofw_bus_get_node(device_get_parent(dev)), &paddr, &size); get_addr_props(node, &addr, &size); nrange = OF_getencprop_alloc(node, "ranges", sizeof(*range), (void **)&range); if (nrange < addr + paddr + size) return (ENXIO); portal_pa = portal_par_pa = 0; portal_size = 0; for (i = 0; i < addr; i++) { portal_pa <<= 32; portal_pa |= range[i]; } for (; i < paddr + addr; i++) { portal_par_pa <<= 32; portal_par_pa |= range[i]; } portal_pa += portal_par_pa; for (; i < size + paddr + addr; i++) { portal_size = (uintmax_t)portal_size << 32; portal_size |= range[i]; } OF_prop_free(range); sc->sc_dp_size = portal_size; sc->sc_dp_pa = portal_pa; /* Find portals tied to CPUs */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { if (cpus >= mp_ncpus) break; if (!ofw_bus_node_is_compatible(child, "fsl,qman-portal")) { continue; } /* Checkout related cpu */ if (OF_getprop(child, "cpu-handle", (void *)&cpu, sizeof(cpu)) <= 0) { cpu = qman_portal_find_cpu(cpus); if (cpu <= 0) continue; } /* Acquire cpu number */ cpu_node = OF_instance_to_package(cpu); if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) { device_printf(dev, "Could not retrieve CPU number.\n"); return (ENXIO); } cpus++; if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) { device_printf(dev, "could not set up devinfo\n"); continue; } resource_list_init(&di.di_res); if (ofw_bus_reg_to_rl(dev, child, addr, size, &di.di_res)) { device_printf(dev, "%s: could not process 'reg' " "property\n", ofw_di.obd_name); ofw_bus_gen_destroy_devinfo(&ofw_di); continue; } if (ofw_bus_intr_to_rl(dev, child, &di.di_res, &intr_rid)) { device_printf(dev, "%s: could not process " "'interrupts' property\n", ofw_di.obd_name); resource_list_free(&di.di_res); ofw_bus_gen_destroy_devinfo(&ofw_di); continue; } di.di_intr_rid = intr_rid; if (dpaa_portal_alloc_res(dev, &di, cpu_num)) goto err; } ofw_bus_gen_destroy_devinfo(&ofw_di); return (qman_portals_attach(dev)); err: resource_list_free(&di.di_res); ofw_bus_gen_destroy_devinfo(&ofw_di); qman_portals_detach(dev); return (ENXIO); }
static int bman_portals_fdt_attach(device_t dev) { struct dpaa_portals_softc *sc; struct resource_list_entry *rle; phandle_t node, child, cpu_node; vm_paddr_t portal_pa; vm_size_t portal_size; uint32_t addr, size; ihandle_t cpu; int cpu_num, cpus, intr_rid; struct dpaa_portals_devinfo di; struct ofw_bus_devinfo ofw_di = {}; cpus = 0; sc = device_get_softc(dev); sc->sc_dev = dev; node = ofw_bus_get_node(dev); get_addr_props(node, &addr, &size); /* Find portals tied to CPUs */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { if (cpus >= mp_ncpus) break; if (!ofw_bus_node_is_compatible(child, "fsl,bman-portal")) { continue; } /* Checkout related cpu */ if (OF_getprop(child, "cpu-handle", (void *)&cpu, sizeof(cpu)) <= 0) { cpu = bman_portal_find_cpu(cpus); if (cpu <= 0) continue; } /* Acquire cpu number */ cpu_node = OF_instance_to_package(cpu); if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) { device_printf(dev, "Could not retrieve CPU number.\n"); return (ENXIO); } cpus++; if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) { device_printf(dev, "could not set up devinfo\n"); continue; } resource_list_init(&di.di_res); if (ofw_bus_reg_to_rl(dev, child, addr, size, &di.di_res)) { device_printf(dev, "%s: could not process 'reg' " "property\n", ofw_di.obd_name); ofw_bus_gen_destroy_devinfo(&ofw_di); continue; } if (ofw_bus_intr_to_rl(dev, child, &di.di_res, &intr_rid)) { device_printf(dev, "%s: could not process " "'interrupts' property\n", ofw_di.obd_name); resource_list_free(&di.di_res); ofw_bus_gen_destroy_devinfo(&ofw_di); continue; } di.di_intr_rid = intr_rid; ofw_reg_to_paddr(child, 0, &portal_pa, &portal_size, NULL); rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 0); if (sc->sc_dp_pa == 0) sc->sc_dp_pa = portal_pa - rle->start; portal_size = rle->end + 1; rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 1); portal_size = ulmax(rle->end + 1, portal_size); sc->sc_dp_size = ulmax(sc->sc_dp_size, portal_size); if (dpaa_portal_alloc_res(dev, &di, cpu_num)) goto err; } ofw_bus_gen_destroy_devinfo(&ofw_di); return (bman_portals_attach(dev)); err: resource_list_free(&di.di_res); ofw_bus_gen_destroy_devinfo(&ofw_di); bman_portals_detach(dev); return (ENXIO); }