Exemplo n.º 1
0
static int
nvmem_get_cell_node(phandle_t node, int idx, phandle_t *cell)
{
	phandle_t *p_cell;
	phandle_t cell_node;
	int ncell;

	if (!OF_hasprop(node, "nvmem-cells") ||
	    !OF_hasprop(node, "nvmem-cell-names"))
		return (ENOENT);

	ncell = OF_getencprop_alloc_multi(node, "nvmem-cells", sizeof(*p_cell), (void **)&p_cell);
	if (ncell <= 0)
		return (ENOENT);

	cell_node = OF_node_from_xref(p_cell[idx]);
	if (cell_node == p_cell[idx]) {
		if (bootverbose)
			printf("nvmem_get_node: Cannot resolve phandle %x\n",
			    p_cell[idx]);
		OF_prop_free(p_cell);
		return (ENOENT);
	}

	OF_prop_free(p_cell);
	*cell = cell_node;

	return (0);
}
Exemplo n.º 2
0
int
opal_check(void)
{
	phandle_t opal;
	cell_t val[2];

	if (opal_initialized)
		return (0);

	opal = OF_finddevice("/ibm,opal");
	if (opal == -1)
		return (ENOENT);

	if (!OF_hasprop(opal, "opal-base-address") ||
	    !OF_hasprop(opal, "opal-entry-address"))
		return (ENOENT);
	
	OF_getencprop(opal, "opal-base-address", val, sizeof(val));
	opal_data = ((uint64_t)val[0] << 32) | val[1];
	OF_getencprop(opal, "opal-entry-address", val, sizeof(val));
	opal_entrypoint = ((uint64_t)val[0] << 32) | val[1];

	opal_msr = mfmsr() & ~(PSL_EE | PSL_IR | PSL_DR | PSL_SE);

	opal_initialized = 1;

	return (0);
}
Exemplo n.º 3
0
static int
parse_dts(struct ckb_softc *sc)
{
	phandle_t node;
	pcell_t dts_value;
	pcell_t *keymap;
	int len, ret;
	const char *keymap_prop = NULL;

	if ((node = ofw_bus_get_node(sc->dev)) == -1)
		return (ENXIO);

	if ((len = OF_getproplen(node, "google,key-rows")) <= 0)
		return (ENXIO);
	OF_getencprop(node, "google,key-rows", &dts_value, len);
	sc->rows = dts_value;

	if ((len = OF_getproplen(node, "google,key-columns")) <= 0)
		return (ENXIO);
	OF_getencprop(node, "google,key-columns", &dts_value, len);
	sc->cols = dts_value;

	if ((len = OF_getproplen(node, "freebsd,intr-gpio")) <= 0)
		return (ENXIO);
	OF_getencprop(node, "freebsd,intr-gpio", &dts_value, len);
	sc->gpio = dts_value;

	if (OF_hasprop(node, "freebsd,keymap")) {
		keymap_prop = "freebsd,keymap";
		device_printf(sc->dev, "using FreeBSD-specific keymap from FDT\n");
	} else if (OF_hasprop(node, "linux,keymap")) {
		keymap_prop = "linux,keymap";
		device_printf(sc->dev, "using Linux keymap from FDT\n");
	} else {
		device_printf(sc->dev, "using built-in keymap\n");
	}

	if (keymap_prop != NULL) {
		if ((ret = read_keymap(node, keymap_prop, &keymap, &len))) {
			device_printf(sc->dev,
			     "failed to read keymap from FDT: %d\n", ret);
			return (ret);
		}
		ret = parse_keymap(sc, keymap, len);
		free(keymap, M_DEVBUF);
		if (ret) {
			return (ret);
		}
	} else {
		if ((ret = parse_keymap(sc, default_keymap, KEYMAP_LEN))) {
			return (ret);
		}
	}

	if ((sc->rows == 0) || (sc->cols == 0) || (sc->gpio == 0))
		return (ENXIO);

	return (0);
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
0
static int
reset_hsic_hub(struct exynos_ehci_softc *esc, phandle_t hub)
{
	device_t gpio_dev;
	pcell_t pin;

	/* TODO: check that hub is compatible with "smsc,usb3503" */
	if (!OF_hasprop(hub, "freebsd,reset-gpio")) {
		return (1);
	}

	if (OF_getencprop(hub, "freebsd,reset-gpio", &pin, sizeof(pin)) < 0) {
		device_printf(esc->dev,
		    "failed to decode reset GPIO pin number for HSIC hub\n");
		return (1);
	}

	/* Get the GPIO device, we need this to give power to USB */
	gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
	if (gpio_dev == NULL) {
		device_printf(esc->dev, "Cant find gpio device\n");
		return (1);
	}

	GPIO_PIN_SET(gpio_dev, pin, GPIO_PIN_LOW);
	DELAY(100);
	GPIO_PIN_SET(gpio_dev, pin, GPIO_PIN_HIGH);

	return (0);
}
Exemplo n.º 6
0
static int
opaldev_probe(device_t dev)
{
	phandle_t iparent;
	pcell_t *irqs;
	int i, n_irqs;

	if (!ofw_bus_is_compatible(dev, "ibm,opal-v3"))
		return (ENXIO);
	if (opal_check() != 0)
		return (ENXIO);

	device_set_desc(dev, "OPAL Abstraction Firmware");

	/* Manually add IRQs before attaching */
	if (OF_hasprop(ofw_bus_get_node(dev), "opal-interrupts")) {
		iparent = OF_finddevice("/interrupt-controller@0");
		iparent = OF_xref_from_node(iparent);

		n_irqs = OF_getproplen(ofw_bus_get_node(dev),
                    "opal-interrupts") / sizeof(*irqs);
		irqs = malloc(n_irqs * sizeof(*irqs), M_DEVBUF, M_WAITOK);
		OF_getencprop(ofw_bus_get_node(dev), "opal-interrupts", irqs,
		    n_irqs * sizeof(*irqs));
		for (i = 0; i < n_irqs; i++)
			bus_set_resource(dev, SYS_RES_IRQ, i,
			    ofw_bus_map_intr(dev, iparent, 1, &irqs[i]), 1);
		free(irqs, M_DEVBUF);
	}


	return (BUS_PROBE_SPECIFIC);
}
Exemplo n.º 7
0
static int
jz4780_pinctrl_attach(device_t dev)
{
	struct jz4780_pinctrl_softc *sc;
	struct resource_list *rs;
	struct resource_list_entry *re;
	phandle_t dt_parent, dt_child;
	int i, ret;

	sc = device_get_softc(dev);
	sc->dev = dev;

	/*
	 * Fetch our own resource list to dole memory between children
	 */
	rs = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
	if (rs == NULL)
		return (ENXIO);
	re = resource_list_find(rs, SYS_RES_MEMORY, 0);
	if (re == NULL)
		return (ENXIO);

	simplebus_init(dev, 0);

	/* Iterate over this node children, looking for pin controllers */
	dt_parent = ofw_bus_get_node(dev);
	i = 0;
	for (dt_child = OF_child(dt_parent); dt_child != 0;
	    dt_child = OF_peer(dt_child)) {
		struct simplebus_devinfo *ndi;
		device_t child;
		bus_addr_t phys;
		bus_size_t size;

		/* Add gpio controller child */
		if (!OF_hasprop(dt_child, "gpio-controller"))
			continue;
		child = simplebus_add_device(dev, dt_child, 0,  NULL, -1, NULL);
		if (child == NULL)
			break;
		/* Setup child resources */
		phys = CHIP_REG_OFFSET(re->start, i);
		size = CHIP_REG_STRIDE;
		if (phys + size - 1 <= re->end) {
			ndi = device_get_ivars(child);
			resource_list_add(&ndi->rl, SYS_RES_MEMORY, 0,
			    phys, phys + size - 1, size);
		}
		i++;
	}

	ret = bus_generic_attach(dev);
	if (ret == 0) {
	    fdt_pinctrl_register(dev, "ingenic,pins");
	    fdt_pinctrl_configure_tree(dev);
	}
	return (ret);
}
Exemplo n.º 8
0
int
ofw_bus_has_prop(device_t dev, const char *propname)
{
	phandle_t node;

	if ((node = ofw_bus_get_node(dev)) == -1)
		return (0);

	return (OF_hasprop(node, propname));
}
Exemplo n.º 9
0
static int
opalflash_attach(device_t dev)
{
	struct opalflash_softc *sc;
	phandle_t node;
	cell_t flash_blocksize, opal_id;
	uint32_t regs[2];

	sc = device_get_softc(dev);
	sc->sc_dev = dev;

	node = ofw_bus_get_node(dev);
	OF_getencprop(node, "ibm,opal-id", &opal_id, sizeof(opal_id));
	sc->sc_opal_id = opal_id;

	if (OF_getencprop(node, "ibm,flash-block-size",
	    &flash_blocksize, sizeof(flash_blocksize)) < 0) {
		device_printf(dev, "Cannot determine flash block size.\n");
		return (ENXIO);
	}

	if (!OF_hasprop(node, "no-erase"))
		sc->sc_erase = true;

	OPALFLASH_LOCK_INIT(sc);

	if (OF_getencprop(node, "reg", regs, sizeof(regs)) < 0) {
		device_printf(dev, "Unable to get flash size.\n");
		return (ENXIO);
	}

	sc->sc_disk = disk_alloc();
	sc->sc_disk->d_name = "opalflash";
	sc->sc_disk->d_open = opalflash_open;
	sc->sc_disk->d_close = opalflash_close;
	sc->sc_disk->d_strategy = opalflash_strategy;
	sc->sc_disk->d_ioctl = opalflash_ioctl;
	sc->sc_disk->d_getattr = opalflash_getattr;
	sc->sc_disk->d_drv1 = sc;
	sc->sc_disk->d_maxsize = DFLTPHYS;
	sc->sc_disk->d_mediasize = regs[1];
	sc->sc_disk->d_unit = device_get_unit(sc->sc_dev);
	sc->sc_disk->d_sectorsize = FLASH_BLOCKSIZE;
	    sc->sc_disk->d_stripesize = flash_blocksize;
	sc->sc_disk->d_dump = NULL;

	disk_create(sc->sc_disk, DISK_VERSION);
	bioq_init(&sc->sc_bio_queue);

	kproc_create(&opalflash_task, sc, &sc->sc_p, 0, 0, "task: OPAL Flash");

	return (0);
}
Exemplo n.º 10
0
static int
gpioled_attach(device_t dev)
{
	struct gpioleds_softc *sc;
	phandle_t child, leds;
	int total_leds;

	if ((leds = ofw_bus_get_node(dev)) == -1)
		return (ENXIO);

	sc = device_get_softc(dev);
	sc->sc_dev = dev;
	sc->sc_busdev = device_get_parent(dev);

	/* Traverse the 'gpio-leds' node and count leds */
	total_leds = 0;
	for (child = OF_child(leds); child != 0; child = OF_peer(child)) {
		if (!OF_hasprop(child, "gpios"))
			continue;
		total_leds++;
	}

	if (total_leds) {
		sc->sc_leds =  malloc(sizeof(struct gpioled) * total_leds,
		    M_DEVBUF, M_WAITOK | M_ZERO);

		sc->sc_total_leds = 0;
		/* Traverse the 'gpio-leds' node and count leds */
		for (child = OF_child(leds); child != 0; child = OF_peer(child)) {
			if (!OF_hasprop(child, "gpios"))
				continue;
			gpioleds_attach_led(sc, child, &sc->sc_leds[sc->sc_total_leds]);
			sc->sc_total_leds++;
		}
	}

	return (0);
}
Exemplo n.º 11
0
static int
mtk_usb_phy_detach(device_t dev)
{
	struct mtk_usb_phy_softc *sc = device_get_softc(dev);
	phandle_t node;

	/* Get our FDT node */
	node = ofw_bus_get_node(dev);

	/* If we have resets defined - assert them */
	if (OF_hasprop(node, "resets"))
		fdt_reset_assert_all(dev);

	/* If we have clocks defined - disable them */
	if (OF_hasprop(node, "clocks"))
		fdt_clock_disable_all(dev);

	/* Finally, release resources, if any were allocated */
	if (sc->res != NULL)
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);

	return (0);
}
Exemplo n.º 12
0
static int
axgbe_get_optional_prop(device_t dev, phandle_t node, const char *name,
    int *data, size_t len)
{

	if (!OF_hasprop(node, name))
		return (-1);

	if (OF_getencprop(node, name, data, len) <= 0) {
		device_printf(dev,"%s property is invalid\n", name);
		return (ENXIO);
	}

	return (0);
}
Exemplo n.º 13
0
/*
 * Write protect setup.
 */
