Beispiel #1
0
static int
central_attach(device_t dev)
{
	struct central_devinfo *cdi;
	struct sbus_regs *reg;
	struct central_softc *sc;
	phandle_t child;
	phandle_t node;
	device_t cdev;
	int nreg;
	int i;

	sc = device_get_softc(dev);
	node = ofw_bus_get_node(dev);

	sc->sc_nrange = OF_getprop_alloc(node, "ranges",
	    sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges);
	if (sc->sc_nrange == -1) {
		device_printf(dev, "can't get ranges\n");
		return (ENXIO);
	}

	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		cdi = malloc(sizeof(*cdi), M_DEVBUF, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(&cdi->cdi_obdinfo, child) != 0) {
			free(cdi, M_DEVBUF);
			continue;
		}
		nreg = OF_getprop_alloc(child, "reg", sizeof(*reg),
		    (void **)&reg);
		if (nreg == -1) {
			device_printf(dev, "<%s>: incomplete\n",
			    cdi->cdi_obdinfo.obd_name);
			ofw_bus_gen_destroy_devinfo(&cdi->cdi_obdinfo);
			free(cdi, M_DEVBUF);
			continue;
		}
		resource_list_init(&cdi->cdi_rl);
		for (i = 0; i < nreg; i++)
			resource_list_add(&cdi->cdi_rl, SYS_RES_MEMORY, i,
			    reg[i].sbr_offset, reg[i].sbr_offset +
			    reg[i].sbr_size, reg[i].sbr_size);
		free(reg, M_OFWPROP);
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    cdi->cdi_obdinfo.obd_name);
			resource_list_free(&cdi->cdi_rl);
			ofw_bus_gen_destroy_devinfo(&cdi->cdi_obdinfo);
			free(cdi, M_DEVBUF);
			continue;
		}
		device_set_ivars(cdev, cdi);
	}

	return (bus_generic_attach(dev));
}
Beispiel #2
0
static int 
ofw_cpulist_attach(device_t dev) 
{
	phandle_t root, child;
	device_t cdev;
	struct ofw_bus_devinfo *dinfo;

	root = ofw_bus_get_node(dev);

	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_OFWCPU, M_WAITOK | M_ZERO);

                if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) {
                        free(dinfo, M_OFWCPU);
                        continue;
                }
                cdev = device_add_child(dev, NULL, -1);
                if (cdev == NULL) {
                        device_printf(dev, "<%s>: device_add_child failed\n",
                            dinfo->obd_name);
                        ofw_bus_gen_destroy_devinfo(dinfo);
                        free(dinfo, M_OFWCPU);
                        continue;
                }
		device_set_ivars(cdev, dinfo);
	}

	return (bus_generic_attach(dev));
}
Beispiel #3
0
static void
ofwbus_destroy_dinfo(struct ofwbus_devinfo *ndi)
{

	resource_list_free(&ndi->ndi_rl);
	ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
	free(ndi, M_DEVBUF);
}
static void
ebus_destroy_dinfo(struct ebus_devinfo *edi)
{

	resource_list_free(&edi->edi_rl);
	ofw_bus_gen_destroy_devinfo(&edi->edi_obdinfo);
	free(edi, M_DEVBUF);
}
Beispiel #5
0
static void
lebuffer_destroy_dinfo(struct lebuffer_devinfo *dinfo)
{

	resource_list_free(&dinfo->ldi_rl);
	ofw_bus_gen_destroy_devinfo(&dinfo->ldi_obdinfo);
	free(dinfo, M_DEVBUF);
}
static void
dma_destroy_dinfo(struct dma_devinfo *dinfo)
{

	resource_list_free(&dinfo->ddi_rl);
	ofw_bus_gen_destroy_devinfo(&dinfo->ddi_obdinfo);
	free(dinfo, M_DEVBUF);
}
Beispiel #7
0
static void
ofw_pcibus_child_deleted(device_t dev, device_t child)
{
	struct ofw_pcibus_devinfo *dinfo;

	dinfo = device_get_ivars(dev);
	ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo);
	pci_child_deleted(dev, child);
}
Beispiel #8
0
/*
 * Bus capability support for GICv3.
 * Collects and configures device informations and finally
 * adds ITS device as a child of GICv3 in Newbus hierarchy.
 */
