Example #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);
}
Example #2
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));
}
Example #3
0
static int
pinmux_process_node(struct pinmux_softc *sc, phandle_t node)
{
	struct pincfg cfg;
	char *pins, *pname;
	int i, len, lpins, rv;

	rv = pinmux_read_node(sc, node, &cfg, &pins, &lpins);
	if (rv != 0)
		return (rv);

	len = 0;
	pname = pins;
	do {
		i = strlen(pname) + 1;
		rv = pinmux_config_node(sc, pname, &cfg);
		if (rv != 0)
			device_printf(sc->dev,
			    "Cannot configure pin: %s: %d\n", pname, rv);

		len += i;
		pname += i;
	} while (len < lpins);

	if (pins != NULL)
		OF_prop_free(pins);
	if (cfg.function != NULL)
		OF_prop_free(cfg.function);
	return (rv);
}
Example #4
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));
}
Example #5
0
static int
clk_fixed_attach(device_t dev)
{
	struct clk_fixed_softc *sc;
	intptr_t clk_type;
	phandle_t node;
	struct clk_fixed_def def;
	int rv;

	sc = device_get_softc(dev);
	sc->dev = dev;
	node  = ofw_bus_get_node(dev);
	clk_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;

	bzero(&def, sizeof(def));
	if (clk_type == CLK_TYPE_FIXED)
		rv = clk_fixed_init_fixed(sc, node, &def);
	else if (clk_type == CLK_TYPE_FIXED_FACTOR)
		rv = clk_fixed_init_fixed_factor(sc, node, &def);
	else
		rv = ENXIO;
	if (rv != 0) {
		device_printf(sc->dev, "Cannot FDT parameters.\n");
		goto fail;
	}
	rv = clk_parse_ofw_clk_name(dev, node, &def.clkdef.name);
	if (rv != 0) {
		device_printf(sc->dev, "Cannot parse clock name.\n");
		goto fail;
	}
	sc->clkdom = clkdom_create(dev);
	KASSERT(sc->clkdom != NULL, ("Clock domain is NULL"));

	rv = clknode_fixed_register(sc->clkdom, &def);
	if (rv != 0) {
		device_printf(sc->dev, "Cannot register fixed clock.\n");
		rv = ENXIO;
		goto fail;
	}

	rv = clkdom_finit(sc->clkdom);
	if (rv != 0) {
		device_printf(sc->dev, "Clk domain finit fails.\n");
		rv = ENXIO;
		goto fail;
	}
#ifdef CLK_DEBUG
	clkdom_dump(sc->clkdom);
#endif
	OF_prop_free(__DECONST(char *, def.clkdef.name));
	OF_prop_free(def.clkdef.parent_names);
	return (bus_generic_attach(dev));

fail:
	OF_prop_free(__DECONST(char *, def.clkdef.name));
	OF_prop_free(def.clkdef.parent_names);
	return (rv);
}
Example #6
0
static void
gpioleds_attach_led(struct gpioleds_softc *sc, phandle_t node,
    struct gpioled *led)
{
	char *name;
	int state, err;
	char *default_state;

	led->parent_sc = sc;

	state = 0;
	if (OF_getprop_alloc(node, "default-state",
	    sizeof(char), (void **)&default_state) != -1) {
		if (strcasecmp(default_state, "on") == 0)
			state = 1;
		else if (strcasecmp(default_state, "off") == 0)
			state = 0;
		else if (strcasecmp(default_state, "keep") == 0)
			state = -1;
		else {
			state = -1;
			device_printf(sc->sc_dev,
			    "unknown value for default-state in FDT\n");
		}
		OF_prop_free(default_state);
	}

	name = NULL;
	if (OF_getprop_alloc(node, "label", 1, (void **)&name) == -1)
		OF_getprop_alloc(node, "name", 1, (void **)&name);

	if (name == NULL) {
		device_printf(sc->sc_dev,
		    "no name provided for gpio LED, skipping\n");
		return;
	}

	err = gpio_pin_get_by_ofw_idx(sc->sc_dev, node, 0, &led->pin);
	if (err) {
		device_printf(sc->sc_dev, "<%s> failed to map pin\n", name);
		if (name)
			OF_prop_free(name);
		return;
	}
	gpio_pin_setflags(led->pin, GPIO_PIN_OUTPUT);

	led->leddev = led_create_state(gpioled_control, led, name,
	    state);