static void
wp_setup(struct sdhci_fdt_gpio *gpio, phandle_t node)
{
	device_t dev;

	dev = gpio->dev;

	if (OF_hasprop(node, "wp-disable")) {
		gpio->wp_disabled = true;
		if (bootverbose)
			device_printf(dev, "Write protect disabled\n");
		return;
	}

	if (gpio_pin_get_by_ofw_property(dev, node, "wp-gpios", &gpio->wp_pin))
		return;

	if (OF_hasprop(node, "wp-inverted"))
		gpio->wp_inverted = true;

	if (bootverbose)
		device_printf(dev, "Write protect switch on %s pin %u\n",
		    device_get_nameunit(gpio->wp_pin->dev), gpio->wp_pin->pin);
}
Exemplo n.º 14
0
static int
jz4780_pinctrl_parse_pincfg(phandle_t pincfgxref, uint32_t *bias_value)
{
	phandle_t pincfg_node;
	int i;

	pincfg_node = OF_node_from_xref(pincfgxref);
	for (i = 0; i < nitems(jx4780_bias_table); i++) {
		if (OF_hasprop(pincfg_node, jx4780_bias_table[i].name)) {
			*bias_value = jx4780_bias_table[i].bias;
			return 0;
		}
	}

	return -1;
}
Exemplo n.º 15
0
/*
 * Get interrupt parent for given node.
 * Returns 0 if interrupt parent doesn't exist.
 */