static int
gic_v3_ofw_bus_attach(device_t dev)
{
	struct gic_v3_ofw_devinfo *di;
	device_t child;
	phandle_t parent, node;
	pcell_t addr_cells, size_cells;

	parent = ofw_bus_get_node(dev);
	if (parent > 0) {
		addr_cells = 2;
		OF_getencprop(parent, "#address-cells", &addr_cells,
		    sizeof(addr_cells));
		size_cells = 2;
		OF_getencprop(parent, "#size-cells", &size_cells,
		    sizeof(size_cells));
		/* Iterate through all GIC subordinates */
		for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
			/* Allocate and populate devinfo. */
			di = malloc(sizeof(*di), M_GIC_V3, M_WAITOK | M_ZERO);
			if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node)) {
				if (bootverbose) {
					device_printf(dev,
					    "Could not set up devinfo for ITS\n");
				}
				free(di, M_GIC_V3);
				continue;
			}

			/* Initialize and populate resource list. */
			resource_list_init(&di->di_rl);
			ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells,
			    &di->di_rl);

			/* Should not have any interrupts, so don't add any */

			/* Add newbus device for this FDT node */
			child = device_add_child(dev, NULL, -1);
			if (!child) {
				if (bootverbose) {
					device_printf(dev,
					    "Could not add child: %s\n",
					    di->di_dinfo.obd_name);
				}
				resource_list_free(&di->di_rl);
				ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
				free(di, M_GIC_V3);
				continue;
			}

			device_set_ivars(child, di);
		}
	}

	return (bus_generic_attach(dev));
}
Beispiel #9
0
static int 
vdevice_attach(device_t dev) 
{
	phandle_t root, child;
	device_t cdev;
	int icells, i, nintr, *intr;
	phandle_t iparent;
	struct vdevice_devinfo *dinfo;

	root = ofw_bus_get_node(dev);

	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO);

                if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo,
		    child) != 0) {
                        free(dinfo, M_DEVBUF);
                        continue;
                }
		resource_list_init(&dinfo->mdi_resources);

		if (OF_searchprop(child, "#interrupt-cells", &icells,
		    sizeof(icells)) <= 0)
			icells = 2;
		if (OF_getprop(child, "interrupt-parent", &iparent,
		    sizeof(iparent)) <= 0)
			iparent = -1;
		nintr = OF_getprop_alloc(child, "interrupts", sizeof(*intr),
		    (void **)&intr);
		if (nintr > 0) {
			for (i = 0; i < nintr; i += icells) {
				u_int irq = intr[i];
				if (iparent != -1)
					irq = ofw_bus_map_intr(dev, iparent,
					    icells, &intr[i]);

				resource_list_add(&dinfo->mdi_resources,
				    SYS_RES_IRQ, i, irq, irq, i);
			}
		}

                cdev = device_add_child(dev, NULL, -1);
                if (cdev == NULL) {
                        device_printf(dev, "<%s>: device_add_child failed\n",
                            dinfo->mdi_obdinfo.obd_name);
                        ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
                        free(dinfo, M_DEVBUF);
                        continue;
                }
		device_set_ivars(cdev, dinfo);
	}

	return (bus_generic_attach(dev));
}
Beispiel #10
0
static int
opaldev_attach(device_t dev)
{
	phandle_t child;
	device_t cdev;
	uint64_t junk;
	int i, rv;
	struct ofw_bus_devinfo *dinfo;
	struct resource *irq;

	/* Test for RTC support and register clock if it works */
	rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk));
	do {
		rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk));
		if (rv == OPAL_BUSY_EVENT)
			rv = opal_call(OPAL_POLL_EVENTS, 0);
	} while (rv == OPAL_BUSY_EVENT);

	if (rv == OPAL_SUCCESS)
		clock_register(dev, 2000);
	
	EVENTHANDLER_REGISTER(shutdown_final, opal_shutdown, NULL,
	    SHUTDOWN_PRI_LAST);

	/* Bind to interrupts */
	for (i = 0; (irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
	    RF_ACTIVE)) != NULL; i++)
		bus_setup_intr(dev, irq, INTR_TYPE_TTY | INTR_MPSAFE |
		    INTR_ENTROPY, NULL, opal_intr, (void *)rman_get_start(irq),
		    NULL);

	for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
	    child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) {
			free(dinfo, M_DEVBUF);
			continue;
		}
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    dinfo->obd_name);
			ofw_bus_gen_destroy_devinfo(dinfo);
			free(dinfo, M_DEVBUF);
			continue;
		}
		device_set_ivars(cdev, dinfo);
	}

	return (bus_generic_attach(dev));
}
Beispiel #11
0
static struct ofw_gpiobus_devinfo *
ofw_gpiobus_setup_devinfo(device_t bus, device_t child, phandle_t node)
{
	int i, npins;
	struct gpiobus_ivar *devi;
	struct gpiobus_pin *pins;
	struct gpiobus_softc *sc;
	struct ofw_gpiobus_devinfo *dinfo;

	sc = device_get_softc(bus);
	dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (dinfo == NULL)
		return (NULL);
	if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0) {
		free(dinfo, M_DEVBUF);
		return (NULL);
	}
	/* Parse the gpios property for the child. */
	npins = ofw_gpiobus_parse_gpios_impl(child, node, "gpios", sc, &pins);
	if (npins <= 0) {
		ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo);
		free(dinfo, M_DEVBUF);
		return (NULL);
	}
	/* Initialize the irq resource list. */
	resource_list_init(&dinfo->opd_dinfo.rl);
	/* Allocate the child ivars and copy the parsed pin data. */
	devi = &dinfo->opd_dinfo;
	devi->npins = (uint32_t)npins;
	if (gpiobus_alloc_ivars(devi) != 0) {
		free(pins, M_DEVBUF);
		ofw_gpiobus_destroy_devinfo(bus, dinfo);
		return (NULL);
	}
	for (i = 0; i < devi->npins; i++) {
		devi->flags[i] = pins[i].flags;
		devi->pins[i] = pins[i].pin;
	}
	free(pins, M_DEVBUF);
