Example #1
0
static int
ofw_pcibus_attach(device_t dev)
{
	device_t pcib;
	struct ofw_pci_register pcir;
	struct ofw_pcibus_devinfo *dinfo;
	phandle_t node, child;
	uint32_t clock;
	u_int busno, domain, func, slot;

	pcib = device_get_parent(dev);
	domain = pcib_get_domain(dev);
	busno = pcib_get_bus(dev);
	if (bootverbose)
		device_printf(dev, "domain=%d, physical bus=%d\n",
		    domain, busno);
	node = ofw_bus_get_node(dev);

	/*
	 * Add the PCI side of the host-PCI bridge itself to the bus.
	 * Note that we exclude the host-PCIe bridges here as these
	 * have no configuration space implemented themselves.
	 */
	if (strcmp(device_get_name(device_get_parent(pcib)), "nexus") == 0 &&
	    ofw_bus_get_type(pcib) != NULL &&
	    strcmp(ofw_bus_get_type(pcib), OFW_TYPE_PCIE) != 0 &&
	    (dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
	    domain, busno, 0, 0, sizeof(*dinfo))) != NULL) {
		if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0)
			pci_freecfg((struct pci_devinfo *)dinfo);
		else
			pci_add_child(dev, (struct pci_devinfo *)dinfo);
	}

	if (OF_getprop(ofw_bus_get_node(pcib), "clock-frequency", &clock,
	    sizeof(clock)) == -1)
		clock = 33000000;
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1)
			continue;
		slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
		func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
		/* Some OFW device trees contain dupes. */
		if (pci_find_dbsf(domain, busno, slot, func) != NULL)
			continue;
		ofw_pcibus_setup_device(pcib, clock, busno, slot, func);
		dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
		    domain, busno, slot, func, sizeof(*dinfo));
		if (dinfo == NULL)
			continue;
		if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) !=
		    0) {
			pci_freecfg((struct pci_devinfo *)dinfo);
			continue;
		}
		pci_add_child(dev, (struct pci_devinfo *)dinfo);
	}

	return (bus_generic_attach(dev));
}
Example #2
0
static int
xlp_pci_attach(device_t dev)
{
    struct pci_devinfo *dinfo;
    device_t pcib;
    int maxslots, s, f, pcifunchigh, irq;
    int busno, node, devoffset;
    uint16_t devid;
    uint8_t hdrtype;

    /*
     * The on-chip devices are on a bus that is almost, but not
     * quite, completely like PCI. Add those things by hand.
     */
    pcib = device_get_parent(dev);
    busno = pcib_get_bus(dev);
    maxslots = PCIB_MAXSLOTS(pcib);
    for (s = 0; s <= maxslots; s++) {
        pcifunchigh = 0;
        f = 0;
        hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1);
        if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
            continue;
        if (hdrtype & PCIM_MFDEV)
            pcifunchigh = PCI_FUNCMAX;
        node = s / 8;
        for (f = 0; f <= pcifunchigh; f++) {
            devoffset = XLP_HDR_OFFSET(node, 0, s % 8, f);
            if (!nlm_dev_exists(devoffset))
                continue;

            /* Find if there is a desc for the SoC device */
            devid = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_DEVICE, 2);

            /* Skip devices that don't have a proper PCI header */
            switch (devid) {
            case PCI_DEVICE_ID_NLM_ICI:
            case PCI_DEVICE_ID_NLM_PIC:
            case PCI_DEVICE_ID_NLM_FMN:
            case PCI_DEVICE_ID_NLM_UART:
            case PCI_DEVICE_ID_NLM_I2C:
            case PCI_DEVICE_ID_NLM_NOR:
            case PCI_DEVICE_ID_NLM_MMC:
                continue;
            case PCI_DEVICE_ID_NLM_EHCI:
                irq = PIC_USB_IRQ(f);
                PCIB_WRITE_CONFIG(pcib, busno, s, f,
                                  XLP_PCI_DEVSCRATCH_REG0 << 2,
                                  (1 << 8) | irq, 4);
            }
            dinfo = pci_read_device(pcib, dev, pcib_get_domain(dev),
                                    busno, s, f);
            pci_add_child(dev, dinfo);
        }
    }
    return (bus_generic_attach(dev));
}
Example #3
0
static int
cardbus_attach_card(device_t cbdev)
{
	device_t brdev = device_get_parent(cbdev);
	device_t child;
	int bus, domain, slot, func;
	int cardattached = 0;
	int cardbusfunchigh = 0;
	struct cardbus_softc *sc;

	sc = device_get_softc(cbdev);
	cardbus_detach_card(cbdev); /* detach existing cards */
	POWER_ENABLE_SOCKET(brdev, cbdev);
	domain = pcib_get_domain(cbdev);
	bus = pcib_get_bus(cbdev);
	slot = 0;
	/* For each function, set it up and try to attach a driver to it */
	for (func = 0; func <= cardbusfunchigh; func++) {
		struct cardbus_devinfo *dinfo;

		dinfo = (struct cardbus_devinfo *)
		    pci_read_device(brdev, domain, bus, slot, func,
			sizeof(struct cardbus_devinfo));
		if (dinfo == NULL)
			continue;
		if (dinfo->pci.cfg.mfdev)
			cardbusfunchigh = PCI_FUNCMAX;

		child = device_add_child(cbdev, NULL, -1);
		if (child == NULL) {
			DEVPRINTF((cbdev, "Cannot add child!\n"));
			pci_freecfg((struct pci_devinfo *)dinfo);
			continue;
		}
		dinfo->pci.cfg.dev = child;
		resource_list_init(&dinfo->pci.resources);
		device_set_ivars(child, dinfo);
		cardbus_device_create(sc, dinfo, cbdev, child);
		if (cardbus_do_cis(cbdev, child) != 0)
			DEVPRINTF((cbdev, "Warning: Bogus CIS ignored\n"));
		pci_cfg_save(dinfo->pci.cfg.dev, &dinfo->pci, 0);
		pci_cfg_restore(dinfo->pci.cfg.dev, &dinfo->pci);
		cardbus_device_setup_regs(&dinfo->pci.cfg);
		pci_add_resources(cbdev, child, 1, dinfo->mprefetchable);
		pci_print_verbose(&dinfo->pci);
		if (device_probe_and_attach(child) == 0)
			cardattached++;
		else
			pci_cfg_save(dinfo->pci.cfg.dev, &dinfo->pci, 1);
	}
	if (cardattached > 0)
		return (0);
/*	POWER_DISABLE_SOCKET(brdev, cbdev); */
	return (ENOENT);
}
Example #4
0
static void
ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno)
{
	device_t pcib;
	struct ofw_pcibus_devinfo *dinfo;
	int maxslots;
	int s, f, pcifunchigh;
	uint8_t hdrtype;

	pcib = device_get_parent(dev);

	maxslots = PCIB_MAXSLOTS(pcib);
	for (s = 0; s <= maxslots; s++) {
		pcifunchigh = 0;
		f = 0;
		DELAY(1);
		hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1);
		if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
			continue;
		if (hdrtype & PCIM_MFDEV)
			pcifunchigh = PCI_FUNCMAX;
		for (f = 0; f <= pcifunchigh; f++) {
			/* Filter devices we have already added */
			if (pci_find_dbsf(domain, busno, s, f) != NULL)
				continue;

			dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(
			    pcib, domain, busno, s, f, sizeof(*dinfo));
			if (dinfo == NULL)
				continue;

			dinfo->opd_dma_tag = NULL;
			dinfo->opd_obdinfo.obd_node = -1;

			dinfo->opd_obdinfo.obd_name = NULL;
			dinfo->opd_obdinfo.obd_compat = NULL;
			dinfo->opd_obdinfo.obd_type = NULL;
			dinfo->opd_obdinfo.obd_model = NULL;

			/*
			 * For non OFW-devices, don't believe 0 
			 * for an interrupt.
			 */
			if (dinfo->opd_dinfo.cfg.intline == 0) {
				dinfo->opd_dinfo.cfg.intline = PCI_INVALID_IRQ;
				PCIB_WRITE_CONFIG(pcib, busno, s, f, 
				    PCIR_INTLINE, PCI_INVALID_IRQ, 1);
			}

			pci_add_child(dev, (struct pci_devinfo *)dinfo);
		}
	}
}
Example #5
0
static void
ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno)
{
	device_t pcib;
	struct ofw_pci_register pcir;
	struct ofw_pcibus_devinfo *dinfo;
	phandle_t node, child;
	u_int func, slot;
	int intline;

	pcib = device_get_parent(dev);
	node = ofw_bus_get_node(dev);

	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1)
			continue;
		slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
		func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);

		/* Some OFW device trees contain dupes. */
		if (pci_find_dbsf(domain, busno, slot, func) != NULL)
			continue;

		/*
		 * The preset in the intline register is usually bogus.  Reset
		 * it such that the PCI code will reroute the interrupt if
		 * needed.
		 */

		intline = PCI_INVALID_IRQ;
		if (OF_getproplen(child, "interrupts") > 0)
			intline = 0;
		PCIB_WRITE_CONFIG(pcib, busno, slot, func, PCIR_INTLINE,
		    intline, 1);

		/*
		 * Now set up the PCI and OFW bus layer devinfo and add it
		 * to the PCI bus.
		 */

		dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
		    domain, busno, slot, func, sizeof(*dinfo));
		if (dinfo == NULL)
			continue;
		if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) !=
		    0) {
			pci_freecfg((struct pci_devinfo *)dinfo);
			continue;
		}
		dinfo->opd_dma_tag = NULL;
		pci_add_child(dev, (struct pci_devinfo *)dinfo);

		/*
		 * Some devices don't have an intpin set, but do have
		 * interrupts. These are fully specified, and set in the
		 * interrupts property, so add that value to the device's
		 * resource list.
		 */
		if (dinfo->opd_dinfo.cfg.intpin == 0)
			ofw_bus_intr_to_rl(dev, child,
				&dinfo->opd_dinfo.resources, NULL);
	}
}
Example #6
0
static void
xlp_add_soc_child(device_t pcib, device_t dev, int b, int s, int f)
{
	struct pci_devinfo *dinfo;
	struct xlp_devinfo *xlp_dinfo;
	struct soc_dev_desc *si;
	uint64_t pcibase;
	int domain, node, irt, irq, flags, devoffset, num;
	uint16_t devid;

	domain = pcib_get_domain(dev);
	node = s / 8;
	devoffset = XLP_HDR_OFFSET(node, 0, s % 8, f);
	if (!nlm_dev_exists(devoffset))
		return;

	/* Find if there is a desc for the SoC device */
	devid = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVICE, 2);
	si = xlp_find_soc_desc(devid);

	/* update flags and irq from desc if available */
	irq = 0;
	flags = 0;
	if (si != NULL) {
		if (si->irqbase != 0)
			irq = si->irqbase + si->ndevs;
		flags = si->flags;
		si->ndevs++;
	}

	/* skip internal devices */
	if ((flags & INTERNAL_DEV) != 0)
		return;

	/* PCIe interfaces are special, bug in Ax */
	if (devid == PCI_DEVICE_ID_NLM_PCIE) {
		xlp_add_irq(node, xlp_pcie_link_irt(f), PIC_PCIE_0_IRQ + f);
	} else {
		/* Stash intline and pin in shadow reg for devices */
		pcibase = nlm_pcicfg_base(devoffset);
		irt = nlm_irtstart(pcibase);
		num = nlm_irtnum(pcibase);
		if (irq != 0 && num > 0) {
			xlp_add_irq(node, irt, irq);
			nlm_write_reg(pcibase, XLP_PCI_DEVSCRATCH_REG0,
			    (1 << 8) | irq);
		}
	}
	dinfo = pci_read_device(pcib, domain, b, s, f, sizeof(*xlp_dinfo));
	if (dinfo == NULL)
		return;
	xlp_dinfo = (struct xlp_devinfo *)dinfo;
	xlp_dinfo->irq = irq;
	xlp_dinfo->flags = flags;

	/* memory resource from ecfg space, if MEM_RES_EMUL is set */
	if ((flags & MEM_RES_EMUL) != 0)
		xlp_dinfo->mem_res_start = XLP_DEFAULT_IO_BASE + devoffset +
		    XLP_IO_PCI_HDRSZ;
	pci_add_child(dev, dinfo);
}