phandle_t
ofw_bus_find_iparent(phandle_t node)
{
	phandle_t iparent;

	if (OF_searchencprop(node, "interrupt-parent", &iparent,
		    sizeof(iparent)) == -1) {
		for (iparent = node; iparent != 0;
		    iparent = OF_parent(iparent)) {
			if (OF_hasprop(iparent, "interrupt-controller"))
				break;
		}
		iparent = OF_xref_from_node(iparent);
	}
	return (iparent);
}
Exemplo n.º 16
0
static int
ahci_fdt_probe(device_t dev)
{
	struct ahci_controller *ctlr = device_get_softc(dev);
	phandle_t node;

	if (!ofw_bus_status_okay(dev))
		return (ENXIO);

	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
		return (ENXIO);

	device_set_desc_copy(dev, "AHCI SATA controller");
	node = ofw_bus_get_node(dev);
	ctlr->dma_coherent = OF_hasprop(node, "dma-coherent");
	return (BUS_PROBE_DEFAULT);
}
Exemplo n.º 17
0
static int
mtk_gpio_probe(device_t dev)
{
	phandle_t node;

	if (!ofw_bus_status_okay(dev))
		return (ENXIO);

	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
		return (ENXIO);

	node = ofw_bus_get_node(dev);
	if (!OF_hasprop(node, "gpio-controller"))
		return (ENXIO);

	device_set_desc(dev, "MTK GPIO Controller (v1)");

	return (BUS_PROBE_DEFAULT);
}
Exemplo n.º 18
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);
}
Exemplo n.º 19
0
static int
gpiobacklight_attach(device_t dev)
{
    struct gpiobacklight_softc *sc;
    struct sysctl_ctx_list *ctx;
    struct sysctl_oid *tree;
    phandle_t node;

    sc = device_get_softc(dev);

    if ((node = ofw_bus_get_node(dev)) == -1)
        return (ENXIO);

    if (OF_hasprop(node, "default-on"))
        sc->sc_brightness = true;
    else
        sc->sc_brightness = false;

    gpio_pin_get_by_ofw_idx(dev, node, 0, &sc->sc_pin);
    if (sc->sc_pin == NULL) {
        device_printf(dev, "failed to map GPIO pin\n");
        return (ENXIO);
    }

    gpio_pin_setflags(sc->sc_pin, GPIO_PIN_OUTPUT);

    gpiobacklight_update_brightness(sc);

    /* Init backlight interface */
    ctx = device_get_sysctl_ctx(dev);
    tree = device_get_sysctl_tree(dev);
    sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
                                 "brightness", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
                                 gpiobacklight_sysctl, "I", "backlight brightness");

    return (0);
}
Exemplo n.º 20
0
static int
ofw_gpiobus_attach(device_t dev)
{
	int err;
	phandle_t child;

	err = gpiobus_init_softc(dev);
	if (err != 0)
		return (err);
	bus_generic_probe(dev);
	bus_enumerate_hinted_children(dev);
	/*
	 * Attach the children represented in the device tree.
	 */
	for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
	    child = OF_peer(child)) {
		if (!OF_hasprop(child, "gpios"))
			continue;
		if (ofw_gpiobus_add_fdt_child(dev, NULL, child) == NULL)
			continue;
	}

	return (bus_generic_attach(dev));
}
Exemplo n.º 21
0
static int
usbphy_attach(device_t dev)
{
	struct usbphy_softc * sc;
	int rid, rv;
	phandle_t node;

	sc = device_get_softc(dev);
	sc->dev = dev;

	rid = 0;
	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (sc->mem_res == NULL) {
		device_printf(dev, "Cannot allocate memory resources\n");
		return (ENXIO);
	}

	rid = 1;
	sc->pads_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (sc->mem_res == NULL) {
		device_printf(dev, "Cannot allocate memory resources\n");
		return (ENXIO);
	}

	node = ofw_bus_get_node(dev);

	rv = hwreset_get_by_ofw_name(sc->dev, 0, "usb", &sc->reset_usb);
	if (rv != 0) {
		device_printf(dev, "Cannot get 'usb' reset\n");
		return (ENXIO);
	}
	rv = hwreset_get_by_ofw_name(sc->dev, 0, "utmi-pads", &sc->reset_pads);
	if (rv != 0) {
		device_printf(dev, "Cannot get 'utmi-pads' reset\n");
		return (ENXIO);
	}

	rv = clk_get_by_ofw_name(sc->dev, 0, "reg", &sc->clk_reg);
	if (rv != 0) {
		device_printf(sc->dev, "Cannot get 'reg' clock\n");
		return (ENXIO);
	}
	rv = clk_get_by_ofw_name(sc->dev, 0, "pll_u", &sc->clk_pllu);
	if (rv != 0) {
		device_printf(sc->dev, "Cannot get 'pll_u' clock\n");
		return (ENXIO);
	}
	rv = clk_get_by_ofw_name(sc->dev, 0, "utmi-pads", &sc->clk_pads);
	if (rv != 0) {
		device_printf(sc->dev, "Cannot get 'utmi-pads' clock\n");
		return (ENXIO);
	}

	rv = hwreset_deassert(sc->reset_usb);
	if (rv != 0) {
		device_printf(dev, "Cannot unreset 'usb' reset\n");
		return (ENXIO);
	}

	rv = clk_enable(sc->clk_pllu);
	if (rv != 0) {
		device_printf(sc->dev, "Cannot enable 'pllu' clock\n");
		return (ENXIO);
	}
	rv = clk_enable(sc->clk_reg);
	if (rv != 0) {
		device_printf(sc->dev, "Cannot enable 'reg' clock\n");
		return (ENXIO);
	}
	if (OF_hasprop(node, "nvidia,has-utmi-pad-registers"))
		sc->have_utmi_regs = true;

	sc->dr_mode = usb_get_dr_mode(dev, node, "dr_mode");
	if (sc->dr_mode == USB_DR_MODE_UNKNOWN)
		sc->dr_mode = USB_DR_MODE_HOST;

	sc->ifc_type = usb_get_ifc_mode(dev, node, "phy_type");

	/* We supports only utmi phy mode for now .... */
	if (sc->ifc_type != USB_IFC_TYPE_UTMI) {
		device_printf(dev, "Unsupported phy type\n");
		return (ENXIO);
	}
	rv = usbphy_utmi_read_params(sc, node);
	if (rv < 0)
		return rv;

	if (OF_hasprop(node, "vbus-supply")) {
		rv = regulator_get_by_ofw_property(sc->dev, 0, "vbus-supply",
		    &sc->supply_vbus);
		if (rv != 0) {
			device_printf(sc->dev,
			   "Cannot get \"vbus\" regulator\n");
			return (ENXIO);
		}
		rv = regulator_enable(sc->supply_vbus);
		if (rv != 0) {
			device_printf(sc->dev,
			    "Cannot enable  \"vbus\" regulator\n");
			return (rv);
		}
	}

	phy_register_provider(dev);
	return (0);
}
Exemplo n.º 22
0
static int
a10_gpio_attach(device_t dev)
{
	int rid;
	phandle_t gpio;
	struct a10_gpio_softc *sc;

	sc = device_get_softc(dev);
	sc->sc_dev = dev;

	mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_SPIN);

	rid = 0;
	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->sc_mem_res) {
		device_printf(dev, "cannot allocate memory window\n");
		goto fail;
	}

	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (!sc->sc_irq_res) {
		device_printf(dev, "cannot allocate interrupt\n");
		goto fail;
	}

	/* Find our node. */
	gpio = ofw_bus_get_node(sc->sc_dev);
	if (!OF_hasprop(gpio, "gpio-controller"))
		/* Node is not a GPIO controller. */
		goto fail;

	/* Use the right pin data for the current SoC */
	switch (allwinner_soc_type()) {
#ifdef SOC_ALLWINNER_A10
	case ALLWINNERSOC_A10:
		sc->padconf = &a10_padconf;
		break;
#endif
#ifdef SOC_ALLWINNER_A20
	case ALLWINNERSOC_A20:
		sc->padconf = &a20_padconf;
		break;
#endif
#ifdef SOC_ALLWINNER_A31
	case ALLWINNERSOC_A31:
		sc->padconf = &a31_padconf;
		break;
#endif
#ifdef SOC_ALLWINNER_A31S
	case ALLWINNERSOC_A31S:
		sc->padconf = &a31s_padconf;
		break;
#endif
	default:
		return (ENOENT);
	}

	sc->sc_busdev = gpiobus_attach_bus(dev);
	if (sc->sc_busdev == NULL)
		goto fail;

	/*
	 * Register as a pinctrl device
	 */
	fdt_pinctrl_register(dev, "allwinner,pins");
	fdt_pinctrl_configure_tree(dev);

	return (0);