	if (name != NULL)
		OF_prop_free(name);
}
Example #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);
}
Example #8
0
static int
ti_pinmux_configure_pins(device_t dev, phandle_t cfgxref)
{
	struct pincfg *cfgtuples, *cfg;
	phandle_t cfgnode;
	int i, ntuples;
	static struct ti_pinmux_softc *sc;

	sc = device_get_softc(dev);
	cfgnode = OF_node_from_xref(cfgxref);
	ntuples = OF_getencprop_alloc(cfgnode, "pinctrl-single,pins", sizeof(*cfgtuples),
	    (void **)&cfgtuples);

	if (ntuples < 0)
		return (ENOENT);

	if (ntuples == 0)
		return (0); /* Empty property is not an error. */

	for (i = 0, cfg = cfgtuples; i < ntuples; i++, cfg++) {
		if (bootverbose) {
			char name[32];
			OF_getprop(cfgnode, "name", &name, sizeof(name));
			printf("%16s: muxreg 0x%04x muxval 0x%02x\n",
			    name, cfg->reg, cfg->conf);
		}

		/* write the register value (16-bit writes) */
		ti_pinmux_write_2(sc, cfg->reg, cfg->conf);
	}

	OF_prop_free(cfgtuples);

	return (0);
}
Example #9
0
static int
fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc,
    struct lbc_devinfo *di)
{
	rman_res_t start, end, count;
	pcell_t *reg, *regptr;
	pcell_t addr_cells, size_cells;
	int tuple_size, tuples;
	int i, j, rv, bank;

	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
		return (ENXIO);

	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
	tuples = OF_getencprop_alloc_multi(node, "reg", tuple_size,
	    (void **)&reg);
	debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
	debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
	if (tuples <= 0)
		/* No 'reg' property in this node. */
		return (0);

	regptr = reg;
	for (i = 0; i < tuples; i++) {

		bank = fdt_data_get((void *)reg, 1);
		di->di_bank = bank;
		reg += 1;

		/* Get address/size. */
		start = count = 0;
		for (j = 0; j < addr_cells; j++) {
			start <<= 32;
			start |= reg[j];
		}
		for (j = 0; j < size_cells; j++) {
			count <<= 32;
			count |= reg[addr_cells + j - 1];
		}
		reg += addr_cells - 1 + size_cells;

		/* Calculate address range relative to VA base. */
		start = sc->sc_banks[bank].kva + start;
		end = start + count - 1;

		debugf("reg addr bank = %d, start = %jx, end = %jx, "
		    "count = %jx\n", bank, start, end, count);

		/* Use bank (CS) cell as rid. */
		resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start,
		    end, count);
	}
	rv = 0;
	OF_prop_free(regptr);
	return (rv);
}
Example #10
0
int
fdt_reg_to_rl(phandle_t node, struct resource_list *rl)
{
	u_long end, count, start;
	pcell_t *reg, *regptr;
	pcell_t addr_cells, size_cells;
	int tuple_size, tuples;
	int i, rv;
	long busaddr, bussize;

	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
		return (ENXIO);
	if (fdt_get_range(OF_parent(node), 0, &busaddr, &bussize)) {
		busaddr = 0;
		bussize = 0;
	}

	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
	tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)&reg);
	debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
	debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
	if (tuples <= 0)
		/* No 'reg' property in this node. */
		return (0);

	regptr = reg;
	for (i = 0; i < tuples; i++) {

		rv = fdt_data_to_res(reg, addr_cells, size_cells, &start,
		    &count);
		if (rv != 0) {
			resource_list_free(rl);
			goto out;
		}
		reg += addr_cells + size_cells;

		/* Calculate address range relative to base. */
		start += busaddr;
		end = start + count - 1;

		debugf("reg addr start = %lx, end = %lx, count = %lx\n", start,
		    end, count);

		resource_list_add(rl, SYS_RES_MEMORY, i, start, end,
		    count);
	}
	rv = 0;

