Exemple #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));
}
Exemple #2
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);
	}

	free(cfgtuples, M_OFWPROP);

	return (0);
}
Exemple #3
0
int
ofw_bus_reg_to_rl(device_t dev, phandle_t node, pcell_t acells, pcell_t scells,
    struct resource_list *rl)
{
	uint64_t phys, size;
	ssize_t i, j, rid, nreg, ret;
	uint32_t *reg;
	char *name;

	/*
	 * This may be just redundant when having ofw_bus_devinfo
	 * but makes this routine independent of it.
	 */
	ret = OF_getencprop_alloc(node, "name", sizeof(*name), (void **)&name);
	if (ret == -1)
		name = NULL;

	ret = OF_getencprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
	nreg = (ret == -1) ? 0 : ret;

	if (nreg % (acells + scells) != 0) {
		if (bootverbose)
			device_printf(dev, "Malformed reg property on <%s>\n",
			    (name == NULL) ? "unknown" : name);
		nreg = 0;
	}

	for (i = 0, rid = 0; i < nreg; i += acells + scells, rid++) {
		phys = size = 0;
		for (j = 0; j < acells; j++) {
			phys <<= 32;
			phys |= reg[i + j];
		}
		for (j = 0; j < scells; j++) {
			size <<= 32;
			size |= reg[i + acells + j];
		}
		/* Skip the dummy reg property of glue devices like ssm(4). */
		if (size != 0)
			resource_list_add(rl, SYS_RES_MEMORY, rid,
			    phys, phys + size - 1, size);
	}
	free(name, M_OFWPROP);
	free(reg, M_OFWPROP);

	return (0);
}
static int
jz4780_pinctrl_configure_pins(device_t dev, phandle_t cfgxref)
{
	struct jz4780_pinctrl_softc *sc = device_get_softc(dev);
	device_t  chip;
	phandle_t node;
	ssize_t i, len;
	uint32_t *value, *pconf;
	int result;

	node = OF_node_from_xref(cfgxref);

	len = OF_getencprop_alloc(node, "ingenic,pins", sizeof(uint32_t) * 4,
	    (void **)&value);
	if (len < 0) {
		device_printf(dev,
		    "missing ingenic,pins attribute in FDT\n");
		return (ENXIO);
	}

	pconf = value;
	result = EINVAL;
	for (i = 0; i < len; i++, pconf += 4) {
		uint32_t bias;

		/* Lookup the chip that handles this configuration */
		chip = jz4780_pinctrl_chip_lookup(sc, pconf[0]);
		if (chip == NULL) {
			device_printf(dev,
			    "invalid gpio controller reference in FDT\n");
			goto done;
		}

		if (jz4780_pinctrl_parse_pincfg(pconf[3], &bias) != 0) {
			device_printf(dev,
			    "invalid pin bias for pin %u on %s in FDT\n",
			    pconf[1], ofw_bus_get_name(chip));
			goto done;
		}

		result = JZ4780_GPIO_CONFIGURE_PIN(chip, pconf[1], pconf[2],
		    bias);
		if (result != 0) {
			device_printf(dev,
			    "failed to configure pin %u on %s\n", pconf[1],
			    ofw_bus_get_name(chip));
			goto done;
		}
	}

	result = 0;
done:
	free(value, M_OFWPROP);
	return (result);
}
Exemple #5
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);
}
Exemple #6
0
int
ofw_bus_msimap(phandle_t node, uint16_t pci_rid, phandle_t *msi_parent,
    uint32_t *msi_rid)
{
	pcell_t *map, mask, msi_base, rid_base, rid_length;
	ssize_t len;
	uint32_t masked_rid, rid;
	int err, i;

	/* TODO: This should be OF_searchprop_alloc if we had it */
	len = OF_getencprop_alloc(node, "msi-map", sizeof(*map), (void **)&map);
	if (len < 0) {
		if (msi_parent != NULL) {
			*msi_parent = 0;
			OF_getencprop(node, "msi-parent", msi_parent,
			    sizeof(*msi_parent));
		}
		if (msi_rid != NULL)
			*msi_rid = pci_rid;
		return (0);
	}

	err = ENOENT;
	rid = 0;
	mask = 0xffffffff;
	OF_getencprop(node, "msi-map-mask", &mask, sizeof(mask));

	masked_rid = pci_rid & mask;
	for (i = 0; i < len; i += 4) {
		rid_base = map[i + 0];
		rid_length = map[i + 3];

		if (masked_rid < rid_base ||
		    masked_rid >= (rid_base + rid_length))
			continue;

		msi_base = map[i + 2];

		if (msi_parent != NULL)
			*msi_parent = map[i + 1];
		if (msi_rid != NULL)
			*msi_rid = masked_rid - rid_base + msi_base;
		err = 0;
		break;
	}

	free(map, M_OFWPROP);

	return (err);
}
Exemple #7
0
void
ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
{
	pcell_t addrc;
	int msksz;

	if (OF_getencprop(node, "#address-cells", &addrc, sizeof(addrc)) == -1)
		addrc = 2;
	ii->opi_addrc = addrc * sizeof(pcell_t);

	ii->opi_imapsz = OF_getencprop_alloc(node, "interrupt-map", 1,
	    (void **)&ii->opi_imap);
	if (ii->opi_imapsz > 0) {
		msksz = OF_getencprop_alloc(node, "interrupt-map-mask", 1,
		    (void **)&ii->opi_imapmsk);
		/*
		 * Failure to get the mask is ignored; a full mask is used
		 * then.  We barf on bad mask sizes, however.
		 */
		if (msksz != -1 && msksz != ii->opi_addrc + intrsz)
			panic("ofw_bus_setup_iinfo: bad interrupt-map-mask "
			    "property!");
	}
}
Exemple #8
0
/*
 * Parse property that contain list of xrefs and values
 * (like standard "clocks" and "resets" properties)
 * Input arguments:
 *  node - consumers device node
 *  list_name  - name of parsed list - "clocks"
 *  cells_name - name of size property - "#clock-cells"
 *  idx - the index of the requested list entry, or, if -1, an indication
 *        to return the number of entries in the parsed list.
 * Output arguments:
 *  producer - handle of producer
 *  ncells   - number of cells in result or the number of items in the list when
 *             idx == -1.
 *  cells    - array of decoded cells
 */