fail:
	if (sc->sc_irq_res)
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
	if (sc->sc_mem_res)
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
	mtx_destroy(&sc->sc_mtx);

	return (ENXIO);
}
Exemplo n.º 23
0
static int
mtk_gpio_attach(device_t dev)
{
	struct mtk_gpio_softc *sc;
	phandle_t node;
	uint32_t i, num_pins;

	sc = device_get_softc(dev);
	sc->dev = dev;

	if (bus_alloc_resources(dev, mtk_gpio_spec, sc->res)) {
		device_printf(dev, "could not allocate resources for device\n");
		return (ENXIO);
	}

	MTK_GPIO_LOCK_INIT(sc);

	node = ofw_bus_get_node(dev);

	if (OF_hasprop(node, "clocks"))
		mtk_soc_start_clock(dev);
	if (OF_hasprop(node, "resets"))
		mtk_soc_reset_device(dev);

	if (OF_getprop(node, "ralink,register-map", sc->regs,
	    GPIO_PIOMAX) <= 0) {
		device_printf(dev, "Failed to read register map\n");
		return (ENXIO);
	}

	if (OF_hasprop(node, "ralink,num-gpios") && (OF_getencprop(node,
	    "ralink,num-gpios", &num_pins, sizeof(num_pins)) >= 0))
		sc->num_pins = num_pins;
	else
		sc->num_pins = MTK_GPIO_PINS;

	for (i = 0; i < sc->num_pins; i++) {
		sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
		    GPIO_PIN_INVIN | GPIO_PIN_INVOUT;
		sc->pins[i].intr_polarity = INTR_POLARITY_HIGH;
		sc->pins[i].intr_trigger = INTR_TRIGGER_EDGE;

		snprintf(sc->pins[i].pin_name, GPIOMAXNAME - 1, "gpio%c%d",
		    device_get_unit(dev) + 'a', i);
		sc->pins[i].pin_name[GPIOMAXNAME - 1] = '\0';

		mtk_gpio_pin_probe(sc, i);
	}

	if (mtk_pic_register_isrcs(sc) != 0) {
		device_printf(dev, "could not register PIC ISRCs\n");
		goto fail;
	}

	if (intr_pic_register(dev, OF_xref_from_node(node)) != 0) {
		device_printf(dev, "could not register PIC\n");
		goto fail;
	}

	if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
	    mtk_gpio_intr, NULL, sc, &sc->intrhand) != 0)
		goto fail_pic;

	sc->busdev = gpiobus_attach_bus(dev);
	if (sc->busdev == NULL)
		goto fail_pic;

	return (0);
