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

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

[SPARC64]: Use in-kernel OBP device tree for PCI controller probing.



It can be pushed even further down, but this is a first step.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent aaf7cec2
Loading
Loading
Loading
Loading
+25 −28
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@
#include <asm/irq.h>
#include <asm/irq.h>
#include <asm/ebus.h>
#include <asm/ebus.h>
#include <asm/isa.h>
#include <asm/isa.h>
#include <asm/prom.h>


unsigned long pci_memspace_mask = 0xffffffffUL;
unsigned long pci_memspace_mask = 0xffffffffUL;


@@ -177,16 +178,16 @@ void pci_config_write32(u32 *addr, u32 val)
}
}


/* Probe for all PCI controllers in the system. */
/* Probe for all PCI controllers in the system. */
extern void sabre_init(int, char *);
extern void sabre_init(struct device_node *, const char *);
extern void psycho_init(int, char *);
extern void psycho_init(struct device_node *, const char *);
extern void schizo_init(int, char *);
extern void schizo_init(struct device_node *, const char *);
extern void schizo_plus_init(int, char *);
extern void schizo_plus_init(struct device_node *, const char *);
extern void tomatillo_init(int, char *);
extern void tomatillo_init(struct device_node *, const char *);
extern void sun4v_pci_init(int, char *);
extern void sun4v_pci_init(struct device_node *, const char *);


static struct {
static struct {
	char *model_name;
	char *model_name;
	void (*init)(int, char *);
	void (*init)(struct device_node *, const char *);
} pci_controller_table[] __initdata = {
} pci_controller_table[] __initdata = {
	{ "SUNW,sabre", sabre_init },
	{ "SUNW,sabre", sabre_init },
	{ "pci108e,a000", sabre_init },
	{ "pci108e,a000", sabre_init },
@@ -204,7 +205,7 @@ static struct {
#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
				  sizeof(pci_controller_table[0]))
				  sizeof(pci_controller_table[0]))


static int __init pci_controller_init(char *model_name, int namelen, int node)
static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp)
{
{
	int i;
	int i;


@@ -212,18 +213,15 @@ static int __init pci_controller_init(char *model_name, int namelen, int node)
		if (!strncmp(model_name,
		if (!strncmp(model_name,
			     pci_controller_table[i].model_name,
			     pci_controller_table[i].model_name,
			     namelen)) {
			     namelen)) {
			pci_controller_table[i].init(node, model_name);
			pci_controller_table[i].init(dp, model_name);
			return 1;
			return 1;
		}
		}
	}
	}
	printk("PCI: Warning unknown controller, model name [%s]\n",
	       model_name);
	printk("PCI: Ignoring controller...\n");


	return 0;
	return 0;
}
}


static int __init pci_is_controller(char *model_name, int namelen, int node)
static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp)
{
{
	int i;
	int i;


@@ -237,36 +235,35 @@ static int __init pci_is_controller(char *model_name, int namelen, int node)
	return 0;
	return 0;
}
}


static int __init pci_controller_scan(int (*handler)(char *, int, int))
static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *))
{
{
	char namebuf[64];
	struct device_node *dp;
	int node;
	int count = 0;
	int count = 0;


	node = prom_getchild(prom_root_node);
	for_each_node_by_name(dp, "pci") {
	while ((node = prom_searchsiblings(node, "pci")) != 0) {
		struct property *prop;
		int len;
		int len;


		if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 ||
		prop = of_find_property(dp, "model", &len);
		    (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) {
		if (!prop)
			prop = of_find_property(dp, "compatible", &len);

		if (prop) {
			const char *model = prop->value;
			int item_len = 0;
			int item_len = 0;


			/* Our value may be a multi-valued string in the
			/* Our value may be a multi-valued string in the
			 * case of some compatible properties. For sanity,
			 * case of some compatible properties. For sanity,
			 * only try the first one. */
			 * only try the first one.

			 */
			while (namebuf[item_len] && len) {
			while (model[item_len] && len) {
				len--;
				len--;
				item_len++;
				item_len++;
			}
			}


			if (handler(namebuf, item_len, node))
			if (handler(model, item_len, dp))
				count++;
				count++;
		}
		}

		node = prom_getsibling(node);
		if (!node)
			break;
	}
	}


	return count;
	return count;
+8 −7
Original line number Original line Diff line number Diff line
@@ -664,7 +664,7 @@ static unsigned int __init pci_intmap_match_to_root(struct pci_pbm_info *pbm,
		}
		}
		pdev = pbus;
		pdev = pbus;


		if (cnode == pbm->prom_node)
		if (cnode == pbm->prom_node->node)
			break;
			break;
	}
	}