static int
ofw_bus_parse_xref_list_internal(phandle_t node, const char *list_name,
    const char *cells_name, int idx, phandle_t *producer, int *ncells,
    pcell_t **cells)
{
	phandle_t pnode;
	phandle_t *elems;
	uint32_t  pcells;
	int rv, i, j, nelems, cnt;

	elems = NULL;
	nelems = OF_getencprop_alloc(node, list_name,  sizeof(*elems),
	    (void **)&elems);
	if (nelems <= 0)
		return (ENOENT);
	rv = (idx == -1) ? 0 : ENOENT;
	for (i = 0, cnt = 0; i < nelems; i += pcells, cnt++) {
		pnode = elems[i++];
		if (OF_getencprop(OF_node_from_xref(pnode),
		    cells_name, &pcells, sizeof(pcells)) == -1) {
			printf("Missing %s property\n", cells_name);
			rv = ENOENT;
			break;
		}

		if ((i + pcells) > nelems) {
			printf("Invalid %s property value <%d>\n", cells_name,
			    pcells);
			rv = ERANGE;
			break;
		}
		if (cnt == idx) {
			*cells= malloc(pcells * sizeof(**cells), M_OFWPROP,
			    M_WAITOK);
			*producer = pnode;
			*ncells = pcells;
			for (j = 0; j < pcells; j++)
				(*cells)[j] = elems[i + j];
			rv = 0;
			break;
		}
	}
	if (elems != NULL)
		free(elems, M_OFWPROP);
	if (idx == -1 && rv == 0)
		*ncells = cnt;
	return (rv);
}
Exemple #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);
}
Exemple #10
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);
}
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);
}
Exemple #12
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);
}
Exemple #13
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);
}
Exemple #14
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);
}
Exemple #15
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);
}
Exemple #16
0
static struct ofwbus_devinfo *
ofwbus_setup_dinfo(device_t dev, phandle_t node)
{
	struct ofwbus_softc *sc;
	struct ofwbus_devinfo *ndi;
	uint32_t *reg, *intr, icells;
	uint64_t phys, size;
	phandle_t iparent;
	int i, j;
	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->ndi_obdinfo, node) != 0) {
		free(ndi, M_DEVBUF);
		return (NULL);
	}
	if (OFWBUS_EXCLUDED(ndi->ndi_obdinfo.obd_name,
	    ndi->ndi_obdinfo.obd_type)) {
		ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
		free(ndi, M_DEVBUF);
		return (NULL);
	}

	resource_list_init(&ndi->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->ndi_obdinfo.obd_name);
		nreg = 0;
	}

	for (i = 0; i < nreg; i += sc->acells + sc->scells) {
		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];
		}
		/* Skip the dummy reg property of glue devices like ssm(4). */
		if (size != 0)
			resource_list_add(&ndi->ndi_rl, SYS_RES_MEMORY, i,
			    phys, phys + size - 1, size);
	}
	free(reg, M_OFWPROP);

	nintr = OF_getencprop_alloc(node, "interrupts",  sizeof(*intr),
	    (void **)&intr);
	if (nintr > 0) {
		iparent = 0;
		OF_searchencprop(node, "interrupt-parent", &iparent,
		    sizeof(iparent));
		OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells",
		    &icells, sizeof(icells));
		for (i = 0; i < nintr; i+= icells) {
			intr[i] = ofw_bus_map_intr(dev, iparent, icells,
			    &intr[i]);
			resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
			    intr[i], 1);
		}
		free(intr, M_OFWPROP);
	}

	return (ndi);
}
Exemple #17
0
int
ofw_bus_intr_to_rl(device_t dev, phandle_t node,
    struct resource_list *rl, int *rlen)
{
	phandle_t iparent;
	uint32_t icells, *intr;
	int err, i, irqnum, nintr, rid;
	boolean_t extended;

