Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 97b3cf05 authored by David S. Miller's avatar David S. Miller
Browse files

[SPARC64]: Add dummy host controller to root of all PCI domains.



We fake up a dummy one in all cases because that is the simplest
thing to do and it happens to be necessary for hypervisor systems.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c6e87566
Loading
Loading
Loading
Loading
+89 −30
Original line number Diff line number Diff line
@@ -368,7 +368,8 @@ static void pci_parse_of_addrs(struct of_device *op,

struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
				  struct device_node *node,
				  struct pci_bus *bus, int devfn)
				  struct pci_bus *bus, int devfn,
				  int host_controller)
{
	struct dev_archdata *sd;
	struct pci_dev *dev;
@@ -400,6 +401,13 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
	dev->devfn = devfn;
	dev->multifunction = 0;		/* maybe a lie? */

	if (host_controller) {
		dev->vendor = 0x108e;
		dev->device = 0x8000;
		dev->subsystem_vendor = 0x0000;
		dev->subsystem_device = 0x0000;
		dev->cfg_size = 256;
	} else {
		dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff);
		dev->device = of_getintprop_default(node, "device-id", 0xffff);
		dev->subsystem_vendor =
@@ -408,24 +416,32 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
			of_getintprop_default(node, "subsystem-id", 0);

		dev->cfg_size = pci_cfg_space_size(dev);

	}
	sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
		dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));

	/* dev->class = of_getintprop_default(node, "class-code", 0); */
	/* We can't actually use the firmware value, we have to read what
	 * is in the register right now.  One reason is that in the case
	 * of IDE interfaces the firmware can sample the value before the
	 * the IDE interface is programmed into native mode.
	if (host_controller) {
		dev->class = PCI_CLASS_BRIDGE_HOST << 8;
	} else {
		/* We can't actually use the firmware value, we have
		 * to read what is in the register right now.  One
		 * reason is that in the case of IDE interfaces the
		 * firmware can sample the value before the the IDE
		 * interface is programmed into native mode.
		 */
		pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
		dev->class = class >> 8;

	}
	printk("    class: 0x%x\n", dev->class);

	dev->current_state = 4;		/* unknown power state */
	dev->error_state = pci_channel_io_normal;

	if (host_controller) {
		dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
		dev->rom_base_reg = PCI_ROM_ADDRESS1;
		dev->irq = PCI_IRQ_NONE;
	} else {
		if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
			/* a PCI-PCI bridge */
			dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
@@ -440,7 +456,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
			if (dev->irq == 0xffffffff)
				dev->irq = PCI_IRQ_NONE;
		}

	}
	pci_parse_of_addrs(sd->op, node, dev);

	printk("    adding to system ...\n");
@@ -632,7 +648,7 @@ static void __init pci_of_scan_bus(struct pci_pbm_info *pbm,
		devfn = (reg[0] >> 8) & 0xff;

		/* create a new pci_dev for this device */
		dev = of_create_pci_dev(pbm, child, bus, devfn);
		dev = of_create_pci_dev(pbm, child, bus, devfn, 0);
		if (!dev)
			continue;
		printk("PCI: dev header type: %x\n", dev->hdr_type);
@@ -677,10 +693,49 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus)
		pci_bus_register_of_sysfs(child_bus);
}

int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
				 unsigned int devfn,
				 int where, int size,
				 u32 *value)
{
	static u8 fake_pci_config[] = {
		0x8e, 0x10, /* Vendor: 0x108e (Sun) */
		0x00, 0x80, /* Device: 0x8000 (PBM) */
		0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */
		0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */
		0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */
		0x00, /* Cacheline: 0x00 */
		0x40, /* Latency: 0x40 */
		0x00, /* Header-Type: 0x00 normal */
	};

	*value = 0;
	if (where >= 0 && where < sizeof(fake_pci_config) &&
	    (where + size) >= 0 &&
	    (where + size) < sizeof(fake_pci_config) &&
	    size <= sizeof(u32)) {
		while (size--) {
			*value <<= 8;
			*value |= fake_pci_config[where + size];
		}
	}

	return PCIBIOS_SUCCESSFUL;
}

int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
				  unsigned int devfn,
				  int where, int size,
				  u32 value)
{
	return PCIBIOS_SUCCESSFUL;
}

struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm)
{
	struct pci_controller_info *p = pbm->parent;
	struct device_node *node = pbm->prom_node;
	struct pci_dev *host_pdev;
	struct pci_bus *bus;

	printk("PCI: Scanning PBM %s\n", node->full_name);
@@ -698,6 +753,10 @@ struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm)
	bus->resource[0] = &pbm->io_space;
	bus->resource[1] = &pbm->mem_space;

	/* Create the dummy host bridge and link it in.  */
	host_pdev = of_create_pci_dev(pbm, node, bus, 0x00, 1);
	bus->self = host_pdev;

	pci_of_scan_bus(pbm, node, bus);
	pci_bus_add_devices(bus);
	pci_bus_register_of_sysfs(bus);
+9 −0
Original line number Diff line number Diff line
@@ -20,6 +20,15 @@ extern int pci_num_controllers;
extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm);

extern int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
					unsigned int devfn,
					int where, int size,
					u32 *value);
extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
					 unsigned int devfn,
					 int where, int size,
					 u32 value);

/* Error reporting support. */
extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
+7 −0
Original line number Diff line number Diff line
@@ -118,6 +118,10 @@ static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
	u16 tmp16;
	u8 tmp8;

	if (bus_dev == pbm->pci_bus && devfn == 0x00)
		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
						    size, value);

	switch (size) {
	case 1:
		*value = 0xff;
@@ -171,6 +175,9 @@ static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
	unsigned char bus = bus_dev->number;
	u32 *addr;

	if (bus_dev == pbm->pci_bus && devfn == 0x00)
		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
						     size, value);
	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
	if (!addr)
		return PCIBIOS_SUCCESSFUL;
+12 −0
Original line number Diff line number Diff line
@@ -319,6 +319,12 @@ static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn,
			      int where, int size, u32 *value)
{
	struct pci_pbm_info *pbm = bus->sysdata;

	if (bus == pbm->pci_bus && devfn == 0x00)
		return pci_host_bridge_read_pci_cfg(bus, devfn, where,
						    size, value);

	if (!bus->number && sabre_out_of_range(devfn)) {
		switch (size) {
		case 1:
@@ -435,6 +441,12 @@ static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn,
			       int where, int size, u32 value)
{
	struct pci_pbm_info *pbm = bus->sysdata;

	if (bus == pbm->pci_bus && devfn == 0x00)
		return pci_host_bridge_write_pci_cfg(bus, devfn, where,
						     size, value);

	if (bus->number)
		return __sabre_write_pci_cfg(bus, devfn, where, size, value);

+6 −0
Original line number Diff line number Diff line
@@ -125,6 +125,9 @@ static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
	u16 tmp16;
	u8 tmp8;

	if (bus_dev == pbm->pci_bus && devfn == 0x00)
		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
						    size, value);
	switch (size) {
	case 1:
		*value = 0xff;
@@ -178,6 +181,9 @@ static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
	unsigned char bus = bus_dev->number;
	u32 *addr;

	if (bus_dev == pbm->pci_bus && devfn == 0x00)
		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
						     size, value);
	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
	if (!addr)
		return PCIBIOS_SUCCESSFUL;
Loading