#ifndef INTRNG
	/* Parse the interrupt resources. */
	if (ofw_bus_intr_to_rl(bus, node, &dinfo->opd_dinfo.rl, NULL) != 0) {
		ofw_gpiobus_destroy_devinfo(bus, dinfo);
		return (NULL);
	}
#endif
	device_set_ivars(child, dinfo);

	return (dinfo);
}
Beispiel #12
0
static int
simplebus_attach(device_t dev)
{
	struct		simplebus_softc *sc;
	struct		simplebus_devinfo *di;
	phandle_t	node;
	device_t	cdev;

	node = ofw_bus_get_node(dev);
	sc = device_get_softc(dev);

	sc->dev = dev;
	sc->node = node;

	/*
	 * Some important numbers
	 */
	sc->acells = 2;
	OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
	sc->scells = 1;
	OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));

	if (simplebus_fill_ranges(node, sc) < 0) {
		device_printf(dev, "could not get ranges\n");
		return (ENXIO);
	}

	/*
	 * In principle, simplebus could have an interrupt map, but ignore that
	 * for now
	 */

	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
		if ((di = simplebus_setup_dinfo(dev, node)) == NULL)
			continue;
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    di->obdinfo.obd_name);
			resource_list_free(&di->rl);
			ofw_bus_gen_destroy_devinfo(&di->obdinfo);
			free(di, M_DEVBUF);
			continue;
		}
		device_set_ivars(cdev, di);
	}

	return (bus_generic_attach(dev));
}
Beispiel #13
0
static int
mdionexus_ofw_bus_attach(device_t dev)
{
	struct simplebus_softc *sc;
	struct mdionexus_ofw_devinfo *di;
	device_t child;
	phandle_t parent, node;

	parent = ofw_bus_get_node(dev);
	simplebus_init(dev, parent);

	sc = (struct simplebus_softc *)device_get_softc(dev);

	if (mdionexus_ofw_fill_ranges(parent, sc) < 0) {
		device_printf(dev, "could not get ranges\n");
		return (ENXIO);
	}
	/* Iterate through all bus subordinates */
	for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
		/* Allocate and populate devinfo. */
		di = malloc(sizeof(*di), M_THUNDER_MDIO, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
			free(di, M_THUNDER_MDIO);
			continue;
		}

		/* Initialize and populate resource list. */
		resource_list_init(&di->di_rl);
		ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells,
		    &di->di_rl);
#ifndef INTRNG
		ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL);