out:
	OF_prop_free(regptr);
	return (rv);
}
Example #11
0
static int
pinctrl_configure_pins(device_t bus, phandle_t cfgxref)
{
	struct pinctrl_softc *sc;
	struct pincfg *cfg, *cfgdata;
	char name[32];
	phandle_t node;
	ssize_t npins;
	int i;

	sc = device_get_softc(bus);
	node = OF_node_from_xref(cfgxref);
	memset(name, 0, sizeof(name));
	OF_getprop(node, "name", name, sizeof(name));
	npins = OF_getencprop_alloc(node, "atmel,pins", sizeof(*cfgdata),
	    (void **)&cfgdata);
	if (npins < 0) {
		printf("We're doing it wrong %s\n", name);
		return (ENXIO);
	}
	if (npins == 0)
		return (0);
	for (i = 0, cfg = cfgdata; i < npins; i++, cfg++) {
		uint32_t pio;
		pio = (0xfffffff & sc->ranges[0].bus) + 0x200 * cfg->unit;
		printf("P%c%d %s %#x\n", cfg->unit + 'A', cfg->pin,
		    periphs[cfg->periph], cfg->flags);
		switch (cfg->periph) {
		case 0:
			at91_pio_use_gpio(pio, 1u << cfg->pin);
			at91_pio_gpio_pullup(pio, 1u << cfg->pin,
			    !!(cfg->flags & 1));
			at91_pio_gpio_high_z(pio, 1u << cfg->pin,
			    !!(cfg->flags & 2));
			at91_pio_gpio_set_deglitch(pio,
			    1u << cfg->pin, !!(cfg->flags & 4));
//			at91_pio_gpio_pulldown(pio, 1u << cfg->pin,
//			    !!(cfg->flags & 8));
//			at91_pio_gpio_dis_schmidt(pio,
//			    1u << cfg->pin, !!(cfg->flags & 16));
			break;
		case 1:
			at91_pio_use_periph_a(pio, 1u << cfg->pin, cfg->flags);
			break;
		case 2:
			at91_pio_use_periph_b(pio, 1u << cfg->pin, cfg->flags);
			break;
		}
	}
	OF_prop_free(cfgdata);
	return (0);
}
Example #12
0
int
hwreset_get_by_ofw_idx(device_t consumer_dev, phandle_t cnode, int idx,
                       hwreset_t *rst)
{
    phandle_t xnode;
    pcell_t *cells;
    device_t rstdev;
    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, "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) {
        OF_prop_free(cells);
        return (ENODEV);
    }
    /* Map reset to number */
    rv = HWRESET_MAP(rstdev, xnode, ncells, cells, &id);
    OF_prop_free(cells);
    if (rv != 0)
        return (rv);

    return (hwreset_get_by_id(consumer_dev, rstdev, id, rst));
}
Example #13
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;
		}
	}
	OF_prop_free(resets);
	return (anyerrors ? ENXIO : 0);
}
Example #14
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);
}
Example #15
0
static enum usb_ifc_type
usb_get_ifc_mode(device_t dev, phandle_t node, char *name)
{
	char *tmpstr;
	int rv;
	enum usb_ifc_type ret;

	rv = OF_getprop_alloc(node, name, 1, (void **)&tmpstr);
	if (rv <= 0)
		return (USB_IFC_TYPE_UNKNOWN);

	ret = USB_IFC_TYPE_UNKNOWN;
	if (strcmp(tmpstr, "utmi") == 0)
		ret = USB_IFC_TYPE_UTMI;
	else if (strcmp(tmpstr, "ulpi") == 0)
		ret = USB_IFC_TYPE_ULPI;
	else
		device_printf(dev, "Unsupported phy type: %s\n", tmpstr);
	OF_prop_free(tmpstr);
	return (ret);
}
Example #16
0
int
fdt_is_enabled(phandle_t node)
{
	char *stat;
	int ena, len;

	len = OF_getprop_alloc(node, "status", sizeof(char),
	    (void **)&stat);

	if (len <= 0)
		/* It is OK if no 'status' property. */
		return (1);

	/* Anything other than 'okay' means disabled. */
	ena = 0;
	if (strncmp((char *)stat, "okay", len) == 0)
		ena = 1;

	OF_prop_free(stat);
	return (ena);
}
Example #17
0
static enum usb_dr_mode
usb_get_dr_mode(device_t dev, phandle_t node, char *name)
{
	char *tmpstr;
	int rv;
	enum usb_dr_mode ret;

	rv = OF_getprop_alloc(node, name, 1, (void **)&tmpstr);
	if (rv <= 0)
		return (USB_DR_MODE_UNKNOWN);

	ret = USB_DR_MODE_UNKNOWN;
	if (strcmp(tmpstr, "device") == 0)
		ret = USB_DR_MODE_DEVICE;
	else if (strcmp(tmpstr, "host") == 0)
		ret = USB_DR_MODE_HOST;
	else if (strcmp(tmpstr, "otg") == 0)
		ret = USB_DR_MODE_OTG;
	else
		device_printf(dev, "Unknown dr mode: %s\n", tmpstr);
	OF_prop_free(tmpstr);
	return (ret);
}
Example #18
0
static int
fdt_localbus_reg_decode(phandle_t node, struct localbus_softc *sc,
    struct localbus_devinfo *di)
{
	u_long start, end, count;
	pcell_t *reg, *regptr;
	pcell_t addr_cells, size_cells;
	int tuple_size, tuples;
	int i, rv, bank;

	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
		return (ENXIO);

	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
	tuples = OF_getprop_alloc_multi(node, "reg", tuple_size, (void **)&reg);
	debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
	debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
	if (tuples <= 0)
		/* No 'reg' property in this node. */
		return (0);