	nintr = OF_getencprop_alloc(node, "interrupts",  sizeof(*intr),
	    (void **)&intr);
	if (nintr > 0) {
		iparent = ofw_bus_find_iparent(node);
		if (iparent == 0) {
			device_printf(dev, "No interrupt-parent found, "
			    "assuming direct parent\n");
			iparent = OF_parent(node);
			iparent = OF_xref_from_node(iparent);
		}
		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;
		}
		extended = false;
	} else {
		nintr = OF_getencprop_alloc(node, "interrupts-extended",
		    sizeof(*intr), (void **)&intr);
		if (nintr <= 0)
			return (0);
		extended = true;
	}
	err = 0;
	rid = 0;
	for (i = 0; i < nintr; i += icells) {
		if (extended) {
			iparent = intr[i++];
			if (OF_searchencprop(OF_node_from_xref(iparent), 
			    "#interrupt-cells", &icells, sizeof(icells)) == -1) {
				device_printf(dev, "Missing #interrupt-cells "
				    "property\n");
				err = ENOENT;
				break;
			}
			if (icells < 1 || (i + icells) > nintr) {
				device_printf(dev, "Invalid #interrupt-cells "
				    "property value <%d>\n", icells);
				err = ERANGE;
				break;
			}
		}
		irqnum = ofw_bus_map_intr(dev, iparent, icells, &intr[i]);
		resource_list_add(rl, SYS_RES_IRQ, rid++, irqnum, irqnum, 1);
	}
	if (rlen != NULL)
		*rlen = rid;
	free(intr, M_OFWPROP);
	return (err);
}
static int
aml8726_usb_phy_attach(device_t dev)
{
	struct aml8726_usb_phy_softc *sc = device_get_softc(dev);
	int err;
	int npwr_en;
	pcell_t *prop;
	phandle_t node;
	ssize_t len;
	uint32_t div;
	uint32_t i;
	uint32_t mode_a;
	uint32_t mode_b;
	uint32_t value;

	sc->dev = dev;

	if (aml8726_usb_phy_mode("/soc/usb@c9040000", &mode_a) != 0) {
		device_printf(dev, "missing usb@c9040000 node in FDT\n");
		return (ENXIO);
	}

	if (aml8726_usb_phy_mode("/soc/usb@c90c0000", &mode_b) != 0) {
		device_printf(dev, "missing usb@c90c0000 node in FDT\n");
		return (ENXIO);
	}

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

	node = ofw_bus_get_node(dev);

	err = 0;

	len = OF_getencprop_alloc(node, "usb-pwr-en",
	    3 * sizeof(pcell_t), (void **)&prop);
	npwr_en = (len > 0) ? len : 0;

	sc->npwr_en = 0;
	sc->pwr_en = (struct aml8726_usb_phy_gpio *)
	    malloc(npwr_en * sizeof (*sc->pwr_en), M_DEVBUF, M_WAITOK);

	for (i = 0; i < npwr_en; i++) {
		sc->pwr_en[i].dev = OF_device_from_xref(prop[i * 3]);
		sc->pwr_en[i].pin = prop[i * 3 + 1];
		sc->pwr_en[i].pol = prop[i * 3 + 2];

		if (sc->pwr_en[i].dev == NULL) {
			err = 1;
			break;
		}
	}

	free(prop, M_OFWPROP);

	if (err) {
		device_printf(dev, "unable to parse gpio\n");
		goto fail;
	}

	/* Turn on power by setting pin and then enabling output driver. */
	for (i = 0; i < npwr_en; i++) {
		if (GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin,
		    PIN_ON_FLAG(sc->pwr_en[i].pol)) != 0 ||
		    GPIO_PIN_SETFLAGS(sc->pwr_en[i].dev, sc->pwr_en[i].pin,
		    GPIO_PIN_OUTPUT) != 0) {
			device_printf(dev,
			    "could not use gpio to control power\n");
			goto fail;
		}

		sc->npwr_en++;
	}

	/*
	 * Configure the clock source and divider.
	 */

	div = 2;

	value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG);

	value &= ~(AML_USB_PHY_CFG_CLK_DIV_MASK | AML_USB_PHY_CFG_CLK_SEL_MASK);

	value &= ~(AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST);
	value &= ~(AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST);
	value &= ~(AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST);
	value &= ~(AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR);

	value |= AML_USB_PHY_CFG_CLK_SEL_XTAL;
	value |= ((div - 1) << AML_USB_PHY_CFG_CLK_DIV_SHIFT) &
	    AML_USB_PHY_CFG_CLK_DIV_MASK;
	value |= AML_USB_PHY_CFG_CLK_EN;

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	/*
	 * Issue the reset sequence.
	 */

	value |= (AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value &= ~(AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value |= (AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value &= ~(AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value |= (AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value &= ~(AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	value |= (AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);
	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	/*
	 * Enable by clearing the power on reset.
	 */

	value &= ~(AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR);

	CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value);

	CSR_BARRIER(sc, AML_USB_PHY_CFG_REG);

	DELAY(200);

	/*
	 * Check if the clock was detected.
	 */
	value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG);
	if ((value & AML_USB_PHY_CFG_CLK_DETECTED) !=
	    AML_USB_PHY_CFG_CLK_DETECTED)
		device_printf(dev, "PHY Clock not detected\n");

	/*
	 * Configure the mode for each port.
	 */

	value = CSR_READ_4(sc, AML_USB_PHY_MISC_A_REG);

	value &= ~(AML_USB_PHY_MISC_ID_OVERIDE_EN |
	    AML_USB_PHY_MISC_ID_OVERIDE_DEVICE |
	    AML_USB_PHY_MISC_ID_OVERIDE_HOST);
	value |= mode_a;

	CSR_WRITE_4(sc, AML_USB_PHY_MISC_A_REG, value);

	value = CSR_READ_4(sc, AML_USB_PHY_MISC_B_REG);

	value &= ~(AML_USB_PHY_MISC_ID_OVERIDE_EN |
	    AML_USB_PHY_MISC_ID_OVERIDE_DEVICE |
	    AML_USB_PHY_MISC_ID_OVERIDE_HOST);
	value |= mode_b;

	CSR_WRITE_4(sc, AML_USB_PHY_MISC_B_REG, value);

	CSR_BARRIER(sc, AML_USB_PHY_MISC_B_REG);

	return (0);

fail:
	/* In the event of problems attempt to turn things back off. */
	i = sc->npwr_en;
	while (i-- != 0) {
		GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin,
		    PIN_OFF_FLAG(sc->pwr_en[i].pol));
	}

	free (sc->pwr_en, M_DEVBUF);
	sc->pwr_en = NULL;

	bus_release_resources(dev, aml8726_usb_phy_spec, sc->res);

	return (ENXIO);
}