#endif

		/* Add newbus device for this FDT node */
		child = device_add_child(dev, NULL, -1);
		if (child == NULL) {
			resource_list_free(&di->di_rl);
			ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
			free(di, M_THUNDER_MDIO);
			continue;
		}

		device_set_ivars(child, di);
	}

	return (0);
}
Beispiel #14
0
static int
at91_pinctrl_attach(device_t dev)
{
	struct pinctrl_softc *sc;
	struct pinctrl_devinfo *di;
	phandle_t	node;
	device_t	cdev;

	sc = device_get_softc(dev);
	node = ofw_bus_get_node(dev);

	sc->dev = dev;
	sc->node = node;
	
	/*
	 * Some important numbers
	 */
	sc->acells = 2;
	OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
	sc->scells = 1;
	OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));

	if (at91_pinctrl_fill_ranges(node, sc) < 0) {
		device_printf(dev, "could not get ranges\n");
		return (ENXIO);
	}

	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
		if ((di = at91_pinctrl_setup_dinfo(dev, node)) == NULL)
			continue;
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    di->obdinfo.obd_name);
			resource_list_free(&di->rl);
			ofw_bus_gen_destroy_devinfo(&di->obdinfo);
			free(di, M_DEVBUF);
			continue;
		}
		device_set_ivars(cdev, di);
	}

	fdt_pinctrl_register(dev, "atmel,pins");

	return (bus_generic_attach(dev));
}
Beispiel #15
0
static void
ofw_gpiobus_destroy_devinfo(device_t bus, struct ofw_gpiobus_devinfo *dinfo)
{
	int i;
	struct gpiobus_ivar *devi;
	struct gpiobus_softc *sc;

	sc = device_get_softc(bus);
	devi = &dinfo->opd_dinfo;
	for (i = 0; i < devi->npins; i++) {
		if (devi->pins[i] > sc->sc_npins)
			continue;
		sc->sc_pins[devi->pins[i]].mapped = 0;
	}
	gpiobus_free_ivars(devi);
	resource_list_free(&dinfo->opd_dinfo.rl);
	ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo);
	free(dinfo, M_DEVBUF);
}
Beispiel #16
0
device_t
simplebus_add_device(device_t dev, phandle_t node, u_int order,
    const char *name, int unit, struct simplebus_devinfo *di)
{
	struct simplebus_devinfo *ndi;
	device_t cdev;

	if ((ndi = simplebus_setup_dinfo(dev, node, di)) == NULL)
		return (NULL);
	cdev = device_add_child_ordered(dev, order, name, unit);
	if (cdev == NULL) {
		device_printf(dev, "<%s>: device_add_child failed\n",
		    ndi->obdinfo.obd_name);
		resource_list_free(&ndi->rl);
		ofw_bus_gen_destroy_devinfo(&ndi->obdinfo);
		if (di == NULL)
			free(ndi, M_DEVBUF);
		return (NULL);
	}
	device_set_ivars(cdev, ndi);

	return(cdev);
}
Beispiel #17
0
static int
lbc_attach(device_t dev)
{
	struct lbc_softc *sc;
	struct lbc_devinfo *di;
	struct rman *rm;
	u_long offset, start, size;
	device_t cdev;
	phandle_t node, child;
	pcell_t *ranges, *rangesptr;
	int tuple_size, tuples;
	int par_addr_cells;
	int bank, error, i;

	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";
	rm->rm_start = 0UL;
	rm->rm_end = ~0UL;
	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_getprop_alloc(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((void *)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 = fdt_data_get((void *)ranges, sc->sc_addr_cells - 1);
		ranges += sc->sc_addr_cells - 1;

		/* Parent bus start address of this bank. */
		start = fdt_data_get((void *)ranges, par_addr_cells);
		ranges += par_addr_cells;

		size = fdt_data_get((void *)ranges, sc->sc_size_cells);
		ranges += sc->sc_size_cells;
		debugf("bank = %d, start = %lx, size = %lx\n", bank,
		    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=%p\n", di->di_ofw.obd_name,
		    (void *)child);
		device_set_ivars(cdev, di);
	}

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

	free(rangesptr, M_OFWPROP);
	return (bus_generic_attach(dev));

fail:
	free(rangesptr, M_OFWPROP);
	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres);
	return (error);
}
Beispiel #18
0
static int
simplebus_attach(device_t dev)
{
	device_t dev_child;
	struct simplebus_devinfo *di;
	struct simplebus_softc *sc;
	phandle_t dt_node, dt_child;

	sc = device_get_softc(dev);

	/*
	 * Walk simple-bus and add direct subordinates as our children.
	 */
	dt_node = ofw_bus_get_node(dev);
	for (dt_child = OF_child(dt_node); dt_child != 0;
	    dt_child = OF_peer(dt_child)) {

		/* Check and process 'status' property. */
		if (!(fdt_is_enabled(dt_child)))
			continue;

		if (!(fdt_pm_is_enabled(dt_child)))
			continue;

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

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

		resource_list_init(&di->di_res);
		if (fdt_reg_to_rl(dt_child, &di->di_res)) {
			device_printf(dev,
			    "%s: could not process 'reg' "
			    "property\n", di->di_ofw.obd_name);
			/* XXX should unmap */
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_SIMPLEBUS);
			continue;
		}

		if (fdt_intr_to_rl(dt_child, &di->di_res, di->di_intr_sl)) {
			device_printf(dev, "%s: could not process "
			    "'interrupts' property\n", di->di_ofw.obd_name);
			resource_list_free(&di->di_res);
			/* XXX should unmap */
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_SIMPLEBUS);
			continue;
		}

		/* Add newbus device for this FDT node */
		dev_child = device_add_child(dev, NULL, -1);
		if (dev_child == NULL) {
			device_printf(dev, "could not add child: %s\n",
			    di->di_ofw.obd_name);
			resource_list_free(&di->di_res);
			/* XXX should unmap */
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_SIMPLEBUS);
			continue;
		}
#ifdef DEBUG
		device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name);