fail_pic:
	intr_pic_deregister(dev, OF_xref_from_node(node));
fail:
	if(sc->intrhand != NULL)
		bus_teardown_intr(dev, sc->res[1], sc->intrhand);
	bus_release_resources(dev, mtk_gpio_spec, sc->res);
	MTK_GPIO_LOCK_DESTROY(sc);
	return (ENXIO);
}
Exemplo n.º 24
0
static int
rk30_gpio_attach(device_t dev)
{
	struct rk30_gpio_softc *sc = device_get_softc(dev);
	uint32_t func;
	int i, rid;
	phandle_t gpio;

	sc->sc_dev = dev;

	mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);

	rid = 0;
	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->sc_mem_res) {
		device_printf(dev, "cannot allocate memory window\n");
		return (ENXIO);
	}

	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (!sc->sc_irq_res) {
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
		device_printf(dev, "cannot allocate interrupt\n");
		return (ENXIO);
	}

	/* Find our node. */
	gpio = ofw_bus_get_node(sc->sc_dev);

	if (!OF_hasprop(gpio, "gpio-controller"))
		/* Node is not a GPIO controller. */
		goto fail;

	/* Initialize the software controlled pins. */
	for (i = 0; i < RK30_GPIO_PINS; i++) {
		snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
		    "pin %d", i);
		func = rk30_gpio_get_function(sc, i);
		sc->sc_gpio_pins[i].gp_pin = i;
		sc->sc_gpio_pins[i].gp_caps = RK30_GPIO_DEFAULT_CAPS;
		sc->sc_gpio_pins[i].gp_flags = rk30_gpio_func_flag(func);
	}
	sc->sc_gpio_npins = i;

	device_add_child(dev, "gpioc", device_get_unit(dev));
	device_add_child(dev, "gpiobus", device_get_unit(dev));
	return (bus_generic_attach(dev));

