Esempio n. 1
0
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));
}
Esempio n. 2
0
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));
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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);
}
Esempio n. 5
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));
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/*
 * 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);
}
Esempio n. 8
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);
}
Esempio n. 9
0
/*
 * 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);
}
Esempio n. 10
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);
}
Esempio n. 11
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);
}
Esempio n. 12
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);
}
Esempio n. 13
0
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);
}
Esempio n. 14
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);
}
Esempio n. 15
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);
}
Esempio n. 16
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);
}
Esempio n. 17
0
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);
}
Esempio n. 18
0
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);
}
Esempio n. 19
0
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);
}
Esempio n. 20
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);
}