#endif
		device_set_ivars(dev_child, di);
	}

	return (bus_generic_attach(dev));
}
Beispiel #19
0
static struct nexus_devinfo *
nexus_setup_dinfo(device_t dev, phandle_t node)
{
	struct nexus_softc *sc;
	struct nexus_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 (NEXUS_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_getprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
	if (nreg == -1)
		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_getprop_alloc(node, "interrupts",  sizeof(*intr),
	    (void **)&intr);
	if (nintr > 0) {
		iparent = 0;
		OF_searchprop(node, "interrupt-parent", &iparent,
		    sizeof(iparent));
		OF_searchprop(iparent, "#interrupt-cells", &icells,
		    sizeof(icells));
		for (i = 0; i < nintr; i+= icells) {
			intr[i] = MAP_IRQ(iparent, intr[i]);
			resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
			    intr[i], 1);
			if (icells > 1) {
				powerpc_config_intr(intr[i], (intr[i+1] & 1) ?
				    INTR_TRIGGER_LEVEL : INTR_TRIGGER_EDGE,
				    INTR_POLARITY_LOW);
			}
		}
		free(intr, M_OFWPROP);
	}

	return (ndi);
}
Beispiel #20
0
static struct nexus_devinfo *
nexus_setup_dinfo(device_t dev, phandle_t node)
{
    struct nexus_devinfo *ndi;
    struct nexus_regs *reg;
    bus_addr_t phys;
    bus_size_t size;
    uint32_t ign;
    uint32_t *intr;
    int i;
    int nintr;
    int nreg;

    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 (NEXUS_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_getprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
    if (nreg == -1) {
        device_printf(dev, "<%s>: incomplete\n",
                      ndi->ndi_obdinfo.obd_name);
        goto fail;
    }
    for (i = 0; i < nreg; i++) {
        phys = NEXUS_REG_PHYS(&reg[i]);
        size = NEXUS_REG_SIZE(&reg[i]);
        /* 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_getprop_alloc(node, "interrupts",  sizeof(*intr),
                             (void **)&intr);
    if (nintr > 0) {
        if (OF_getprop(node, PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII ?
                       "upa-portid" : "portid", &ign, sizeof(ign)) <= 0) {
            device_printf(dev, "<%s>: could not determine portid\n",
                          ndi->ndi_obdinfo.obd_name);
            free(intr, M_OFWPROP);
            goto fail;
        }

        /* XXX 7-bit MID on Starfire */
        ign = (ign << INTMAP_IGN_SHIFT) & INTMAP_IGN_MASK;
        for (i = 0; i < nintr; i++) {
            intr[i] |= ign;
            resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
                              intr[i], 1);
        }
        free(intr, M_OFWPROP);
    }

    return (ndi);

fail:
    nexus_destroy_dinfo(ndi);
    return (NULL);
}
Beispiel #21
0
static int
qman_portals_fdt_attach(device_t dev)
{
	struct dpaa_portals_softc *sc;
	struct resource_list_entry *rle;
	phandle_t node, child, cpu_node;
	vm_paddr_t portal_pa;
	vm_size_t portal_size;
	uint32_t addr, size;
	ihandle_t cpu;
	int cpu_num, cpus, intr_rid;
	struct dpaa_portals_devinfo di;
	struct ofw_bus_devinfo ofw_di = {};

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

	node = ofw_bus_get_node(dev);
	get_addr_props(node, &addr, &size);

	/* Find portals tied to CPUs */
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		if (!fdt_is_compatible(child, "fsl,qman-portal")) {
			continue;
		}
		/* Checkout related cpu */
		if (OF_getprop(child, "cpu-handle", (void *)&cpu,
		    sizeof(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 (cpus > MAXCPU)
			break;

		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;
		
		ofw_reg_to_paddr(child, 0, &portal_pa, &portal_size, NULL);
		rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 0);

		if (sc->sc_dp_pa == 0)
			sc->sc_dp_pa = portal_pa - rle->start;

		portal_size = rle->end + 1;
		rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 1);
		portal_size = ulmax(rle->end + 1, portal_size);
		sc->sc_dp_size = ulmax(sc->sc_dp_size, portal_size);

		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);
}
Beispiel #22
0
static int
mv_pcib_ofw_bus_attach(device_t dev)
{
	struct mv_pcib_ctrl_devinfo *di;
	struct mv_pcib_ctrl_softc *sc;
	device_t child;
	phandle_t parent, node;
	get_rl_t get_rl;

	parent = ofw_bus_get_node(dev);
	sc = device_get_softc(dev);
	if (parent > 0) {
		sc->addr_cells = 1;
		if (OF_getencprop(parent, "#address-cells", &(sc->addr_cells),
		    sizeof(sc->addr_cells)) <= 0)
			return(ENXIO);

		sc->size_cells = 1;
		if (OF_getencprop(parent, "#size-cells", &(sc->size_cells),
		    sizeof(sc->size_cells)) <= 0)
			return(ENXIO);

		for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
			di = malloc(sizeof(*di), M_PCIB_CTRL, M_WAITOK | M_ZERO);
			if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node)) {
				if (bootverbose) {
					device_printf(dev,
					    "Could not set up devinfo for PCI\n");
				}
				free(di, M_PCIB_CTRL);
				continue;
			}

			child = device_add_child(dev, NULL, -1);
			if (child == NULL) {
				if (bootverbose) {
					device_printf(dev,
					    "Could not add child: %s\n",
					    di->di_dinfo.obd_name);
				}
				ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
				free(di, M_PCIB_CTRL);
				continue;
			}

			resource_list_init(&di->di_rl);
			get_rl = (get_rl_t) ofw_bus_search_compatible(dev,
			    mv_pcib_ctrl_compat)->ocd_data;
			if (get_rl != NULL)
				get_rl(child, node, sc->addr_cells,
				    sc->size_cells, &di->di_rl);

			device_set_ivars(child, di);
		}
	}

	if (mv_pcib_ctrl_fill_ranges(parent, sc) < 0) {
		device_printf(dev, "could not get ranges\n");
		return (ENXIO);
	}

	return (0);
}
Beispiel #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);
}
Beispiel #24
0
static int
unin_chip_attach(device_t dev)
{
	struct unin_chip_softc *sc;
	struct unin_chip_devinfo *dinfo;
	phandle_t  root;
	phandle_t  child;
	phandle_t  iparent;
	device_t   cdev;
	cell_t     acells, scells;
	char compat[32];
	char name[32];
	u_int irq, reg[3];
	int error, i = 0;

	sc = device_get_softc(dev);
	root = ofw_bus_get_node(dev);

	if (OF_getprop(root, "reg", reg, sizeof(reg)) < 8)
		return (ENXIO);

	acells = scells = 1;
	OF_getprop(OF_parent(root), "#address-cells", &acells, sizeof(acells));
	OF_getprop(OF_parent(root), "#size-cells", &scells, sizeof(scells));

	i = 0;
	sc->sc_physaddr = reg[i++];
	if (acells == 2) {
		sc->sc_physaddr <<= 32;
		sc->sc_physaddr |= reg[i++];
	}
	sc->sc_size = reg[i++];
	if (scells == 2) {
		sc->sc_size <<= 32;
		sc->sc_size |= reg[i++];
	}

	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
	sc->sc_mem_rman.rm_descr = "UniNorth Device Memory";

	error = rman_init(&sc->sc_mem_rman);

	if (error) {
		device_printf(dev, "rman_init() failed. error = %d\n", error);
		return (error);
	}

	error = rman_manage_region(&sc->sc_mem_rman, sc->sc_physaddr,
				   sc->sc_physaddr + sc->sc_size - 1);	
	if (error) {
		device_printf(dev,
			      "rman_manage_region() failed. error = %d\n",
			      error);
		return (error);
	}

	if (unin_chip == NULL)
		unin_chip = dev;

        /*
	 * Iterate through the sub-devices
	 */
	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_UNIN, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(&dinfo->udi_obdinfo, child)
		    != 0)
		{
			free(dinfo, M_UNIN);
			continue;
		}

		resource_list_init(&dinfo->udi_resources);
		dinfo->udi_ninterrupts = 0;
		unin_chip_add_intr(child, dinfo);

		/*
		 * Some Apple machines do have a bug in OF, they miss
		 * the interrupt entries on the U3 I2C node. That means they
		 * do not have an entry with number of interrupts nor the
		 * entry of the interrupt parent handle.
		 * We define an interrupt and hardwire it to the /u3/mpic
		 * handle.
		 */

		if (OF_getprop(child, "name", name, sizeof(name)) <= 0)
			device_printf(dev, "device has no name!\n");
		if (dinfo->udi_ninterrupts == 0 &&
		    (strcmp(name, "i2c-bus") == 0 ||
		     strcmp(name, "i2c")  == 0)) {
			if (OF_getprop(child, "interrupt-parent", &iparent,
				       sizeof(iparent)) <= 0) {
				iparent = OF_finddevice("/u3/mpic");
				device_printf(dev, "Set /u3/mpic as iparent!\n");
			}
			/* Add an interrupt number 0 to the parent. */
			irq = MAP_IRQ(iparent, 0);
			resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
					  dinfo->udi_ninterrupts, irq, irq, 1);
			dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq;
			dinfo->udi_ninterrupts++;
		}

		unin_chip_add_reg(child, dinfo);

		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
				      dinfo->udi_obdinfo.obd_name);
			resource_list_free(&dinfo->udi_resources);
			ofw_bus_gen_destroy_devinfo(&dinfo->udi_obdinfo);
			free(dinfo, M_UNIN);
			continue;
		}

		device_set_ivars(cdev, dinfo);
	}

	/*
	 * Only map the first page, since that is where the registers
	 * of interest lie.
	 */
	sc->sc_addr = (vm_offset_t)pmap_mapdev(sc->sc_physaddr, PAGE_SIZE);

	sc->sc_version = *(u_int *)sc->sc_addr;
	device_printf(dev, "Version %d\n", sc->sc_version);

	/*
	 * Enable the GMAC Ethernet cell and the integrated OpenPIC
	 * if Open Firmware says they are used.
	 */
	for (child = OF_child(root); child; child = OF_peer(child)) {
		memset(compat, 0, sizeof(compat));
		OF_getprop(child, "compatible", compat, sizeof(compat));
		if (strcmp(compat, "gmac") == 0)
			unin_enable_gmac(dev);
		if (strcmp(compat, "chrp,open-pic") == 0)
			unin_enable_mpic(dev);
	}
	
	/*
	 * GMAC lives under the PCI bus, so just check if enet is gmac.
	 */
	child = OF_finddevice("enet");
	memset(compat, 0, sizeof(compat));
	OF_getprop(child, "compatible", compat, sizeof(compat));
	if (strcmp(compat, "gmac") == 0)
		unin_enable_gmac(dev);

	return (bus_generic_attach(dev));
}
Beispiel #25
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);
}
/*
 * PCI attach: scan Open Firmware child nodes, and attach these as children
 * of the macio bus
 */
