int phy_get_by_ofw_property(device_t consumer_dev, phandle_t cnode, char *name, phy_t *phy) { pcell_t *cells; device_t phydev; int ncells, rv; intptr_t id; if (cnode <= 0) cnode = ofw_bus_get_node(consumer_dev); if (cnode <= 0) { device_printf(consumer_dev, "%s called on not ofw based device\n", __func__); return (ENXIO); } ncells = OF_getencprop_alloc(cnode, name, sizeof(pcell_t), (void **)&cells); if (ncells < 1) return (ENXIO); /* Tranlate provider to device. */ phydev = OF_device_from_xref(cells[0]); if (phydev == NULL) { OF_prop_free(cells); return (ENODEV); } /* Map phy to number. */ rv = PHY_MAP(phydev, cells[0], ncells - 1 , cells + 1, &id); OF_prop_free(cells); if (rv != 0) return (rv); return (phy_get_by_id(consumer_dev, phydev, id, phy)); }
int hwreset_get_by_ofw_idx(device_t consumer_dev, int idx, hwreset_t *rst) { phandle_t cnode, xnode; pcell_t *cells; device_t rstdev; int ncells, rv; intptr_t id; cnode = ofw_bus_get_node(consumer_dev); if (cnode <= 0) { device_printf(consumer_dev, "%s called on not ofw based device\n", __func__); return (ENXIO); } rv = ofw_bus_parse_xref_list_alloc(cnode, "resets", "#reset-cells", idx, &xnode, &ncells, &cells); if (rv != 0) return (rv); /* Tranlate provider to device */ rstdev = OF_device_from_xref(xnode); if (rstdev == NULL) { free(cells, M_OFWPROP); return (ENODEV); } /* Map reset to number */ rv = HWRESET_MAP(rstdev, xnode, ncells, cells, &id); free(cells, M_OFWPROP); if (rv != 0) return (rv); return (hwreset_get_by_id(consumer_dev, rstdev, id, rst)); }
static int mv_cp110_icu_attach(device_t dev) { struct mv_cp110_icu_softc *sc; phandle_t node, msi_parent; sc = device_get_softc(dev); sc->dev = dev; node = ofw_bus_get_node(dev); if (OF_getencprop(node, "msi-parent", &msi_parent, sizeof(phandle_t)) <= 0) { device_printf(dev, "cannot find msi-parent property\n"); return (ENXIO); } if ((sc->parent = OF_device_from_xref(msi_parent)) == NULL) { device_printf(dev, "cannot find msi-parent device\n"); return (ENXIO); } if (bus_alloc_resources(dev, mv_cp110_icu_res_spec, &sc->res) != 0) { device_printf(dev, "cannot allocate resources for device\n"); return (ENXIO); } if (intr_pic_register(dev, OF_xref_from_node(node)) == NULL) { device_printf(dev, "Cannot register ICU\n"); goto fail; } return (0); fail: bus_release_resources(dev, mv_cp110_icu_res_spec, &sc->res); return (ENXIO); }
static int rbled_attach(device_t dev) { struct rbled_softc *sc; phandle_t node; cell_t gp[2]; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); if (OF_getprop(node, "user_led", gp, sizeof(gp)) <= 0) return (ENXIO); sc->sc_gpio = OF_device_from_xref(gp[0]); if (sc->sc_gpio == NULL) { device_printf(dev, "No GPIO resource found!\n"); return (ENXIO); } sc->sc_ledpin = gp[1]; sc->sc_led = led_create(rbled_toggle, sc, "user_led"); if (sc->sc_led == NULL) return (ENXIO); return (0); }
int phy_get_by_ofw_idx(device_t consumer_dev, phandle_t cnode, int idx, phy_t *phy) { phandle_t xnode; pcell_t *cells; device_t phydev; int ncells, rv; intptr_t id; if (cnode <= 0) cnode = ofw_bus_get_node(consumer_dev); if (cnode <= 0) { device_printf(consumer_dev, "%s called on not ofw based device\n", __func__); return (ENXIO); } rv = ofw_bus_parse_xref_list_alloc(cnode, "phys", "#phy-cells", idx, &xnode, &ncells, &cells); if (rv != 0) return (rv); /* Tranlate provider to device. */ phydev = OF_device_from_xref(xnode); if (phydev == NULL) { OF_prop_free(cells); return (ENODEV); } /* Map phy to number. */ rv = PHY_MAP(phydev, xnode, ncells, cells, &id); OF_prop_free(cells); if (rv != 0) return (rv); return (phy_get_by_id(consumer_dev, phydev, id, phy)); }
static device_t jz4780_pinctrl_chip_lookup(struct jz4780_pinctrl_softc *sc, phandle_t chipxref) { device_t chipdev; chipdev = OF_device_from_xref(chipxref); return chipdev; }
/* * Utility functions for easier handling of OFW GPIO pins. * * !!! BEWARE !!! * GPIOBUS uses children's IVARs, so we cannot use this interface for cross * tree consumers. * */ static int gpio_pin_get_by_ofw_impl(device_t consumer, phandle_t cnode, char *prop_name, int idx, gpio_pin_t *out_pin) { phandle_t xref; pcell_t *cells; device_t busdev; struct gpiobus_pin pin; int ncells, rv; KASSERT(consumer != NULL && cnode > 0, ("both consumer and cnode required")); rv = ofw_bus_parse_xref_list_alloc(cnode, prop_name, "#gpio-cells", idx, &xref, &ncells, &cells); if (rv != 0) return (rv); /* Translate provider to device. */ pin.dev = OF_device_from_xref(xref); if (pin.dev == NULL) { OF_prop_free(cells); return (ENODEV); } /* Test if GPIO bus already exist. */ busdev = GPIO_GET_BUS(pin.dev); if (busdev == NULL) { OF_prop_free(cells); return (ENODEV); } /* Map GPIO pin. */ rv = gpio_map_gpios(pin.dev, cnode, OF_node_from_xref(xref), ncells, cells, &pin.pin, &pin.flags); OF_prop_free(cells); if (rv != 0) return (ENXIO); /* Reserve GPIO pin. */ rv = gpiobus_acquire_pin(busdev, pin.pin); if (rv != 0) return (EBUSY); *out_pin = malloc(sizeof(struct gpiobus_pin), M_DEVBUF, M_WAITOK | M_ZERO); **out_pin = pin; return (0); }
static int tegra_lic_attach(device_t dev) { struct tegra_lic_sc *sc; phandle_t node; phandle_t parent_xref; int i, rv; sc = device_get_softc(dev); sc->dev = dev; node = ofw_bus_get_node(dev); rv = OF_getencprop(node, "interrupt-parent", &parent_xref, sizeof(parent_xref)); if (rv <= 0) { device_printf(dev, "Cannot read parent node property\n"); goto fail; } sc->parent = OF_device_from_xref(parent_xref); if (sc->parent == NULL) { device_printf(dev, "Cannott find parent controller\n"); goto fail; } if (bus_alloc_resources(dev, lic_spec, sc->mem_res)) { device_printf(dev, "Cannott allocate resources\n"); goto fail; } /* Disable all interrupts, route all to irq */ for (i = 0; i < nitems(lic_spec); i++) { if (sc->mem_res[i] == NULL) continue; WR4(sc, i, LIC_CPU_IER_CLR, 0xFFFFFFFF); WR4(sc, i, LIC_CPU_IEP_CLASS, 0); } if (intr_pic_register(dev, OF_xref_from_node(node)) == NULL) { device_printf(dev, "Cannot register PIC\n"); goto fail; } return (0); fail: bus_release_resources(dev, lic_spec, sc->mem_res); return (ENXIO); }
/* * Loop through all the tuples in the resets= property for a device, asserting * or deasserting each reset. * * Be liberal about errors for now: warn about a failure to (de)assert but keep * trying with any other resets in the list. Return ENXIO if any errors were * found, and let the caller decide whether the problem is fatal. */ static int assert_deassert_all(device_t consumer, boolean_t assert) { phandle_t rnode; device_t resetdev; int resetnum, err, i, ncells; uint32_t *resets; boolean_t anyerrors; rnode = ofw_bus_get_node(consumer); ncells = OF_getencprop_alloc(rnode, "resets", sizeof(*resets), (void **)&resets); if (!assert && ncells < 2) { device_printf(consumer, "Warning: No resets specified in fdt " "data; device may not function."); return (ENXIO); } anyerrors = false; for (i = 0; i < ncells; i += 2) { resetdev = OF_device_from_xref(resets[i]); resetnum = resets[i + 1]; if (resetdev == NULL) { if (!assert) device_printf(consumer, "Warning: can not find " "driver for reset number %u; device may " "not function\n", resetnum); anyerrors = true; continue; } if (assert) err = FDT_RESET_ASSERT(resetdev, resetnum); else err = FDT_RESET_DEASSERT(resetdev, resetnum); if (err != 0) { if (!assert) device_printf(consumer, "Warning: failed to " "deassert reset number %u; device may not " "function\n", resetnum); anyerrors = true; } } free(resets, M_OFWPROP); return (anyerrors ? ENXIO : 0); }
static int tegra124_coretemp_ofw_parse(struct tegra124_coretemp_softc *sc) { int rv, ncells; phandle_t node, xnode; pcell_t *cells; node = OF_peer(0); node = ofw_bus_find_child(node, "thermal-zones"); if (node <= 0) { device_printf(sc->dev, "Cannot find 'thermal-zones'.\n"); return (ENXIO); } node = ofw_bus_find_child(node, "cpu"); if (node <= 0) { device_printf(sc->dev, "Cannot find 'cpu'\n"); return (ENXIO); } rv = ofw_bus_parse_xref_list_alloc(node, "thermal-sensors", "#thermal-sensor-cells", 0, &xnode, &ncells, &cells); if (rv != 0) { device_printf(sc->dev, "Cannot parse 'thermal-sensors' property.\n"); return (ENXIO); } if (ncells != 1) { device_printf(sc->dev, "Invalid format of 'thermal-sensors' property(%d).\n", ncells); return (ENXIO); } sc->tsens_id = 0x100 + sc->cpu_id; //cells[0]; OF_prop_free(cells); sc->tsens_dev = OF_device_from_xref(xnode); if (sc->tsens_dev == NULL) { device_printf(sc->dev, "Cannot find thermal sensors device."); return (ENXIO); } return (0); }
/* * Loop through all the tuples in the clocks= property for a device, enabling or * disabling each clock. * * Be liberal about errors for now: warn about a failure to enable but keep * trying with any other clocks in the list. Return ENXIO if any errors were * found, and let the caller decide whether the problem is fatal. */ static int enable_disable_all(device_t consumer, boolean_t enable) { phandle_t cnode; device_t clockdev; int clocknum, err, i, ncells; uint32_t *clks; boolean_t anyerrors; cnode = ofw_bus_get_node(consumer); ncells = OF_getencprop_alloc(cnode, "clocks", sizeof(*clks), (void **)&clks); if (enable && ncells < 2) { device_printf(consumer, "Warning: No clocks specified in fdt " "data; device may not function."); return (ENXIO); } anyerrors = false; for (i = 0; i < ncells; i += 2) { clockdev = OF_device_from_xref(clks[i]); clocknum = clks[i + 1]; if (clockdev == NULL) { if (enable) device_printf(consumer, "Warning: can not find " "driver for clock number %u; device may not " "function\n", clocknum); anyerrors = true; continue; } if (enable) err = FDT_CLOCK_ENABLE(clockdev, clocknum); else err = FDT_CLOCK_DISABLE(clockdev, clocknum); if (err != 0) { if (enable) device_printf(consumer, "Warning: failed to " "enable clock number %u; device may not " "function\n", clocknum); anyerrors = true; } } free(clks, M_OFWPROP); return (anyerrors ? ENXIO : 0); }
static int omap4_wugen_attach(device_t dev) { struct omap4_wugen_sc *sc; phandle_t node; phandle_t parent_xref; int rid, rv; sc = device_get_softc(dev); sc->sc_dev = dev; node = ofw_bus_get_node(dev); rv = OF_getencprop(node, "interrupt-parent", &parent_xref, sizeof(parent_xref)); if (rv <= 0) { device_printf(dev, "can't read parent node property\n"); goto fail; } sc->sc_parent = OF_device_from_xref(parent_xref); if (sc->sc_parent == NULL) { device_printf(dev, "can't find parent controller\n"); goto fail; } rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_mem_res == NULL) { device_printf(dev, "can't allocate resources\n"); return (ENXIO); } if (intr_pic_register(dev, OF_xref_from_node(node)) == NULL) { device_printf(dev, "can't register PIC\n"); goto fail; } return (0); fail: omap4_wugen_detach(dev); return (ENXIO); }
int nvmem_write_cell_by_idx(phandle_t node, int idx, void *cell, size_t buflen) { phandle_t cell_node, prov_node; device_t provider; uint32_t reg[2]; int rv; rv = nvmem_get_cell_node(node, idx, &cell_node); if (rv != 0) return (rv); prov_node = OF_parent(cell_node); if (OF_hasprop(prov_node, "read-only")) return (ENXIO); /* Validate the reg property */ if (OF_getencprop(cell_node, "reg", reg, sizeof(reg)) != sizeof(reg)) { if (bootverbose) printf("nvmem_get_cell_by_idx: Cannot parse reg property of cell %d\n", idx); return (ENXIO); } if (buflen != reg[1]) return (EINVAL); provider = OF_device_from_xref(OF_xref_from_node(prov_node)); if (provider == NULL) { if (bootverbose) printf("nvmem_get_cell_by_idx: Cannot find the nvmem device\n"); return (ENXIO); } rv = NVMEM_WRITE(provider, reg[0], reg[1], cell); if (rv != 0) { return (rv); } return (0); }
static int a10codec_mixer_init(struct snd_mixer *m) { struct a10codec_info *sc = mix_getdevinfo(m); pcell_t prop[4]; phandle_t node; device_t gpio; uint32_t val; ssize_t len; int pin; mix_setdevs(m, SOUND_MASK_VOLUME | SOUND_MASK_LINE | SOUND_MASK_RECLEV); mix_setrecdevs(m, SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC); /* Unmute input source to PA */ val = CODEC_READ(sc, AC_DAC_ACTL); val |= DAC_ACTL_PAMUTE; CODEC_WRITE(sc, AC_DAC_ACTL, val); /* Enable PA */ val = CODEC_READ(sc, AC_ADC_ACTL); val |= ADC_ACTL_PA_EN; CODEC_WRITE(sc, AC_ADC_ACTL, val); /* Unmute PA */ node = ofw_bus_get_node(sc->dev); len = OF_getencprop(node, "allwinner,pa-gpios", prop, sizeof(prop)); if (len > 0 && (len / sizeof(prop[0])) == 4) { gpio = OF_device_from_xref(prop[0]); if (gpio != NULL) { pin = prop[1] * 32 + prop[2]; GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT); GPIO_PIN_SET(gpio, pin, GPIO_PIN_LOW); } } return (0); }
int tegra_drm_encoder_attach(struct tegra_drm_encoder *output, phandle_t node) { int rv; phandle_t ddc; /* XXX parse output panel here */ rv = OF_getencprop_alloc(node, "nvidia,edid", (void **)&output->edid); /* EDID exist but have invalid size */ if ((rv >= 0) && (rv != sizeof(struct edid))) { device_printf(output->dev, "Malformed \"nvidia,edid\" property\n"); if (output->edid != NULL) free(output->edid, M_OFWPROP); return (ENXIO); } gpio_pin_get_by_ofw_property(output->dev, node, "nvidia,hpd-gpio", &output->gpio_hpd); ddc = 0; OF_getencprop(node, "nvidia,ddc-i2c-bus", &ddc, sizeof(ddc)); if (ddc > 0) output->ddc = OF_device_from_xref(ddc); if ((output->edid == NULL) && (output->ddc == NULL)) return (ENXIO); if (output->gpio_hpd != NULL) { output->connector.polled = // DRM_CONNECTOR_POLL_HPD; DRM_CONNECTOR_POLL_DISCONNECT | DRM_CONNECTOR_POLL_CONNECT; } return (0); }
int fdt_clock_get_info(device_t consumer, int n, struct fdt_clock_info *info) { phandle_t cnode; device_t clockdev; int clocknum, err, ncells; uint32_t *clks; cnode = ofw_bus_get_node(consumer); ncells = OF_getencprop_alloc(cnode, "clocks", sizeof(*clks), (void **)&clks); if (ncells <= 0) return (ENXIO); n *= 2; if (ncells <= n) err = ENXIO; else { clockdev = OF_device_from_xref(clks[n]); if (clockdev == NULL) err = ENXIO; else { /* * Make struct contents minimally valid, then call * provider to fill in what it knows (provider can * override anything it wants to). */ clocknum = clks[n + 1]; bzero(info, sizeof(*info)); info->provider = clockdev; info->index = clocknum; info->name = ""; err = FDT_CLOCK_GET_INFO(clockdev, clocknum, info); } } free(clks, M_OFWPROP); return (err); }
static int rb_nand_attach(device_t dev) { struct rb_nand_softc *sc; phandle_t node; uint32_t ale[2],cle[2],nce[2],rdy[2]; u_long size,start; int err; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); if (OF_getprop(node, "ale", ale, sizeof(ale)) <= 0) { return (ENXIO); } if (OF_getprop(node, "cle", cle, sizeof(cle)) <= 0) { return (ENXIO); } if (OF_getprop(node, "nce", nce, sizeof(nce)) <= 0) { return (ENXIO); } if (OF_getprop(node, "rdy", rdy, sizeof(rdy)) <= 0) { return (ENXIO); } if (ale[0] != cle[0] || ale[0] != nce[0] || ale[0] != rdy[0]) { device_printf(dev, "GPIO handles for signals must match.\n"); return (ENXIO); } sc->sc_ale_pin = ale[1]; sc->sc_cle_pin = cle[1]; sc->sc_nce_pin = nce[1]; sc->sc_rdy_pin = rdy[1]; sc->sc_gpio = OF_device_from_xref(ale[0]); if (sc->sc_gpio == NULL) { device_printf(dev, "No GPIO resource found!\n"); return (ENXIO); } sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, RF_ACTIVE); if (sc->sc_mem == NULL) { device_printf(dev, "could not allocate resources!\n"); return (ENXIO); } start = rman_get_start(sc->sc_mem); size = rman_get_size(sc->sc_mem); if (law_enable(OCP85XX_TGTIF_LBC, start, size) != 0) { bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->sc_mem); device_printf(dev, "could not allocate local address window.\n"); return (ENXIO); } nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL); err = nandbus_create(dev); return (err); }
static int aml8726_usb_phy_attach(device_t dev) { struct aml8726_usb_phy_softc *sc = device_get_softc(dev); int err; int npwr_en; pcell_t *prop; phandle_t node; ssize_t len; uint32_t div; uint32_t i; uint32_t mode_a; uint32_t mode_b; uint32_t value; sc->dev = dev; if (aml8726_usb_phy_mode("/soc/usb@c9040000", &mode_a) != 0) { device_printf(dev, "missing usb@c9040000 node in FDT\n"); return (ENXIO); } if (aml8726_usb_phy_mode("/soc/usb@c90c0000", &mode_b) != 0) { device_printf(dev, "missing usb@c90c0000 node in FDT\n"); return (ENXIO); } if (bus_alloc_resources(dev, aml8726_usb_phy_spec, sc->res)) { device_printf(dev, "can not allocate resources for device\n"); return (ENXIO); } node = ofw_bus_get_node(dev); err = 0; len = OF_getencprop_alloc(node, "usb-pwr-en", 3 * sizeof(pcell_t), (void **)&prop); npwr_en = (len > 0) ? len : 0; sc->npwr_en = 0; sc->pwr_en = (struct aml8726_usb_phy_gpio *) malloc(npwr_en * sizeof (*sc->pwr_en), M_DEVBUF, M_WAITOK); for (i = 0; i < npwr_en; i++) { sc->pwr_en[i].dev = OF_device_from_xref(prop[i * 3]); sc->pwr_en[i].pin = prop[i * 3 + 1]; sc->pwr_en[i].pol = prop[i * 3 + 2]; if (sc->pwr_en[i].dev == NULL) { err = 1; break; } } free(prop, M_OFWPROP); if (err) { device_printf(dev, "unable to parse gpio\n"); goto fail; } /* Turn on power by setting pin and then enabling output driver. */ for (i = 0; i < npwr_en; i++) { if (GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, PIN_ON_FLAG(sc->pwr_en[i].pol)) != 0 || GPIO_PIN_SETFLAGS(sc->pwr_en[i].dev, sc->pwr_en[i].pin, GPIO_PIN_OUTPUT) != 0) { device_printf(dev, "could not use gpio to control power\n"); goto fail; } sc->npwr_en++; } /* * Configure the clock source and divider. */ div = 2; value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG); value &= ~(AML_USB_PHY_CFG_CLK_DIV_MASK | AML_USB_PHY_CFG_CLK_SEL_MASK); value &= ~(AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST); value &= ~(AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST); value &= ~(AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST); value &= ~(AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR); value |= AML_USB_PHY_CFG_CLK_SEL_XTAL; value |= ((div - 1) << AML_USB_PHY_CFG_CLK_DIV_SHIFT) & AML_USB_PHY_CFG_CLK_DIV_MASK; value |= AML_USB_PHY_CFG_CLK_EN; CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); /* * Issue the reset sequence. */ value |= (AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST); CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); DELAY(200); value &= ~(AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST); CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); DELAY(200); value |= (AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST); CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); DELAY(200); value &= ~(AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST); CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); DELAY(200); value |= (AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST); CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); DELAY(200); value &= ~(AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST); CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); DELAY(200); value |= (AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR); CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); DELAY(200); /* * Enable by clearing the power on reset. */ value &= ~(AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR); CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); DELAY(200); /* * Check if the clock was detected. */ value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG); if ((value & AML_USB_PHY_CFG_CLK_DETECTED) != AML_USB_PHY_CFG_CLK_DETECTED) device_printf(dev, "PHY Clock not detected\n"); /* * Configure the mode for each port. */ value = CSR_READ_4(sc, AML_USB_PHY_MISC_A_REG); value &= ~(AML_USB_PHY_MISC_ID_OVERIDE_EN | AML_USB_PHY_MISC_ID_OVERIDE_DEVICE | AML_USB_PHY_MISC_ID_OVERIDE_HOST); value |= mode_a; CSR_WRITE_4(sc, AML_USB_PHY_MISC_A_REG, value); value = CSR_READ_4(sc, AML_USB_PHY_MISC_B_REG); value &= ~(AML_USB_PHY_MISC_ID_OVERIDE_EN | AML_USB_PHY_MISC_ID_OVERIDE_DEVICE | AML_USB_PHY_MISC_ID_OVERIDE_HOST); value |= mode_b; CSR_WRITE_4(sc, AML_USB_PHY_MISC_B_REG, value); CSR_BARRIER(sc, AML_USB_PHY_MISC_B_REG); return (0); fail: /* In the event of problems attempt to turn things back off. */ i = sc->npwr_en; while (i-- != 0) { GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, PIN_OFF_FLAG(sc->pwr_en[i].pol)); } free (sc->pwr_en, M_DEVBUF); sc->pwr_en = NULL; bus_release_resources(dev, aml8726_usb_phy_spec, sc->res); return (ENXIO); }
static int axgbe_attach(device_t dev) { struct axgbe_softc *sc; struct ifnet *ifp; pcell_t phy_handle; device_t phydev; phandle_t node, phy_node; struct resource *mac_res[11]; struct resource *phy_res[4]; ssize_t len; int error, i, j; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); if (OF_getencprop(node, "phy-handle", &phy_handle, sizeof(phy_handle)) <= 0) { phy_node = node; if (bus_alloc_resources(dev, mac_spec, mac_res)) { device_printf(dev, "could not allocate phy resources\n"); return (ENXIO); } sc->prv.xgmac_res = mac_res[0]; sc->prv.xpcs_res = mac_res[1]; sc->prv.rxtx_res = mac_res[2]; sc->prv.sir0_res = mac_res[3]; sc->prv.sir1_res = mac_res[4]; sc->prv.dev_irq_res = mac_res[5]; sc->prv.per_channel_irq = OF_hasprop(node, XGBE_DMA_IRQS_PROPERTY); for (i = 0, j = 6; j < nitems(mac_res) - 1 && mac_res[j + 1] != NULL; i++, j++) { if (sc->prv.per_channel_irq) { sc->prv.chan_irq_res[i] = mac_res[j]; } } /* The last entry is the auto-negotiation interrupt */ sc->prv.an_irq_res = mac_res[j]; } else { phydev = OF_device_from_xref(phy_handle); phy_node = ofw_bus_get_node(phydev); if (bus_alloc_resources(phydev, old_phy_spec, phy_res)) { device_printf(dev, "could not allocate phy resources\n"); return (ENXIO); } if (bus_alloc_resources(dev, old_mac_spec, mac_res)) { device_printf(dev, "could not allocate mac resources\n"); return (ENXIO); } sc->prv.rxtx_res = phy_res[0]; sc->prv.sir0_res = phy_res[1]; sc->prv.sir1_res = phy_res[2]; sc->prv.an_irq_res = phy_res[3]; sc->prv.xgmac_res = mac_res[0]; sc->prv.xpcs_res = mac_res[1]; sc->prv.dev_irq_res = mac_res[2]; sc->prv.per_channel_irq = OF_hasprop(node, XGBE_DMA_IRQS_PROPERTY); if (sc->prv.per_channel_irq) { for (i = 0, j = 3; i < nitems(sc->prv.chan_irq_res) && mac_res[j] != NULL; i++, j++) { sc->prv.chan_irq_res[i] = mac_res[j]; } } } if ((len = OF_getproplen(node, "mac-address")) < 0) { device_printf(dev, "No mac-address property\n"); return (EINVAL); } if (len != ETHER_ADDR_LEN) return (EINVAL); OF_getprop(node, "mac-address", sc->mac_addr, ETHER_ADDR_LEN); sc->prv.netdev = ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(dev, "Cannot alloc ifnet\n"); return (ENXIO); } sc->prv.dev = dev; sc->prv.dmat = bus_get_dma_tag(dev); sc->prv.phy.advertising = ADVERTISED_10000baseKR_Full | ADVERTISED_1000baseKX_Full; /* * Read the needed properties from the phy node. */ /* This is documented as optional, but Linux requires it */ if (OF_getencprop(phy_node, XGBE_SPEEDSET_PROPERTY, &sc->prv.speed_set, sizeof(sc->prv.speed_set)) <= 0) { device_printf(dev, "%s property is missing\n", XGBE_SPEEDSET_PROPERTY); return (EINVAL); } error = axgbe_get_optional_prop(dev, phy_node, XGBE_BLWC_PROPERTY, sc->prv.serdes_blwc, sizeof(sc->prv.serdes_blwc)); if (error > 0) { return (error); } else if (error < 0) { sc->prv.serdes_blwc[0] = XGBE_SPEED_1000_BLWC; sc->prv.serdes_blwc[1] = XGBE_SPEED_2500_BLWC; sc->prv.serdes_blwc[2] = XGBE_SPEED_10000_BLWC; } error = axgbe_get_optional_prop(dev, phy_node, XGBE_CDR_RATE_PROPERTY, sc->prv.serdes_cdr_rate, sizeof(sc->prv.serdes_cdr_rate)); if (error > 0) { return (error); } else if (error < 0) { sc->prv.serdes_cdr_rate[0] = XGBE_SPEED_1000_CDR; sc->prv.serdes_cdr_rate[1] = XGBE_SPEED_2500_CDR; sc->prv.serdes_cdr_rate[2] = XGBE_SPEED_10000_CDR; } error = axgbe_get_optional_prop(dev, phy_node, XGBE_PQ_SKEW_PROPERTY, sc->prv.serdes_pq_skew, sizeof(sc->prv.serdes_pq_skew)); if (error > 0) { return (error); } else if (error < 0) { sc->prv.serdes_pq_skew[0] = XGBE_SPEED_1000_PQ; sc->prv.serdes_pq_skew[1] = XGBE_SPEED_2500_PQ; sc->prv.serdes_pq_skew[2] = XGBE_SPEED_10000_PQ; } error = axgbe_get_optional_prop(dev, phy_node, XGBE_TX_AMP_PROPERTY, sc->prv.serdes_tx_amp, sizeof(sc->prv.serdes_tx_amp)); if (error > 0) { return (error); } else if (error < 0) { sc->prv.serdes_tx_amp[0] = XGBE_SPEED_1000_TXAMP; sc->prv.serdes_tx_amp[1] = XGBE_SPEED_2500_TXAMP; sc->prv.serdes_tx_amp[2] = XGBE_SPEED_10000_TXAMP; } error = axgbe_get_optional_prop(dev, phy_node, XGBE_DFE_CFG_PROPERTY, sc->prv.serdes_dfe_tap_cfg, sizeof(sc->prv.serdes_dfe_tap_cfg)); if (error > 0) { return (error); } else if (error < 0) { sc->prv.serdes_dfe_tap_cfg[0] = XGBE_SPEED_1000_DFE_TAP_CONFIG; sc->prv.serdes_dfe_tap_cfg[1] = XGBE_SPEED_2500_DFE_TAP_CONFIG; sc->prv.serdes_dfe_tap_cfg[2] = XGBE_SPEED_10000_DFE_TAP_CONFIG; } error = axgbe_get_optional_prop(dev, phy_node, XGBE_DFE_ENA_PROPERTY, sc->prv.serdes_dfe_tap_ena, sizeof(sc->prv.serdes_dfe_tap_ena)); if (error > 0) { return (error); } else if (error < 0) { sc->prv.serdes_dfe_tap_ena[0] = XGBE_SPEED_1000_DFE_TAP_ENABLE; sc->prv.serdes_dfe_tap_ena[1] = XGBE_SPEED_2500_DFE_TAP_ENABLE; sc->prv.serdes_dfe_tap_ena[2] = XGBE_SPEED_10000_DFE_TAP_ENABLE; } /* Check if the NIC is DMA coherent */ sc->prv.coherent = OF_hasprop(node, "dma-coherent"); if (sc->prv.coherent) { sc->prv.axdomain = XGBE_DMA_OS_AXDOMAIN; sc->prv.arcache = XGBE_DMA_OS_ARCACHE; sc->prv.awcache = XGBE_DMA_OS_AWCACHE; } else { sc->prv.axdomain = XGBE_DMA_SYS_AXDOMAIN; sc->prv.arcache = XGBE_DMA_SYS_ARCACHE; sc->prv.awcache = XGBE_DMA_SYS_AWCACHE; } /* Create the lock & workqueues */ spin_lock_init(&sc->prv.xpcs_lock); sc->prv.dev_workqueue = taskqueue_create("axgbe", M_WAITOK, taskqueue_thread_enqueue, &sc->prv.dev_workqueue); taskqueue_start_threads(&sc->prv.dev_workqueue, 1, PI_NET, "axgbe taskq"); /* Set the needed pointers */ xgbe_init_function_ptrs_phy(&sc->prv.phy_if); xgbe_init_function_ptrs_dev(&sc->prv.hw_if); xgbe_init_function_ptrs_desc(&sc->prv.desc_if); /* Reset the hardware */ sc->prv.hw_if.exit(&sc->prv); /* Read the hardware features */ xgbe_get_all_hw_features(&sc->prv); /* Set default values */ sc->prv.pblx8 = DMA_PBL_X8_ENABLE; sc->prv.tx_desc_count = XGBE_TX_DESC_CNT; sc->prv.tx_sf_mode = MTL_TSF_ENABLE; sc->prv.tx_threshold = MTL_TX_THRESHOLD_64; sc->prv.tx_pbl = DMA_PBL_16; sc->prv.tx_osp_mode = DMA_OSP_ENABLE; sc->prv.rx_desc_count = XGBE_RX_DESC_CNT; sc->prv.rx_sf_mode = MTL_RSF_DISABLE; sc->prv.rx_threshold = MTL_RX_THRESHOLD_64; sc->prv.rx_pbl = DMA_PBL_16; sc->prv.pause_autoneg = 1; sc->prv.tx_pause = 1; sc->prv.rx_pause = 1; sc->prv.phy_speed = SPEED_UNKNOWN; sc->prv.power_down = 0; /* TODO: Limit to min(ncpus, hw rings) */ sc->prv.tx_ring_count = 1; sc->prv.tx_q_count = 1; sc->prv.rx_ring_count = 1; sc->prv.rx_q_count = sc->prv.hw_feat.rx_q_cnt; /* Init the PHY */ sc->prv.phy_if.phy_init(&sc->prv); /* Set the coalescing */ xgbe_init_rx_coalesce(&sc->prv); xgbe_init_tx_coalesce(&sc->prv); if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_init = axgbe_init; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = axgbe_ioctl; ifp->if_transmit = xgbe_xmit; ifp->if_qflush = axgbe_qflush; ifp->if_get_counter = axgbe_get_counter; /* TODO: Support HW offload */ ifp->if_capabilities = 0; ifp->if_capenable = 0; ifp->if_hwassist = 0; ether_ifattach(ifp, sc->mac_addr); ifmedia_init(&sc->media, IFM_IMASK, axgbe_media_change, axgbe_media_status); #ifdef notyet ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL); #endif ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL); ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); set_bit(XGBE_DOWN, &sc->prv.dev_state); if (xgbe_open(ifp) < 0) { device_printf(dev, "ndo_open failed\n"); return (ENXIO); } return (0); }
static int ofw_gpiobus_parse_gpios_impl(device_t consumer, phandle_t cnode, char *pname, struct gpiobus_softc *bussc, struct gpiobus_pin **pins) { int gpiocells, i, j, ncells, npins; pcell_t *gpios; phandle_t gpio; ncells = OF_getencprop_alloc(cnode, pname, sizeof(*gpios), (void **)&gpios); if (ncells == -1) { device_printf(consumer, "Warning: No %s specified in fdt data; " "device may not function.\n", pname); return (-1); } /* * The gpio-specifier is controller independent, the first pcell has * the reference to the GPIO controller phandler. * Count the number of encoded gpio-specifiers on the first pass. */ i = 0; npins = 0; while (i < ncells) { /* Allow NULL specifiers. */ if (gpios[i] == 0) { npins++; i++; continue; } gpio = OF_node_from_xref(gpios[i]); /* If we have bussc, ignore devices from other gpios. */ if (bussc != NULL) if (ofw_bus_get_node(bussc->sc_dev) != gpio) return (0); /* * Check for gpio-controller property and read the #gpio-cells * for this GPIO controller. */ if (!OF_hasprop(gpio, "gpio-controller") || OF_getencprop(gpio, "#gpio-cells", &gpiocells, sizeof(gpiocells)) < 0) { device_printf(consumer, "gpio reference is not a gpio-controller.\n"); OF_prop_free(gpios); return (-1); } if (ncells - i < gpiocells + 1) { device_printf(consumer, "%s cells doesn't match #gpio-cells.\n", pname); return (-1); } npins++; i += gpiocells + 1; } if (npins == 0 || pins == NULL) { if (npins == 0) device_printf(consumer, "no pin specified in %s.\n", pname); OF_prop_free(gpios); return (npins); } *pins = malloc(sizeof(struct gpiobus_pin) * npins, M_DEVBUF, M_NOWAIT | M_ZERO); if (*pins == NULL) { OF_prop_free(gpios); return (-1); } /* Decode the gpio specifier on the second pass. */ i = 0; j = 0; while (i < ncells) { /* Allow NULL specifiers. */ if (gpios[i] == 0) { j++; i++; continue; } gpio = OF_node_from_xref(gpios[i]); /* Read gpio-cells property for this GPIO controller. */ if (OF_getencprop(gpio, "#gpio-cells", &gpiocells, sizeof(gpiocells)) < 0) { device_printf(consumer, "gpio does not have the #gpio-cells property.\n"); goto fail; } /* Return the device reference for the GPIO controller. */ (*pins)[j].dev = OF_device_from_xref(gpios[i]); if ((*pins)[j].dev == NULL) { device_printf(consumer, "no device registered for the gpio controller.\n"); goto fail; } /* * If the gpiobus softc is NULL we use the GPIO_GET_BUS() to * retrieve it. The GPIO_GET_BUS() method is only valid after * the child is probed and attached. */ if (bussc == NULL) { if (GPIO_GET_BUS((*pins)[j].dev) == NULL) { device_printf(consumer, "no gpiobus reference for %s.\n", device_get_nameunit((*pins)[j].dev)); goto fail; } bussc = device_get_softc(GPIO_GET_BUS((*pins)[j].dev)); } /* Get the GPIO pin number and flags. */ if (gpio_map_gpios((*pins)[j].dev, cnode, gpio, gpiocells, &gpios[i + 1], &(*pins)[j].pin, &(*pins)[j].flags) != 0) { device_printf(consumer, "cannot map the gpios specifier.\n"); goto fail; } /* Reserve the GPIO pin. */ if (gpiobus_acquire_pin(bussc->sc_busdev, (*pins)[j].pin) != 0) goto fail; j++; i += gpiocells + 1; } OF_prop_free(gpios); return (npins); fail: OF_prop_free(gpios); free(*pins, M_DEVBUF); return (-1); }