@@ -680,7 +680,7 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt
	int i, cnode, plen;
	int i, cnode, plen;


	cnode = pci_intmap_match_to_root(pbm, pdev, interrupt);
	cnode = pci_intmap_match_to_root(pbm, pdev, interrupt);
	if (cnode == pbm->prom_node)
	if (cnode == pbm->prom_node->node)
		goto success;
		goto success;


	plen = prom_getproperty(cnode, "reg", (char *) reg, sizeof(reg));
	plen = prom_getproperty(cnode, "reg", (char *) reg, sizeof(reg));
@@ -691,10 +691,10 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt
		goto fail;
		goto fail;
	}
	}


	hi   = reg[0].phys_hi & pbm->pbm_intmask.phys_hi;
	hi   = reg[0].phys_hi & pbm->pbm_intmask->phys_hi;
	mid  = reg[0].phys_mid & pbm->pbm_intmask.phys_mid;
	mid  = reg[0].phys_mid & pbm->pbm_intmask->phys_mid;
	lo   = reg[0].phys_lo & pbm->pbm_intmask.phys_lo;
	lo   = reg[0].phys_lo & pbm->pbm_intmask->phys_lo;
	irq  = *interrupt & pbm->pbm_intmask.interrupt;
	irq  = *interrupt & pbm->pbm_intmask->interrupt;


	for (i = 0; i < pbm->num_pbm_intmap; i++) {
	for (i = 0; i < pbm->num_pbm_intmap; i++) {
		struct linux_prom_pci_intmap *intmap;
		struct linux_prom_pci_intmap *intmap;
@@ -714,7 +714,8 @@ fail:
	return 0;
	return 0;


success:
success:
	printk("PCI-IRQ: Routing bus[%2x] slot[%2x] to INO[%02x]\n",
	printk("%s: Routing bus[%2x] slot[%2x] to INO[%02x]\n",
	       pbm->name,
	       pdev->bus->number, PCI_SLOT(pdev->devfn),
	       pdev->bus->number, PCI_SLOT(pdev->devfn),
	       *interrupt);
	       *interrupt);
	return 1;
	return 1;
+50 −58
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#include <asm/iommu.h>
#include <asm/iommu.h>
#include <asm/irq.h>
#include <asm/irq.h>
#include <asm/starfire.h>
#include <asm/starfire.h>
#include <asm/prom.h>


#include "pci_impl.h"
#include "pci_impl.h"
#include "iommu_common.h"
#include "iommu_common.h"
@@ -1103,7 +1104,7 @@ static void pbm_scan_bus(struct pci_controller_info *p,
	pci_fixup_host_bridge_self(pbm->pci_bus);
	pci_fixup_host_bridge_self(pbm->pci_bus);
	pbm->pci_bus->self->sysdata = cookie;
	pbm->pci_bus->self->sysdata = cookie;


	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node->node);
	pci_record_assignments(pbm, pbm->pci_bus);
	pci_record_assignments(pbm, pbm->pci_bus);
	pci_assign_unassigned(pbm, pbm->pci_bus);
	pci_assign_unassigned(pbm, pbm->pci_bus);
	pci_fixup_irq(pbm, pbm->pci_bus);
	pci_fixup_irq(pbm, pbm->pci_bus);
@@ -1291,11 +1292,12 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
#define PSYCHO_MEMSPACE_SIZE	0x07fffffffUL
#define PSYCHO_MEMSPACE_SIZE	0x07fffffffUL


static void psycho_pbm_init(struct pci_controller_info *p,
static void psycho_pbm_init(struct pci_controller_info *p,
			    int prom_node, int is_pbm_a)
			    struct device_node *dp, int is_pbm_a)
{
{
	unsigned int busrange[2];
	unsigned int *busrange;
	struct property *prop;
	struct pci_pbm_info *pbm;
	struct pci_pbm_info *pbm;
	int err;
	int len;


	if (is_pbm_a) {
	if (is_pbm_a) {
		pbm = &p->pbm_A;
		pbm = &p->pbm_A;
@@ -1310,10 +1312,14 @@ static void psycho_pbm_init(struct pci_controller_info *p,
	}
	}


	pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
	pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
	pbm->chip_version =
	pbm->chip_version = 0;
		prom_getintdefault(prom_node, "version#", 0);
	prop = of_find_property(dp, "version#", NULL);
	pbm->chip_revision =
	if (prop)
		prom_getintdefault(prom_node, "module-revision#", 0);
		pbm->chip_version = *(int *) prop->value;
	pbm->chip_revision = 0;
	prop = of_find_property(dp, "module-revision#", NULL);
	if (prop)
		pbm->chip_revision = *(int *) prop->value;


	pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
	pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
	pbm->io_space.flags = IORESOURCE_IO;
	pbm->io_space.flags = IORESOURCE_IO;
@@ -1322,45 +1328,36 @@ static void psycho_pbm_init(struct pci_controller_info *p,
	pbm_register_toplevel_resources(p, pbm);
	pbm_register_toplevel_resources(p, pbm);


	pbm->parent = p;
	pbm->parent = p;
	pbm->prom_node = prom_node;
	pbm->prom_node = dp;
	prom_getstring(prom_node, "name",
	pbm->name = dp->full_name;
		       pbm->prom_name,

		       sizeof(pbm->prom_name));
	printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n",

	       pbm->name,
	err = prom_getproperty(prom_node, "ranges",
	       pbm->chip_version, pbm->chip_revision);
			       (char *)pbm->pbm_ranges,

			       sizeof(pbm->pbm_ranges));
	prop = of_find_property(dp, "ranges", &len);
	if (err != -1)
	if (prop) {
		pbm->pbm_ranges = prop->value;
		pbm->num_pbm_ranges =
		pbm->num_pbm_ranges =
			(err / sizeof(struct linux_prom_pci_ranges));
			(len / sizeof(struct linux_prom_pci_ranges));
	else
	} else {
		pbm->num_pbm_ranges = 0;
		pbm->num_pbm_ranges = 0;

	err = prom_getproperty(prom_node, "interrupt-map",
			       (char *)pbm->pbm_intmap,
			       sizeof(pbm->pbm_intmap));
	if (err != -1) {
		pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
		err = prom_getproperty(prom_node, "interrupt-map-mask",
				       (char *)&pbm->pbm_intmask,
				       sizeof(pbm->pbm_intmask));
		if (err == -1) {
			prom_printf("PSYCHO-PBM: Fatal error, no "
				    "interrupt-map-mask.\n");
			prom_halt();
	}
	}

	prop = of_find_property(dp, "interrupt-map", &len);
	if (prop) {
		pbm->pbm_intmap = prop->value;
		pbm->num_pbm_intmap =
			(len / sizeof(struct linux_prom_pci_intmap));

		prop = of_find_property(dp, "interrupt-map-mask", NULL);
		pbm->pbm_intmask = prop->value;
	} else {
	} else {
		pbm->num_pbm_intmap = 0;
		pbm->num_pbm_intmap = 0;
		memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
	}
	}


	err = prom_getproperty(prom_node, "bus-range",
	prop = of_find_property(dp, "bus-range", NULL);
			       (char *)&busrange[0],
	busrange = prop->value;
			       sizeof(busrange));
	if (err == 0 || err == -1) {
		prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n");
		prom_halt();
	}
	pbm->pci_first_busno = busrange[0];
	pbm->pci_first_busno = busrange[0];
	pbm->pci_last_busno = busrange[1];
	pbm->pci_last_busno = busrange[1];


@@ -1369,20 +1366,24 @@ static void psycho_pbm_init(struct pci_controller_info *p,


#define PSYCHO_CONFIGSPACE	0x001000000UL
#define PSYCHO_CONFIGSPACE	0x001000000UL


void psycho_init(int node, char *model_name)
void psycho_init(struct device_node *dp, char *model_name)
{
{
	struct linux_prom64_registers pr_regs[3];
	struct linux_prom64_registers *pr_regs;
	struct pci_controller_info *p;
	struct pci_controller_info *p;
	struct pci_iommu *iommu;
	struct pci_iommu *iommu;
	struct property *prop;
	u32 upa_portid;
	u32 upa_portid;
	int is_pbm_a, err;
	int is_pbm_a;


	upa_portid = prom_getintdefault(node, "upa-portid", 0xff);
	upa_portid = 0xff;
	prop = of_find_property(dp, "upa-portid", NULL);
	if (prop)
		upa_portid = *(u32 *) prop->value;


	for(p = pci_controller_root; p; p = p->next) {
	for(p = pci_controller_root; p; p = p->next) {
		if (p->pbm_A.portid == upa_portid) {
		if (p->pbm_A.portid == upa_portid) {
			is_pbm_a = (p->pbm_A.prom_node == 0);
			is_pbm_a = (p->pbm_A.prom_node == NULL);
			psycho_pbm_init(p, node, is_pbm_a);
			psycho_pbm_init(p, dp, is_pbm_a);
			return;
			return;
		}
		}
	}
	}
@@ -1412,23 +1413,14 @@ void psycho_init(int node, char *model_name)
	p->resource_adjust = psycho_resource_adjust;
	p->resource_adjust = psycho_resource_adjust;
	p->pci_ops = &psycho_ops;
	p->pci_ops = &psycho_ops;


	err = prom_getproperty(node, "reg",
	prop = of_find_property(dp, "reg", NULL);
			       (char *)&pr_regs[0],
	pr_regs = prop->value;
			       sizeof(pr_regs));
	if (err == 0 || err == -1) {
		prom_printf("PSYCHO: Fatal error, no reg property.\n");
		prom_halt();
	}


	p->pbm_A.controller_regs = pr_regs[2].phys_addr;
	p->pbm_A.controller_regs = pr_regs[2].phys_addr;
	p->pbm_B.controller_regs = pr_regs[2].phys_addr;
	p->pbm_B.controller_regs = pr_regs[2].phys_addr;
	printk("PCI: Found PSYCHO, control regs at %016lx\n",
	       p->pbm_A.controller_regs);


	p->pbm_A.config_space = p->pbm_B.config_space =
	p->pbm_A.config_space = p->pbm_B.config_space =
		(pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
		(pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
	printk("PSYCHO: Shared PCI config space at %016lx\n",
	       p->pbm_A.config_space);


	/*
	/*
	 * Psycho's PCI MEM space is mapped to a 2GB aligned area, so
	 * Psycho's PCI MEM space is mapped to a 2GB aligned area, so
@@ -1441,5 +1433,5 @@ void psycho_init(int node, char *model_name)
	psycho_iommu_init(p);
	psycho_iommu_init(p);


	is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
	is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
	psycho_pbm_init(p, node, is_pbm_a);
	psycho_pbm_init(p, dp, is_pbm_a);
}
}
+82 −110
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <asm/irq.h>
#include <asm/irq.h>
#include <asm/smp.h>
#include <asm/smp.h>
#include <asm/oplib.h>
#include <asm/oplib.h>
#include <asm/prom.h>


#include "pci_impl.h"
#include "pci_impl.h"
#include "iommu_common.h"
#include "iommu_common.h"
@@ -1160,7 +1161,7 @@ static void sabre_scan_bus(struct pci_controller_info *p)


		pbus->sysdata = pbm;
		pbus->sysdata = pbm;
		pbm->pci_bus = pbus;
		pbm->pci_bus = pbus;
		pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node);
		pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node->node);
		pci_record_assignments(pbm, pbus);
		pci_record_assignments(pbm, pbus);
		pci_assign_unassigned(pbm, pbus);
		pci_assign_unassigned(pbm, pbus);
		pci_fixup_irq(pbm, pbus);
		pci_fixup_irq(pbm, pbus);
@@ -1173,7 +1174,7 @@ static void sabre_scan_bus(struct pci_controller_info *p)
		pbm = &p->pbm_A;
		pbm = &p->pbm_A;
		sabre_bus->sysdata = pbm;
		sabre_bus->sysdata = pbm;
		pbm->pci_bus = sabre_bus;
		pbm->pci_bus = sabre_bus;
		pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node);
		pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node->node);
		pci_record_assignments(pbm, sabre_bus);
		pci_record_assignments(pbm, sabre_bus);
		pci_assign_unassigned(pbm, sabre_bus);
		pci_assign_unassigned(pbm, sabre_bus);
		pci_fixup_irq(pbm, sabre_bus);
		pci_fixup_irq(pbm, sabre_bus);
@@ -1306,34 +1307,36 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p,
					    &pbm->mem_space);
					    &pbm->mem_space);
}
}


static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin)
static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin)
{
{
	struct pci_pbm_info *pbm;
	struct pci_pbm_info *pbm;
	char namebuf[128];
	struct device_node *node;
	u32 busrange[2];
	struct property *prop;
	int node, simbas_found;
	u32 *busrange;
	int len, simbas_found;


	simbas_found = 0;
	simbas_found = 0;
	node = prom_getchild(sabre_node);
	node = dp->child;
	while ((node = prom_searchsiblings(node, "pci")) != 0) {
	while (node != NULL) {
		int err;
		if (strcmp(node->name, "pci"))

		err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
		if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))
			goto next_pci;
			goto next_pci;


		err = prom_getproperty(node, "bus-range",
		prop = of_find_property(node, "model", NULL);
				       (char *)&busrange[0], sizeof(busrange));
		if (!prop || strncmp(prop->value, "SUNW,simba", prop->length))
		if (err == 0 || err == -1) {
			goto next_pci;
			prom_printf("APB: Error, cannot get PCI bus-range.\n");
			prom_halt();
		}


		simbas_found++;
		simbas_found++;

		prop = of_find_property(node, "bus-range", NULL);
		busrange = prop->value;
		if (busrange[0] == 1)
		if (busrange[0] == 1)
			pbm = &p->pbm_B;
			pbm = &p->pbm_B;
		else
		else
			pbm = &p->pbm_A;
			pbm = &p->pbm_A;

		pbm->name = node->full_name;
		printk("%s: SABRE PCI Bus Module\n", pbm->name);

		pbm->chip_type = PBM_CHIP_TYPE_SABRE;
		pbm->chip_type = PBM_CHIP_TYPE_SABRE;
		pbm->parent = p;
		pbm->parent = p;
		pbm->prom_node = node;
		pbm->prom_node = node;
@@ -1341,83 +1344,68 @@ static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dm
		pbm->pci_first_busno = busrange[0];
		pbm->pci_first_busno = busrange[0];
		pbm->pci_last_busno = busrange[1];
		pbm->pci_last_busno = busrange[1];


		prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name));
		prop = of_find_property(node, "ranges", &len);
		err = prom_getproperty(node, "ranges",
		if (prop) {
				       (char *)pbm->pbm_ranges,
			pbm->pbm_ranges = prop->value;
				       sizeof(pbm->pbm_ranges));
		if (err != -1)
			pbm->num_pbm_ranges =
			pbm->num_pbm_ranges =
				(err / sizeof(struct linux_prom_pci_ranges));
				(len / sizeof(struct linux_prom_pci_ranges));
		else
		} else {
			pbm->num_pbm_ranges = 0;
			pbm->num_pbm_ranges = 0;

		err = prom_getproperty(node, "interrupt-map",
				       (char *)pbm->pbm_intmap,
				       sizeof(pbm->pbm_intmap));
		if (err != -1) {
			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
			err = prom_getproperty(node, "interrupt-map-mask",
					       (char *)&pbm->pbm_intmask,
					       sizeof(pbm->pbm_intmask));
			if (err == -1) {
				prom_printf("APB: Fatal error, no interrupt-map-mask.\n");
				prom_halt();
		}
		}

		prop = of_find_property(node, "interrupt-map", &len);
		if (prop) {
			pbm->pbm_intmap = prop->value;
			pbm->num_pbm_intmap =
				(len / sizeof(struct linux_prom_pci_intmap));

			prop = of_find_property(node, "interrupt-map-mask",
						NULL);
			pbm->pbm_intmask = prop->value;
		} else {
		} else {
			pbm->num_pbm_intmap = 0;
			pbm->num_pbm_intmap = 0;
			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
		}
		}


		pbm_register_toplevel_resources(p, pbm);
		pbm_register_toplevel_resources(p, pbm);


	next_pci:
	next_pci:
		node = prom_getsibling(node);
		node = node->sibling;
		if (!node)
			break;
	}
	}
	if (simbas_found == 0) {
	if (simbas_found == 0) {
		int err;

		/* No APBs underneath, probably this is a hummingbird
		/* No APBs underneath, probably this is a hummingbird
		 * system.
		 * system.
		 */
		 */
		pbm = &p->pbm_A;
		pbm = &p->pbm_A;
		pbm->parent = p;
		pbm->parent = p;
		pbm->prom_node = sabre_node;
		pbm->prom_node = dp;
		pbm->pci_first_busno = p->pci_first_busno;
		pbm->pci_first_busno = p->pci_first_busno;
		pbm->pci_last_busno = p->pci_last_busno;
		pbm->pci_last_busno = p->pci_last_busno;


		prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name));
		prop = of_find_property(dp, "ranges", &len);
		err = prom_getproperty(sabre_node, "ranges",
		if (prop) {
				       (char *) pbm->pbm_ranges,
			pbm->pbm_ranges = prop->value;
				       sizeof(pbm->pbm_ranges));
		if (err != -1)
			pbm->num_pbm_ranges =
			pbm->num_pbm_ranges =
				(err / sizeof(struct linux_prom_pci_ranges));
				(len / sizeof(struct linux_prom_pci_ranges));
		else
		} else {
			pbm->num_pbm_ranges = 0;
			pbm->num_pbm_ranges = 0;

		err = prom_getproperty(sabre_node, "interrupt-map",
				       (char *) pbm->pbm_intmap,
				       sizeof(pbm->pbm_intmap));

		if (err != -1) {
			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
			err = prom_getproperty(sabre_node, "interrupt-map-mask",
					       (char *)&pbm->pbm_intmask,
					       sizeof(pbm->pbm_intmask));
			if (err == -1) {
				prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n");
				prom_halt();
		}
		}

		prop = of_find_property(dp, "interrupt-map", &len);
		if (prop) {
			pbm->pbm_intmap = prop->value;
			pbm->num_pbm_intmap =
				(len / sizeof(struct linux_prom_pci_intmap));

			prop = of_find_property(dp, "interrupt-map-mask",
						NULL);
			pbm->pbm_intmask = prop->value;
		} else {
		} else {
			pbm->num_pbm_intmap = 0;
			pbm->num_pbm_intmap = 0;
			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
		}
		}


		pbm->name = dp->full_name;
		printk("%s: SABRE PCI Bus Module\n", pbm->name);


		sprintf(pbm->name, "SABRE%d PBM%c", p->index,
			(pbm == &p->pbm_A ? 'A' : 'B'));
		pbm->io_space.name = pbm->mem_space.name = pbm->name;
		pbm->io_space.name = pbm->mem_space.name = pbm->name;


		/* Hack up top-level resources. */
		/* Hack up top-level resources. */
@@ -1443,14 +1431,15 @@ static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dm
	}
	}
}
}


void sabre_init(int pnode, char *model_name)
void sabre_init(struct device_node *dp, char *model_name)
{
{
	struct linux_prom64_registers pr_regs[2];
	struct linux_prom64_registers *pr_regs;
	struct pci_controller_info *p;
	struct pci_controller_info *p;
	struct pci_iommu *iommu;
	struct pci_iommu *iommu;
	int tsbsize, err;
	struct property *prop;
	u32 busrange[2];
	int tsbsize;
	u32 vdma[2];
	u32 *busrange;
	u32 *vdma;
	u32 upa_portid, dma_mask;
	u32 upa_portid, dma_mask;
	u64 clear_irq;
	u64 clear_irq;


@@ -1458,13 +1447,15 @@ void sabre_init(int pnode, char *model_name)
	if (!strcmp(model_name, "pci108e,a001"))
	if (!strcmp(model_name, "pci108e,a001"))
		hummingbird_p = 1;
		hummingbird_p = 1;
	else if (!strcmp(model_name, "SUNW,sabre")) {
	else if (!strcmp(model_name, "SUNW,sabre")) {
		char compat[64];
		prop = of_find_property(dp, "compatible", NULL);
		if (prop) {
			const char *compat = prop->value;


		if (prom_getproperty(pnode, "compatible",
			if (!strcmp(compat, "pci108e,a001"))
				     compat, sizeof(compat)) > 0 &&
		    !strcmp(compat, "pci108e,a001")) {
				hummingbird_p = 1;
				hummingbird_p = 1;
		} else {
		}
		if (!hummingbird_p) {
			char compat[64];
			int cpu_node;
			int cpu_node;


			/* Of course, Sun has to encode things a thousand
			/* Of course, Sun has to encode things a thousand
@@ -1491,7 +1482,10 @@ void sabre_init(int pnode, char *model_name)
	}
	}
	p->pbm_A.iommu = p->pbm_B.iommu = iommu;
	p->pbm_A.iommu = p->pbm_B.iommu = iommu;


	upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
	upa_portid = 0xff;
	prop = of_find_property(dp, "upa-portid", NULL);
	if (prop)
		upa_portid = *(u32 *) prop->value;


	p->next = pci_controller_root;
	p->next = pci_controller_root;
	pci_controller_root = p;
	pci_controller_root = p;
@@ -1509,13 +1503,9 @@ void sabre_init(int pnode, char *model_name)
	/*
	/*
	 * Map in SABRE register set and report the presence of this SABRE.
	 * Map in SABRE register set and report the presence of this SABRE.
	 */
	 */
	err = prom_getproperty(pnode, "reg",
	
			       (char *)&pr_regs[0], sizeof(pr_regs));
	prop = of_find_property(dp, "reg", NULL);
	if(err == 0 || err == -1) {
	pr_regs = prop->value;
		prom_printf("SABRE: Error, cannot get U2P registers "
			    "from PROM.\n");
		prom_halt();
	}


	/*
	/*
	 * First REG in property is base of entire SABRE register space.
	 * First REG in property is base of entire SABRE register space.
@@ -1523,9 +1513,6 @@ void sabre_init(int pnode, char *model_name)
	p->pbm_A.controller_regs = pr_regs[0].phys_addr;
	p->pbm_A.controller_regs = pr_regs[0].phys_addr;
	p->pbm_B.controller_regs = pr_regs[0].phys_addr;
	p->pbm_B.controller_regs = pr_regs[0].phys_addr;


	printk("PCI: Found SABRE, main regs at %016lx\n",
	       p->pbm_A.controller_regs);

	/* Clear interrupts */
	/* Clear interrupts */


	/* PCI first */
	/* PCI first */
@@ -1544,16 +1531,9 @@ void sabre_init(int pnode, char *model_name)
	/* Now map in PCI config space for entire SABRE. */
	/* Now map in PCI config space for entire SABRE. */
	p->pbm_A.config_space = p->pbm_B.config_space =
	p->pbm_A.config_space = p->pbm_B.config_space =
		(p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
		(p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
	printk("SABRE: Shared PCI config space at %016lx\n",

	       p->pbm_A.config_space);
	prop = of_find_property(dp, "virtual-dma", NULL);

	vdma = prop->value;
	err = prom_getproperty(pnode, "virtual-dma",
			       (char *)&vdma[0], sizeof(vdma));
	if(err == 0 || err == -1) {
		prom_printf("SABRE: Error, cannot get virtual-dma property "
			    "from PROM.\n");
		prom_halt();
	}


	dma_mask = vdma[0];
	dma_mask = vdma[0];
	switch(vdma[1]) {
	switch(vdma[1]) {
@@ -1577,21 +1557,13 @@ void sabre_init(int pnode, char *model_name)


	sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);
	sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);


	printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
	prop = of_find_property(dp, "bus-range", NULL);

	busrange = prop->value;
	err = prom_getproperty(pnode, "bus-range",
				       (char *)&busrange[0], sizeof(busrange));
	if(err == 0 || err == -1) {
		prom_printf("SABRE: Error, cannot get PCI bus-range "
			    " from PROM.\n");
		prom_halt();
	}

	p->pci_first_busno = busrange[0];
	p->pci_first_busno = busrange[0];
	p->pci_last_busno = busrange[1];
	p->pci_last_busno = busrange[1];


	/*
	/*
	 * Look for APB underneath.
	 * Look for APB underneath.
	 */
	 */
	sabre_pbm_init(p, pnode, vdma[0]);
	sabre_pbm_init(p, dp, vdma[0]);
}
}
+76 −97

File changed.

Preview size limit exceeded, changes collapsed.

Loading