static int 
macio_attach(device_t dev)
{
	struct macio_softc *sc;
        struct macio_devinfo *dinfo;
        phandle_t  root;
	phandle_t  child;
	phandle_t  subchild;
        device_t cdev;
        u_int reg[3];
	int error, quirks;

	sc = device_get_softc(dev);
	root = sc->sc_node = ofw_bus_get_node(dev);
	
	/*
	 * Locate the device node and it's base address
	 */
	if (OF_getprop(root, "assigned-addresses", 
		       reg, sizeof(reg)) < sizeof(reg)) {
		return (ENXIO);
	}

	sc->sc_base = reg[2];
	sc->sc_size = MACIO_REG_SIZE;

	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
	sc->sc_mem_rman.rm_descr = "MacIO Device Memory";
	error = rman_init(&sc->sc_mem_rman);
	if (error) {
		device_printf(dev, "rman_init() failed. error = %d\n", error);
		return (error);
	}
	error = rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size);	
	if (error) {
		device_printf(dev,
		    "rman_manage_region() failed. error = %d\n", error);
		return (error);
	}

	/*
	 * Iterate through the sub-devices
	 */
	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_MACIO, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) !=
		    0) {
			free(dinfo, M_MACIO);
			continue;
		}
		quirks = macio_get_quirks(dinfo->mdi_obdinfo.obd_name);
		if ((quirks & MACIO_QUIRK_IGNORE) != 0) {
			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
			free(dinfo, M_MACIO);
			continue;
		}
		resource_list_init(&dinfo->mdi_resources);
		dinfo->mdi_ninterrupts = 0;
		macio_add_intr(child, dinfo);
		if ((quirks & MACIO_QUIRK_USE_CHILD_REG) != 0)
			macio_add_reg(OF_child(child), dinfo);
		else
			macio_add_reg(child, dinfo);
		if ((quirks & MACIO_QUIRK_CHILD_HAS_INTR) != 0)
			for (subchild = OF_child(child); subchild != 0;
			    subchild = OF_peer(subchild))
				macio_add_intr(subchild, dinfo);
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    dinfo->mdi_obdinfo.obd_name);
			resource_list_free(&dinfo->mdi_resources);
			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
			free(dinfo, M_MACIO);
			continue;
		}
		device_set_ivars(cdev, dinfo);
	}

	return (bus_generic_attach(dev));
}
Beispiel #27
0
static int
arm_gic_fdt_attach(device_t dev)
{
	struct arm_gic_fdt_softc *sc = device_get_softc(dev);
	phandle_t root, child;
	struct gic_devinfo *dinfo;
	device_t cdev;
	int err;

	err = arm_gic_attach(dev);
	if (err != 0)
		return (err);

	root = ofw_bus_get_node(dev);

	sc->sc_host_cells = 1;
	OF_getencprop(OF_parent(root), "#address-cells", &sc->sc_host_cells,
	    sizeof(sc->sc_host_cells));
	sc->sc_addr_cells = 2;
	OF_getencprop(root, "#address-cells", &sc->sc_addr_cells,
	    sizeof(sc->sc_addr_cells));
	sc->sc_size_cells = 2;
	OF_getencprop(root, "#size-cells", &sc->sc_size_cells,
	    sizeof(sc->sc_size_cells));

	/* If we have no children don't probe for them */
	child = OF_child(root);
	if (child == 0)
		return (0);

	if (gic_fill_ranges(root, sc) < 0) {
		device_printf(dev, "could not get ranges\n");
		return (ENXIO);
	}

	for (; child != 0; child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO);

		if (ofw_bus_gen_setup_devinfo(&dinfo->obdinfo, child) != 0) {
			free(dinfo, M_DEVBUF);
			continue;
		}

		resource_list_init(&dinfo->rl);
		ofw_bus_reg_to_rl(dev, child, sc->sc_addr_cells,
		    sc->sc_size_cells, &dinfo->rl);

		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    dinfo->obdinfo.obd_name);
			resource_list_free(&dinfo->rl);
			ofw_bus_gen_destroy_devinfo(&dinfo->obdinfo);
			free(dinfo, M_DEVBUF);
			continue;
		}
		device_set_ivars(cdev, dinfo);
	}

	bus_generic_probe(dev);
	return (bus_generic_attach(dev));
}
Beispiel #28
0
/*
 * Scan Open Firmware child nodes, and attach these as children
 * of the macgpio bus
 */