	regptr = reg;
	for (i = 0; i < tuples; i++) {

		bank = fdt_data_get((void *)regptr, 1);

		if (bank >= MV_LOCALBUS_MAX_BANKS) {
			device_printf(sc->sc_dev, "bank number [%d] out of "
			    "range\n", bank);
			continue;
		}

		/*
		 * If device doesn't have virtual to physical mapping don't add
		 * resources
		 */
		if (!(sc->sc_banks[bank].mapped)) {
			device_printf(sc->sc_dev, "device [%d]: missing memory "
			    "mapping\n", bank);
			continue;
		}

		di->di_bank = bank;
		regptr += 1;

		/* Get address/size. */
		rv = fdt_data_to_res(regptr, addr_cells - 1, size_cells, &start,
		    &count);
		if (rv != 0) {
			resource_list_free(&di->di_res);
			goto out;
		}

		/* Check if enough amount of memory is mapped */
		if (sc->sc_banks[bank].size < count) {
			device_printf(sc->sc_dev, "device [%d]: not enough "
			    "memory reserved\n", bank);
			continue;
		}

		regptr += addr_cells - 1 + size_cells;

		/* Calculate address range relative to VA base. */
		start = sc->sc_banks[bank].va + start;
		end = start + count - 1;

		debugf("reg addr bank = %d, start = %lx, end = %lx, "
		    "count = %lx\n", bank, start, end, count);

		/* Use bank (CS) cell as rid. */
		resource_list_add(&di->di_res, SYS_RES_MEMORY, di->di_bank,
		    start, end, count);
	}
	rv = 0;
out:
	OF_prop_free(reg);
	return (rv);
}
Example #19
0
static struct pinctrl_devinfo *
at91_pinctrl_setup_dinfo(device_t dev, phandle_t node)
{
	struct pinctrl_softc *sc;
	struct pinctrl_devinfo *ndi;
	uint32_t *reg, *intr, icells;
	uint64_t phys, size;
	phandle_t iparent;
	int i, j, k;
	int nintr;
	int nreg;

	sc = device_get_softc(dev);

	ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
	if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) {
		free(ndi, M_DEVBUF);
		return (NULL);
	}

	resource_list_init(&ndi->rl);
	nreg = OF_getencprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
	if (nreg == -1)
		nreg = 0;
	if (nreg % (sc->acells + sc->scells) != 0) {
//		if (bootverbose)
			device_printf(dev, "Malformed reg property on <%s>\n",
			    ndi->obdinfo.obd_name);
		nreg = 0;
	}

	for (i = 0, k = 0; i < nreg; i += sc->acells + sc->scells, k++) {
		phys = size = 0;
		for (j = 0; j < sc->acells; j++) {
			phys <<= 32;
			phys |= reg[i + j];
		}
		for (j = 0; j < sc->scells; j++) {
			size <<= 32;
			size |= reg[i + sc->acells + j];
		}
		
		resource_list_add(&ndi->rl, SYS_RES_MEMORY, k,
		    phys, phys + size - 1, size);
	}
	OF_prop_free(reg);

	nintr = OF_getencprop_alloc(node, "interrupts",  sizeof(*intr),
	    (void **)&intr);
	if (nintr > 0) {
		if (OF_searchencprop(node, "interrupt-parent", &iparent,
		    sizeof(iparent)) == -1) {
			device_printf(dev, "No interrupt-parent found, "
			    "assuming direct parent\n");
			iparent = OF_parent(node);
		}
		if (OF_searchencprop(OF_node_from_xref(iparent), 
		    "#interrupt-cells", &icells, sizeof(icells)) == -1) {
			device_printf(dev, "Missing #interrupt-cells property,"
			    " assuming <1>\n");
			icells = 1;
		}
		if (icells < 1 || icells > nintr) {
			device_printf(dev, "Invalid #interrupt-cells property "
			    "value <%d>, assuming <1>\n", icells);
			icells = 1;
		}
		for (i = 0, k = 0; i < nintr; i += icells, k++) {
			intr[i] = ofw_bus_map_intr(dev, iparent, icells,
			    &intr[i]);
			resource_list_add(&ndi->rl, SYS_RES_IRQ, k, intr[i],
			    intr[i], 1);
		}
		OF_prop_free(intr);
	}

	return (ndi);
}
Example #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);
}
Example #21
0
static int
lbc_attach(device_t dev)
{
	struct lbc_softc *sc;
	struct lbc_devinfo *di;
	struct rman *rm;
	uintmax_t offset, size;
	vm_paddr_t start;
	device_t cdev;
	phandle_t node, child;
	pcell_t *ranges, *rangesptr;
	int tuple_size, tuples;
	int par_addr_cells;
	int bank, error, i, j;

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

	sc->sc_mrid = 0;
	sc->sc_mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mrid,
	    RF_ACTIVE);
	if (sc->sc_mres == NULL)
		return (ENXIO);

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

	for (bank = 0; bank < LBC_DEV_MAX; bank++) {
		bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_BR(bank), 0);
		bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_OR(bank), 0);
	}

	/*
	 * Initialize configuration register:
	 * - enable Local Bus
	 * - set data buffer control signal function
	 * - disable parity byte select
	 * - set ECC parity type
	 * - set bus monitor timing and timer prescale
	 */
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);

	/*
	 * Initialize clock ratio register:
	 * - disable PLL bypass mode
	 * - configure LCLK delay cycles for the assertion of LALE
	 * - set system clock divider
	 */
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);

	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEDR, 0);
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ~0);
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEIR, 0x64080001);

	sc->sc_irid = 0;
	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (sc->sc_ires != NULL) {
		error = bus_setup_intr(dev, sc->sc_ires,
		    INTR_TYPE_MISC | INTR_MPSAFE, NULL, lbc_intr, sc,
		    &sc->sc_icookie);
		if (error) {
			device_printf(dev, "could not activate interrupt\n");
			bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
			    sc->sc_ires);
			sc->sc_ires = NULL;
		}
	}

	sc->sc_ltesr = ~0;

	rangesptr = NULL;

	rm = &sc->sc_rman;
	rm->rm_type = RMAN_ARRAY;
	rm->rm_descr = "Local Bus Space";
	error = rman_init(rm);
	if (error)
		goto fail;

	error = rman_manage_region(rm, rm->rm_start, rm->rm_end);
	if (error) {
		rman_fini(rm);
		goto fail;
	}

	/*
	 * Process 'ranges' property.
	 */
	node = ofw_bus_get_node(dev);
	if ((fdt_addrsize_cells(node, &sc->sc_addr_cells,
	    &sc->sc_size_cells)) != 0) {
		error = ENXIO;
		goto fail;
	}

	par_addr_cells = fdt_parent_addr_cells(node);
	if (par_addr_cells > 2) {
		device_printf(dev, "unsupported parent #addr-cells\n");
		error = ERANGE;
		goto fail;
	}
	tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells +
	    sc->sc_size_cells);

	tuples = OF_getencprop_alloc_multi(node, "ranges", tuple_size,
	    (void **)&ranges);
	if (tuples < 0) {
		device_printf(dev, "could not retrieve 'ranges' property\n");
		error = ENXIO;
		goto fail;
	}
	rangesptr = ranges;

	debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, "
	    "tuple_size = %d, tuples = %d\n", par_addr_cells,
	    sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples);

	start = 0;
	size = 0;
	for (i = 0; i < tuples; i++) {

		/* The first cell is the bank (chip select) number. */
		bank = fdt_data_get(ranges, 1);
		if (bank < 0 || bank > LBC_DEV_MAX) {
			device_printf(dev, "bank out of range: %d\n", bank);
			error = ERANGE;
			goto fail;
		}
		ranges += 1;

		/*
		 * Remaining cells of the child address define offset into
		 * this CS.
		 */
		offset = 0;
		for (j = 0; j < sc->sc_addr_cells - 1; j++) {
			offset <<= sizeof(pcell_t) * 8;
			offset |= *ranges;
			ranges++;
		}

		/* Parent bus start address of this bank. */
		start = 0;
		for (j = 0; j < par_addr_cells; j++) {
			start <<= sizeof(pcell_t) * 8;
			start |= *ranges;
			ranges++;
		}

		size = fdt_data_get((void *)ranges, sc->sc_size_cells);
		ranges += sc->sc_size_cells;
		debugf("bank = %d, start = %jx, size = %jx\n", bank,
		    (uintmax_t)start, size);

		sc->sc_banks[bank].addr = start + offset;
		sc->sc_banks[bank].size = size;

		/*
		 * Attributes for the bank.
		 *
		 * XXX Note there are no DT bindings defined for them at the
		 * moment, so we need to provide some defaults.
		 */
		sc->sc_banks[bank].width = 16;
		sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM;
		sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED;
		sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED;
		sc->sc_banks[bank].wp = 0;
	}

	/*
	 * Initialize mem-mappings for the LBC banks (i.e. chip selects).
	 */
	error = lbc_banks_map(sc);
	if (error)
		goto fail;

	/*
	 * Walk the localbus and add direct subordinates as our children.
	 */
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {

		di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO);

		if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) {
			free(di, M_LBC);
			device_printf(dev, "could not set up devinfo\n");
			continue;
		}

		resource_list_init(&di->di_res);

		if (fdt_lbc_reg_decode(child, sc, di)) {
			device_printf(dev, "could not process 'reg' "
			    "property\n");
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_LBC);
			continue;
		}

		fdt_lbc_fixup(child, sc, di);

		/* Add newbus device for this FDT node */
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "could not add child: %s\n",
			    di->di_ofw.obd_name);
			resource_list_free(&di->di_res);
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_LBC);
			continue;
		}
		debugf("added child name='%s', node=%x\n", di->di_ofw.obd_name,
		    child);
		device_set_ivars(cdev, di);
	}

	/*
	 * Enable the LBC.
	 */
	lbc_banks_enable(sc);

	OF_prop_free(rangesptr);
	return (bus_generic_attach(dev));