fail:
	if (sc->sc_irq_res)
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
	if (sc->sc_mem_res)
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
	return (ENXIO);
}
Exemplo n.º 25
0
int
ofw_cpu_early_foreach(ofw_cpu_foreach_cb callback, boolean_t only_runnable)
{
	phandle_t node, child;
	pcell_t addr_cells, reg[2];
	char status[16];
	char device_type[16];
	u_int id, next_id;
	int count, rv;

	count = 0;
	id = 0;
	next_id = 0;

	node = OF_finddevice("/cpus");
	if (node == -1)
		return (-1);

	/* Find the number of cells in the cpu register */
	if (OF_getencprop(node, "#address-cells", &addr_cells,
	    sizeof(addr_cells)) < 0)
		return (-1);

	for (child = OF_child(node); child != 0; child = OF_peer(child),
	    id = next_id) {

		/* Check if child is a CPU */
		memset(device_type, 0, sizeof(device_type));
		rv = OF_getprop(child, "device_type", device_type,
		    sizeof(device_type) - 1);
		if (rv < 0)
			continue;
		if (strcmp(device_type, "cpu") != 0)
			continue;

		/* We're processing CPU, update next_id used in the next iteration */
		next_id++;

		/*
		 * If we are filtering by runnable then limit to only
		 * those that have been enabled, or do provide a method
		 * to enable them.
		 */
		if (only_runnable) {
			status[0] = '\0';
			OF_getprop(child, "status", status, sizeof(status));
			if (status[0] != '\0' && strcmp(status, "okay") != 0 &&
				strcmp(status, "ok") != 0 &&
				!OF_hasprop(child, "enable-method"))
					continue;
		}

		/*
		 * Check we have a register to identify the cpu
		 */
		rv = OF_getencprop(child, "reg", reg,
		    addr_cells * sizeof(cell_t));
		if (rv != addr_cells * sizeof(cell_t))
			continue;

		if (callback == NULL || callback(id, child, addr_cells, reg))
			count++;
	}

	return (only_runnable ? count : id);
}
Exemplo n.º 26
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);
}
Exemplo n.º 27
0
static int
tegra124_pmc_parse_fdt(struct tegra124_pmc_softc *sc, phandle_t node)
{
	int rv;
	uint32_t tmp;
	uint32_t tmparr[2];

	rv = OF_getencprop(node, "nvidia,suspend-mode", &tmp, sizeof(tmp));
	if (rv > 0) {
		switch (tmp) {
		case 0:
			sc->suspend_mode = TEGRA_SUSPEND_LP0;
			break;

		case 1:
			sc->suspend_mode = TEGRA_SUSPEND_LP1;
			break;

		case 2:
			sc->suspend_mode = TEGRA_SUSPEND_LP2;
			break;

		default:
			sc->suspend_mode = TEGRA_SUSPEND_NONE;
			break;
		}
	}

	rv = OF_getencprop(node, "nvidia,cpu-pwr-good-time", &tmp, sizeof(tmp));
	if (rv > 0) {
		sc->cpu_good_time = tmp;
		sc->suspend_mode = TEGRA_SUSPEND_NONE;
	}

	rv = OF_getencprop(node, "nvidia,cpu-pwr-off-time", &tmp, sizeof(tmp));
	if (rv > 0) {
		sc->cpu_off_time = tmp;
		sc->suspend_mode = TEGRA_SUSPEND_NONE;
	}

	rv = OF_getencprop(node, "nvidia,core-pwr-good-time", tmparr,
	    sizeof(tmparr));
	if (rv == sizeof(tmparr)) {
		sc->core_osc_time = tmparr[0];
		sc->core_pmu_time = tmparr[1];
		sc->suspend_mode = TEGRA_SUSPEND_NONE;
	}

	rv = OF_getencprop(node, "nvidia,core-pwr-off-time", &tmp, sizeof(tmp));
	if (rv > 0) {
		sc->core_off_time = tmp;
		sc->suspend_mode = TEGRA_SUSPEND_NONE;
	}

	sc->corereq_high =
	    OF_hasprop(node, "nvidia,core-power-req-active-high");
	sc->sysclkreq_high =
	    OF_hasprop(node, "nvidia,sys-clock-req-active-high");
	sc->combined_req =
	    OF_hasprop(node, "nvidia,combined-power-req");
	sc->cpu_pwr_good_en =
	    OF_hasprop(node, "nvidia,cpu-pwr-good-en");

	rv = OF_getencprop(node, "nvidia,lp0-vec", tmparr, sizeof(tmparr));
	if (rv == sizeof(tmparr)) {

		sc->lp0_vec_phys = tmparr[0];
		sc->core_pmu_time = tmparr[1];
		sc->lp0_vec_size = TEGRA_SUSPEND_NONE;
		if (sc->suspend_mode == TEGRA_SUSPEND_LP0)
			sc->suspend_mode = TEGRA_SUSPEND_LP1;
	}
	return 0;
}
Exemplo n.º 28
0
static int
rk30_gpio_attach(device_t dev)
{
	struct rk30_gpio_softc *sc = device_get_softc(dev);
	int i, rid;
	phandle_t gpio;
	unsigned long start;

	if (rk30_gpio_sc)
		return (ENXIO);
	sc->sc_dev = dev;
	mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);

	rid = 0;
	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->sc_mem_res) {
		device_printf(dev, "cannot allocate memory window\n");
		goto fail;
	}
	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
	/* Check the unit we are attaching by our base address. */
	sc->sc_bank = -1;
	start = rman_get_start(sc->sc_mem_res);
	for (i = 0; i < nitems(rk30_gpio_base_addr); i++) {
		if (rk30_gpio_base_addr[i] == start) {
			sc->sc_bank = i;
			break;
		}
	}
	if (sc->sc_bank == -1) {
		device_printf(dev,
		    "unsupported device unit (only GPIO0..3 are supported)\n");
		goto fail;
	}

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (!sc->sc_irq_res) {
		device_printf(dev, "cannot allocate interrupt\n");
		goto fail;
	}

	/* Find our node. */
	gpio = ofw_bus_get_node(sc->sc_dev);

	if (!OF_hasprop(gpio, "gpio-controller"))
		/* Node is not a GPIO controller. */
		goto fail;

	/* Initialize the software controlled pins. */
	for (i = 0; i < RK30_GPIO_PINS; i++) {
		snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
		    "pin %d", i);
		sc->sc_gpio_pins[i].gp_pin = i;
		sc->sc_gpio_pins[i].gp_caps = RK30_GPIO_DEFAULT_CAPS;
		sc->sc_gpio_pins[i].gp_flags = rk30_gpio_get_function(sc, i);
	}
	sc->sc_gpio_npins = i;
	rk30_gpio_sc = sc;
	rk30_gpio_init();
	sc->sc_busdev = gpiobus_attach_bus(dev);
	if (sc->sc_busdev == NULL)
		goto fail;

	return (0);