static int 
macgpio_attach(device_t dev)
{
	struct macgpio_softc *sc;
        struct macgpio_devinfo *dinfo;
        phandle_t root, child, iparent;
        device_t cdev;
	uint32_t irq[2];

	sc = device_get_softc(dev);
	root = sc->sc_node = ofw_bus_get_node(dev);
	
	sc->sc_gpios = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &sc->sc_gpios_rid, RF_ACTIVE);

	/*
	 * Iterate through the sub-devices
	 */
	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_MACGPIO, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) !=
		    0) {
			free(dinfo, M_MACGPIO);
			continue;
		}

		if (OF_getencprop(child, "reg", &dinfo->gpio_num,
		    sizeof(dinfo->gpio_num)) != sizeof(dinfo->gpio_num)) {
			/*
			 * Some early GPIO controllers don't provide GPIO
			 * numbers for GPIOs designed only to provide
			 * interrupt resources.  We should still allow these
			 * to attach, but with caution.
			 */

			dinfo->gpio_num = -1;
		}

		resource_list_init(&dinfo->mdi_resources);

		if (OF_getencprop(child, "interrupts", irq, sizeof(irq)) == 
		    sizeof(irq)) {
			OF_searchencprop(child, "interrupt-parent", &iparent,
			    sizeof(iparent));
			resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
			    0, MAP_IRQ(iparent, irq[0]),
			    MAP_IRQ(iparent, irq[0]), 1);
		}

		/* Fix messed-up offsets */
		if (dinfo->gpio_num > 0x50)
			dinfo->gpio_num -= 0x50;

		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    dinfo->mdi_obdinfo.obd_name);
			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
			free(dinfo, M_MACGPIO);
			continue;
		}
		device_set_ivars(cdev, dinfo);
	}

	return (bus_generic_attach(dev));
}
Beispiel #29
0
/*
 * PCI attach: scan Open Firmware child nodes, and attach these as children
 * of the macio bus
 */