fail:
	OF_prop_free(rangesptr);
	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres);
	return (error);
}
Example #22
0
static int
aml8726_pinctrl_configure_pins(device_t dev, phandle_t cfgxref)
{
	struct aml8726_pinctrl_softc *sc = device_get_softc(dev);
	struct aml8726_pinctrl_function *cf;
	struct aml8726_pinctrl_function *f;
	struct aml8726_pinctrl_pkg_pin *pp;
	struct aml8726_pinctrl_pin *cp;
	struct aml8726_pinctrl_pin *p;
	enum aml8726_pinctrl_pull_mode pm;
	char *function_name;
	char *pins;
	char *pin_name;
	char *pull;
	phandle_t node;
	ssize_t len;
	uint32_t value;

	node = OF_node_from_xref(cfgxref);

	len = OF_getprop_alloc(node, "amlogic,function",
	    sizeof(char), (void **)&function_name);

	if (len < 0) {
		device_printf(dev,
		    "missing amlogic,function attribute in FDT\n");
		return (ENXIO);
	}

	for (f = sc->soc.func; f->name != NULL; f++)
		if (strncmp(f->name, function_name, len) == 0)
			break;

	if (f->name == NULL) {
		device_printf(dev, "unknown function attribute %.*s in FDT\n",
		    len, function_name);
		OF_prop_free(function_name);
		return (ENXIO);
	}

	OF_prop_free(function_name);

	len = OF_getprop_alloc(node, "amlogic,pull",
	    sizeof(char), (void **)&pull);

	pm = aml8726_unknown_pm;

	if (len > 0) {
		if (strncmp(pull, "enable", len) == 0)
			pm = aml8726_enable_pm;
		else if (strncmp(pull, "disable", len) == 0)
			pm = aml8726_disable_pm;
		else if (strncmp(pull, "down", len) == 0)
			pm = aml8726_enable_down_pm;
		else if (strncmp(pull, "up", len) == 0)
			pm = aml8726_enable_up_pm;
		else {
			device_printf(dev,
			    "unknown pull attribute %.*s in FDT\n",
			    len, pull);
			OF_prop_free(pull);
			return (ENXIO);
		}
	}

	OF_prop_free(pull);

	/*
	 * Setting the pull direction isn't supported on all SoC.
	 */
	switch (pm) {
	case aml8726_enable_down_pm:
	case aml8726_enable_up_pm:
		if (sc->soc.pud_ctrl == false) {
			device_printf(dev,
			    "SoC doesn't support setting pull direction.\n");
			return (ENXIO);
		}
		break;
	default:
		break;
	}

	len = OF_getprop_alloc(node, "amlogic,pins",
	    sizeof(char), (void **)&pins);

	if (len < 0) {
		device_printf(dev, "missing amlogic,pins attribute in FDT\n");
		return (ENXIO);
	}

	pin_name = pins;

	while (len) {
		for (p = f->pins; p->name != NULL; p++)
			if (strncmp(p->name, pin_name, len) == 0)
				break;

		if (p->name == NULL) {
			/* display message prior to queuing up next string */
			device_printf(dev, "unknown pin attribute %.*s in FDT\n",
			    len, pin_name);
		}

		/* queue up next string */
		while (*pin_name && len) {
			pin_name++;
			len--;
		}
		if (len) {
			pin_name++;
			len--;
		}

		if (p->name == NULL)
			continue;

		for (pp = sc->soc.ppin; pp->pkg_name != NULL; pp++)
			if (strcmp(pp->pkg_name, p->pkg_name) == 0)
				break;

		if (pp->pkg_name == NULL) {
			device_printf(dev,
			    "missing entry for package pin %s\n",
			    p->pkg_name);
			continue;
		}

		if (pm != aml8726_unknown_pm && pp->pull_bits == 0x00000000) {
			device_printf(dev,
			    "missing pull info for package pin %s\n",
			    p->pkg_name);
			continue;
		}

		AML_PINCTRL_LOCK(sc);

		/*
		 * First clear all other mux bits associated with this
		 * package pin.  This may briefly configure the pin as
		 * GPIO ...  however this should be fine since after
		 * reset the default GPIO mode is input.
		 */

		for (cf = sc->soc.func; cf->name != NULL; cf++)
			for (cp = cf->pins; cp->name != NULL; cp++) {
				if (cp == p)
					continue;
				if (strcmp(cp->pkg_name, p->pkg_name) != 0)
					continue;
				if (cp->mux_bits == 0)
					continue;
				if (pp->aobus == false) {
					value = MUX_READ_4(sc, cp->mux_addr);
					value &= ~cp->mux_bits;
					MUX_WRITE_4(sc, cp->mux_addr, value);
				} else {
					value = AOMUX_READ_4(sc, cp->mux_addr);
					value &= ~cp->mux_bits;
					AOMUX_WRITE_4(sc, cp->mux_addr, value);
				}
			}

		/*
		 * Now set the desired mux bits.
		 *
		 * In the case of GPIO there's no bits to set.
		 */

		if (p->mux_bits != 0) {
			if (pp->aobus == false) {
				value = MUX_READ_4(sc, p->mux_addr);
				value |= p->mux_bits;
				MUX_WRITE_4(sc, p->mux_addr, value);
			} else {
				value = AOMUX_READ_4(sc, p->mux_addr);
				value |= p->mux_bits;
				AOMUX_WRITE_4(sc, p->mux_addr, value);
			}
		}

		/*
		 * Finally set the pull mode if it was specified.
		 */

		switch (pm) {
		case aml8726_enable_down_pm:
		case aml8726_enable_up_pm:
			if (pp->aobus == false) {
				value = PUD_READ_4(sc, pp->pull_addr);
				if (pm == aml8726_enable_down_pm)
					value &= ~pp->pull_bits;
				else
					value |= pp->pull_bits;
				PUD_WRITE_4(sc, pp->pull_addr, value);
			} else {
				value = AOPUD_READ_4(sc, pp->pull_addr);
				if (pm == aml8726_enable_down_pm)
					value &= ~(pp->pull_bits << 16);
				else
					value |= (pp->pull_bits << 16);
				AOPUD_WRITE_4(sc, pp->pull_addr, value);
			}
			/* FALLTHROUGH */
		case aml8726_disable_pm:
		case aml8726_enable_pm:
			if (pp->aobus == false) {
				value = PEN_READ_4(sc, pp->pull_addr);
				if (pm == aml8726_disable_pm)
					value &= ~pp->pull_bits;
				else
					value |= pp->pull_bits;
				PEN_WRITE_4(sc, pp->pull_addr, value);
			} else {
				value = AOPEN_READ_4(sc, pp->pull_addr);
				if (pm == aml8726_disable_pm)
					value &= ~pp->pull_bits;
				else
					value |= pp->pull_bits;
				AOPEN_WRITE_4(sc, pp->pull_addr, value);
			}
			break;
		default:
			break;
		}

		AML_PINCTRL_UNLOCK(sc);
	}

	OF_prop_free(pins);

	return (0);
}
Example #23
0
static int
qman_portals_fdt_attach(device_t dev)
{
	struct dpaa_portals_softc *sc;
	phandle_t node, child, cpu_node;
	vm_paddr_t portal_pa, portal_par_pa;
	vm_size_t portal_size;
	uint32_t addr, paddr, size;
	ihandle_t cpu;
	int cpu_num, cpus, intr_rid;
	struct dpaa_portals_devinfo di;
	struct ofw_bus_devinfo ofw_di = {};
	cell_t *range;
	int nrange;
	int i;

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

	node = ofw_bus_get_node(dev);

	/* Get this node's range */
	get_addr_props(ofw_bus_get_node(device_get_parent(dev)), &paddr, &size);
	get_addr_props(node, &addr, &size);

	nrange = OF_getencprop_alloc(node, "ranges",
	    sizeof(*range), (void **)&range);
	if (nrange < addr + paddr + size)
		return (ENXIO);
	portal_pa = portal_par_pa = 0;
	portal_size = 0;
	for (i = 0; i < addr; i++) {
		portal_pa <<= 32;
		portal_pa |= range[i];
	}
	for (; i < paddr + addr; i++) {
		portal_par_pa <<= 32;
		portal_par_pa |= range[i];
	}
	portal_pa += portal_par_pa;
	for (; i < size + paddr + addr; i++) {
		portal_size = (uintmax_t)portal_size << 32;
		portal_size |= range[i];
	}
	OF_prop_free(range);
	sc->sc_dp_size = portal_size;
	sc->sc_dp_pa = portal_pa;

	/* Find portals tied to CPUs */
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		if (cpus >= mp_ncpus)
			break;
		if (!ofw_bus_node_is_compatible(child, "fsl,qman-portal")) {
			continue;
		}
		/* Checkout related cpu */
		if (OF_getprop(child, "cpu-handle", (void *)&cpu,
		    sizeof(cpu)) <= 0) {
			cpu = qman_portal_find_cpu(cpus);
			if (cpu <= 0)
				continue;
		}
		/* Acquire cpu number */
		cpu_node = OF_instance_to_package(cpu);
		if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) {
			device_printf(dev, "Could not retrieve CPU number.\n");
			return (ENXIO);
		}

		cpus++;

		if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) {
			device_printf(dev, "could not set up devinfo\n");
			continue;
		}

		resource_list_init(&di.di_res);
		if (ofw_bus_reg_to_rl(dev, child, addr, size, &di.di_res)) {
			device_printf(dev, "%s: could not process 'reg' "
			    "property\n", ofw_di.obd_name);
			ofw_bus_gen_destroy_devinfo(&ofw_di);
			continue;
		}
		if (ofw_bus_intr_to_rl(dev, child, &di.di_res, &intr_rid)) {
			device_printf(dev, "%s: could not process "
			    "'interrupts' property\n", ofw_di.obd_name);
			resource_list_free(&di.di_res);
			ofw_bus_gen_destroy_devinfo(&ofw_di);
			continue;
		}
		di.di_intr_rid = intr_rid;

		if (dpaa_portal_alloc_res(dev, &di, cpu_num))
			goto err;
	}

	ofw_bus_gen_destroy_devinfo(&ofw_di);

	return (qman_portals_attach(dev));