fail:
	if (sc->sc_irq_res)
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
	if (sc->sc_mem_res)
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
	mtx_destroy(&sc->sc_mtx);

	return (ENXIO);
}
Exemplo n.º 29
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);
}
Exemplo n.º 30
0
static int
mtk_usb_phy_attach(device_t dev)
{
	struct mtk_usb_phy_softc * sc = device_get_softc(dev);
	phandle_t node;
	uint32_t val;
	int rid;

	sc->dev = dev;

	/* Get our FDT node and SoC id */
	node = ofw_bus_get_node(dev);

	/* Now let's see about setting USB to host or device mode */
	/* XXX: is it the same for all SoCs? */
	val = mtk_sysctl_get(SYSCTL_SYSCFG1);
	if (OF_hasprop(node, "mtk,usb-device"))
		val &= ~SYSCFG1_USB_HOST_MODE;
	else
		val |= SYSCFG1_USB_HOST_MODE;
	mtk_sysctl_set(SYSCTL_SYSCFG1, val);

	/* If we have clocks defined - enable them */
	if (OF_hasprop(node, "clocks"))
		fdt_clock_enable_all(dev);

	/* If we have resets defined - perform a reset sequence */
	if (OF_hasprop(node, "resets")) {
		fdt_reset_assert_all(dev);
		DELAY(RESET_ASSERT_DELAY);
		fdt_reset_deassert_all(dev);
		DELAY(RESET_DEASSERT_DELAY);
	}

	/* Careful, some devices actually require resources */
	if (OF_hasprop(node, "reg")) {
		rid = 0;
		sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
		    RF_ACTIVE);
		if (sc->res == NULL) {
			device_printf(dev, "could not map memory\n");
			return (ENXIO);
		}
	} else {
		sc->res = NULL;
	}

	/* Some SoCs require specific USB PHY init... handle these */
	switch (sc->socid) {
	case MTK_SOC_MT7628: /* Fallthrough */
	case MTK_SOC_MT7688:
		if (sc->res == NULL)
			return (ENXIO);
		sc->fm_base = MT7628_FM_FEG_BASE;
		sc->u2_base = MT7628_U2_BASE;
		sc->sr_coef = MT7628_SR_COEF;
		mtk_usb_phy_mt7628_init(dev);
		break;
	case MTK_SOC_MT7621:
		if (sc->res == NULL)
			return (ENXIO);
		sc->fm_base = MT7621_FM_FEG_BASE;
		sc->u2_base = MT7621_U2_BASE;
		sc->sr_coef = MT7621_SR_COEF;
		mtk_usb_phy_mt7621_init(dev);
		break;
	}

	/* We no longer need the resources, release them */
	if (sc->res != NULL)
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);

	return (0);
}