static int 
macio_attach(device_t dev)
{
	struct macio_softc *sc;
        struct macio_devinfo *dinfo;
        phandle_t  root;
	phandle_t  child;
	phandle_t  subchild;
        device_t cdev;
        u_int reg[3];
	char compat[32];
	int error, quirks;

	sc = device_get_softc(dev);
	root = sc->sc_node = ofw_bus_get_node(dev);
	
	/*
	 * Locate the device node and it's base address
	 */
	if (OF_getprop(root, "assigned-addresses", 
		       reg, sizeof(reg)) < (ssize_t)sizeof(reg)) {
		return (ENXIO);
	}

	/* Used later to see if we have to enable the I2S part. */
	OF_getprop(root, "compatible", compat, sizeof(compat));

	sc->sc_base = reg[2];
	sc->sc_size = MACIO_REG_SIZE;

	sc->sc_memrid = PCIR_BAR(0);
	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &sc->sc_memrid, RF_ACTIVE);

	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
	sc->sc_mem_rman.rm_descr = "MacIO Device Memory";
	error = rman_init(&sc->sc_mem_rman);
	if (error) {
		device_printf(dev, "rman_init() failed. error = %d\n", error);
		return (error);
	}
	error = rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size);	
	if (error) {
		device_printf(dev,
		    "rman_manage_region() failed. error = %d\n", error);
		return (error);
	}

	/*
	 * Iterate through the sub-devices
	 */
	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_MACIO, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) !=
		    0) {
			free(dinfo, M_MACIO);
			continue;
		}
		quirks = macio_get_quirks(dinfo->mdi_obdinfo.obd_name);
		if ((quirks & MACIO_QUIRK_IGNORE) != 0) {
			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
			free(dinfo, M_MACIO);
			continue;
		}
		resource_list_init(&dinfo->mdi_resources);
		dinfo->mdi_ninterrupts = 0;
		macio_add_intr(child, dinfo);
		if ((quirks & MACIO_QUIRK_USE_CHILD_REG) != 0)
			macio_add_reg(OF_child(child), dinfo);
		else
			macio_add_reg(child, dinfo);
		if ((quirks & MACIO_QUIRK_CHILD_HAS_INTR) != 0)
			for (subchild = OF_child(child); subchild != 0;
			    subchild = OF_peer(subchild))
				macio_add_intr(subchild, dinfo);
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    dinfo->mdi_obdinfo.obd_name);
			resource_list_free(&dinfo->mdi_resources);
			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
			free(dinfo, M_MACIO);
			continue;
		}
		device_set_ivars(cdev, dinfo);

		/* Set FCRs to enable some devices */
		if (sc->sc_memr == NULL)
			continue;

		if (strcmp(ofw_bus_get_name(cdev), "bmac") == 0 ||
		    strcmp(ofw_bus_get_compat(cdev), "bmac+") == 0) {
			uint32_t fcr;

			fcr = bus_read_4(sc->sc_memr, HEATHROW_FCR);

			fcr |= FCR_ENET_ENABLE & ~FCR_ENET_RESET;
			bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
			DELAY(50000);
			fcr |= FCR_ENET_RESET;
			bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
			DELAY(50000);
			fcr &= ~FCR_ENET_RESET;
			bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
			DELAY(50000);
			
			bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
		}

		/*
		 * Make sure the I2S0 and the I2S0_CLK are enabled.
		 * On certain G5's they are not.
		 */
		if ((strcmp(ofw_bus_get_name(cdev), "i2s") == 0) &&
		    (strcmp(compat, "K2-Keylargo") == 0)) {

			uint32_t fcr1;

			fcr1 = bus_read_4(sc->sc_memr, KEYLARGO_FCR1);
			fcr1 |= FCR1_I2S0_CLK_ENABLE | FCR1_I2S0_ENABLE;
			bus_write_4(sc->sc_memr, KEYLARGO_FCR1, fcr1);
		}

	}

	return (bus_generic_attach(dev));
}