err:
	resource_list_free(&di.di_res);
	ofw_bus_gen_destroy_devinfo(&ofw_di);
	qman_portals_detach(dev);
	return (ENXIO);
}
Example #24
0
static int
aml8726_ccm_configure_gates(struct aml8726_ccm_softc *sc)
{
	struct aml8726_ccm_function *f;
	struct aml8726_ccm_gate *g;
	char *function_name;
	char *functions;
	phandle_t node;
	ssize_t len;
	uint32_t value;

	node = ofw_bus_get_node(sc->dev);

	len = OF_getprop_alloc(node, "functions", sizeof(char),
	    (void **)&functions);

	if (len < 0) {
		device_printf(sc->dev, "missing functions attribute in FDT\n");
		return (ENXIO);
	}

	function_name = functions;

	while (len) {
		for (f = sc->soc; f->name != NULL; f++)
			if (strncmp(f->name, function_name, len) == 0)
				break;

		if (f->name == NULL) {
			/* display message prior to queuing up next string */
			device_printf(sc->dev,
			    "unknown function attribute %.*s in FDT\n",
			    len, function_name);
		}

		/* queue up next string */
		while (*function_name && len) {
			function_name++;
			len--;
		}
		if (len) {
			function_name++;
			len--;
		}

		if (f->name == NULL)
			continue;

		AML_CCM_LOCK(sc);

		/*
		 * Enable the clock gates necessary for the function.
		 *
		 * In some cases a clock may be shared across functions
		 * (meaning don't disable a clock without ensuring that
		 * it's not required by someone else).
		 */
		for (g = f->gates; g->bits != 0x00000000; g++) {
			value = CSR_READ_4(sc, g->addr);
			value |= g->bits;
			CSR_WRITE_4(sc, g->addr, value);
		}

		AML_CCM_UNLOCK(sc);
	}

	OF_prop_free(functions);

	return (0);
}
Example #25
0
static int
altera_avgen_fdt_attach(device_t dev)
{
	struct altera_avgen_softc *sc;
	char *str_fileio, *str_geomio, *str_mmapio;
	char *str_devname;
	phandle_t node;
	pcell_t cell;
	int devunit, error;

	sc = device_get_softc(dev);
	sc->avg_dev = dev;
	sc->avg_unit = device_get_unit(dev);

	/*
	 * Query driver-specific OpenFirmware properties to determine how to
	 * expose the device via /dev.
	 */
	str_fileio = NULL;
	str_geomio = NULL;
	str_mmapio = NULL;
	str_devname = NULL;
	devunit = -1;
	sc->avg_width = 1;
	node = ofw_bus_get_node(dev);
	if (OF_getprop(node, "sri-cambridge,width", &cell, sizeof(cell)) > 0)
		sc->avg_width = cell;
	(void)OF_getprop_alloc(node, "sri-cambridge,fileio", sizeof(char),
	    (void **)&str_fileio);
	(void)OF_getprop_alloc(node, "sri-cambridge,geomio", sizeof(char),
	    (void **)&str_geomio);
	(void)OF_getprop_alloc(node, "sri-cambridge,mmapio", sizeof(char),
	    (void **)&str_mmapio);
	(void)OF_getprop_alloc(node,  "sri-cambridge,devname", sizeof(char),
	    (void **)&str_devname);
	if (OF_getprop(node, "sri-cambridge,devunit", &cell, sizeof(cell)) > 0)
		devunit = cell;

	/* Memory allocation and checking. */
	sc->avg_rid = 0;
	sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &sc->avg_rid, RF_ACTIVE);
	if (sc->avg_res == NULL) {
		device_printf(dev, "couldn't map memory\n");
		return (ENXIO);
	}
	error = altera_avgen_attach(sc, str_fileio, str_geomio, str_mmapio,
	    str_devname, devunit);
	if (error != 0)
		bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
		    sc->avg_res);
	if (str_fileio != NULL)
		OF_prop_free(str_fileio);
	if (str_geomio != NULL)
		OF_prop_free(str_geomio);
	if (str_mmapio != NULL)
		OF_prop_free(str_mmapio);
	if (str_devname != NULL)
		OF_prop_free(str_devname);
	return (error);
}