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

[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
...@@ -22,6 +22,7 @@ ...@@ -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) ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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;
......
...@@ -664,7 +664,7 @@ static unsigned int __init pci_intmap_match_to_root(struct pci_pbm_info *pbm, ...@@ -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 ...@@ -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 ...@@ -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: ...@@ -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;
......
...@@ -17,6 +17,7 @@ ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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);
} }
...@@ -19,6 +19,7 @@ ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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]);
} }
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/upa.h> #include <asm/upa.h>
#include <asm/pstate.h> #include <asm/pstate.h>
#include <asm/prom.h>
#include "pci_impl.h" #include "pci_impl.h"
#include "iommu_common.h" #include "iommu_common.h"
...@@ -1437,7 +1438,7 @@ static void pbm_scan_bus(struct pci_controller_info *p, ...@@ -1437,7 +1438,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);
...@@ -1456,10 +1457,12 @@ static void __schizo_scan_bus(struct pci_controller_info *p, ...@@ -1456,10 +1457,12 @@ static void __schizo_scan_bus(struct pci_controller_info *p,
pbm_config_busmastering(&p->pbm_B); pbm_config_busmastering(&p->pbm_B);
p->pbm_B.is_66mhz_capable = p->pbm_B.is_66mhz_capable =
prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL)
!= NULL);
pbm_config_busmastering(&p->pbm_A); pbm_config_busmastering(&p->pbm_A);
p->pbm_A.is_66mhz_capable = p->pbm_A.is_66mhz_capable =
prom_getbool(p->pbm_A.prom_node, "66mhz-capable"); (of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL)
!= NULL);
pbm_scan_bus(p, &p->pbm_B); pbm_scan_bus(p, &p->pbm_B);
pbm_scan_bus(p, &p->pbm_A); pbm_scan_bus(p, &p->pbm_A);
...@@ -1661,13 +1664,18 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) ...@@ -1661,13 +1664,18 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
{ {
struct pci_iommu *iommu = pbm->iommu; struct pci_iommu *iommu = pbm->iommu;
unsigned long i, tagbase, database; unsigned long i, tagbase, database;
struct property *prop;
u32 vdma[2], dma_mask; u32 vdma[2], dma_mask;
u64 control; u64 control;
int err, tsbsize; int tsbsize;
err = prom_getproperty(pbm->prom_node, "virtual-dma", prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
(char *)&vdma[0], sizeof(vdma)); if (prop) {
if (err == 0 || err == -1) { u32 *val = prop->value;
vdma[0] = val[0];
vdma[1] = val[1];
} else {
/* No property, use default values. */ /* No property, use default values. */
vdma[0] = 0xc0000000; vdma[0] = 0xc0000000;
vdma[1] = 0x40000000; vdma[1] = 0x40000000;
...@@ -1778,6 +1786,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) ...@@ -1778,6 +1786,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
{ {
struct property *prop;
u64 tmp; u64 tmp;
schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5);
...@@ -1791,7 +1800,8 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) ...@@ -1791,7 +1800,8 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
pbm->chip_version >= 0x2) pbm->chip_version >= 0x2)
tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
if (!prom_getbool(pbm->prom_node, "no-bus-parking")) prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL);
if (!prop)
tmp |= SCHIZO_PCICTRL_PARK; tmp |= SCHIZO_PCICTRL_PARK;
else else
tmp &= ~SCHIZO_PCICTRL_PARK; tmp &= ~SCHIZO_PCICTRL_PARK;
...@@ -1831,16 +1841,17 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) ...@@ -1831,16 +1841,17 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
} }
static void schizo_pbm_init(struct pci_controller_info *p, static void schizo_pbm_init(struct pci_controller_info *p,
int prom_node, u32 portid, struct device_node *dp, u32 portid,
int chip_type) int chip_type)
{ {
struct linux_prom64_registers pr_regs[4]; struct linux_prom64_registers *regs;
unsigned int busrange[2]; struct property *prop;
unsigned int *busrange;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
const char *chipset_name; const char *chipset_name;
u32 ino_bitmap[2]; u32 *ino_bitmap;
int is_pbm_a; int is_pbm_a;
int err; int len;
switch (chip_type) { switch (chip_type) {
case PBM_CHIP_TYPE_TOMATILLO: case PBM_CHIP_TYPE_TOMATILLO:
...@@ -1868,16 +1879,10 @@ static void schizo_pbm_init(struct pci_controller_info *p, ...@@ -1868,16 +1879,10 @@ static void schizo_pbm_init(struct pci_controller_info *p,
* 3) PBM PCI config space * 3) PBM PCI config space
* 4) Ichip regs * 4) Ichip regs
*/ */
err = prom_getproperty(prom_node, "reg", prop = of_find_property(dp, "reg", NULL);
(char *)&pr_regs[0], regs = prop->value;
sizeof(pr_regs));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no reg property.\n",
chipset_name);
prom_halt();
}
is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000); is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
if (is_pbm_a) if (is_pbm_a)
pbm = &p->pbm_A; pbm = &p->pbm_A;
...@@ -1886,92 +1891,62 @@ static void schizo_pbm_init(struct pci_controller_info *p, ...@@ -1886,92 +1891,62 @@ static void schizo_pbm_init(struct pci_controller_info *p,
pbm->portid = portid; pbm->portid = portid;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = prom_node; pbm->prom_node = dp;
pbm->pci_first_slot = 1; pbm->pci_first_slot = 1;
pbm->chip_type = chip_type; pbm->chip_type = chip_type;
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;
pbm->pbm_regs = pr_regs[0].phys_addr; prop = of_find_property(dp, "module-revision#", NULL);
pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL; if (prop)
pbm->chip_revision = *(int *) prop->value;
pbm->pbm_regs = regs[0].phys_addr;
pbm->controller_regs = regs[1].phys_addr - 0x10000UL;
if (chip_type == PBM_CHIP_TYPE_TOMATILLO) if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL; pbm->sync_reg = regs[3].phys_addr + 0x1a18UL;
sprintf(pbm->name, pbm->name = dp->full_name;
(chip_type == PBM_CHIP_TYPE_TOMATILLO ?
"TOMATILLO%d PBM%c" :
"SCHIZO%d PBM%c"),
p->index,
(pbm == &p->pbm_A ? 'A' : 'B'));
printk("%s: ver[%x:%x], portid %x, " printk("%s: %s PCI Bus Module ver[%x:%x]\n",
"cregs[%lx] pregs[%lx]\n",
pbm->name, pbm->name,
pbm->chip_version, pbm->chip_revision, (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
pbm->portid, "TOMATILLO" : "SCHIZO"),
pbm->controller_regs, pbm->chip_version, pbm->chip_revision);
pbm->pbm_regs);
schizo_pbm_hw_init(pbm); schizo_pbm_hw_init(pbm);
prom_getstring(prom_node, "name", prop = of_find_property(dp, "ranges", &len);
pbm->prom_name, pbm->pbm_ranges = prop->value;
sizeof(pbm->prom_name));
err = prom_getproperty(prom_node, "ranges",
(char *) pbm->pbm_ranges,
sizeof(pbm->pbm_ranges));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no ranges property.\n",
pbm->name);
prom_halt();
}
pbm->num_pbm_ranges = pbm->num_pbm_ranges =
(err / sizeof(struct linux_prom_pci_ranges)); (len / sizeof(struct linux_prom_pci_ranges));
schizo_determine_mem_io_space(pbm); schizo_determine_mem_io_space(pbm);
pbm_register_toplevel_resources(p, pbm); pbm_register_toplevel_resources(p, pbm);
err = prom_getproperty(prom_node, "interrupt-map", prop = of_find_property(dp, "interrupt-map", &len);
(char *)pbm->pbm_intmap, if (prop) {
sizeof(pbm->pbm_intmap)); pbm->pbm_intmap = prop->value;
if (err != -1) { pbm->num_pbm_intmap =
pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); (len / sizeof(struct linux_prom_pci_intmap));
err = prom_getproperty(prom_node, "interrupt-map-mask",
(char *)&pbm->pbm_intmask, prop = of_find_property(dp, "interrupt-map-mask", NULL);
sizeof(pbm->pbm_intmask)); pbm->pbm_intmask = prop->value;
if (err == -1) {
prom_printf("%s: Fatal error, no "
"interrupt-map-mask.\n", pbm->name);
prom_halt();
}
} 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, "ino-bitmap", prop = of_find_property(dp, "ino-bitmap", NULL);
(char *) &ino_bitmap[0], ino_bitmap = prop->value;
sizeof(ino_bitmap));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no ino-bitmap.\n", pbm->name);
prom_halt();
}
pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
((u64)ino_bitmap[0] << 0UL)); ((u64)ino_bitmap[0] << 0UL));
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("%s: Fatal error, no bus-range.\n", pbm->name);
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];
...@@ -1989,16 +1964,20 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) ...@@ -1989,16 +1964,20 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
return (x == y); return (x == y);
} }
static void __schizo_init(int node, char *model_name, int chip_type) static void __schizo_init(struct device_node *dp, char *model_name, int chip_type)
{ {
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct pci_iommu *iommu;
struct property *prop;
int is_pbm_a; int is_pbm_a;
u32 portid; u32 portid;
portid = prom_getintdefault(node, "portid", 0xff); portid = 0xff;
prop = of_find_property(dp, "portid", NULL);
if (prop)
portid = *(u32 *) prop->value;
for(p = pci_controller_root; p; p = p->next) { for (p = pci_controller_root; p; p = p->next) {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
if (p->pbm_A.prom_node && p->pbm_B.prom_node) if (p->pbm_A.prom_node && p->pbm_B.prom_node)
...@@ -2009,8 +1988,8 @@ static void __schizo_init(int node, char *model_name, int chip_type) ...@@ -2009,8 +1988,8 @@ static void __schizo_init(int node, char *model_name, int chip_type)
&p->pbm_B); &p->pbm_B);
if (portid_compare(pbm->portid, portid, chip_type)) { if (portid_compare(pbm->portid, portid, chip_type)) {
is_pbm_a = (p->pbm_A.prom_node == 0); is_pbm_a = (p->pbm_A.prom_node == NULL);
schizo_pbm_init(p, node, portid, chip_type); schizo_pbm_init(p, dp, portid, chip_type);
return; return;
} }
} }
...@@ -2051,20 +2030,20 @@ static void __schizo_init(int node, char *model_name, int chip_type) ...@@ -2051,20 +2030,20 @@ static void __schizo_init(int node, char *model_name, int chip_type)
/* Like PSYCHO we have a 2GB aligned area for memory space. */ /* Like PSYCHO we have a 2GB aligned area for memory space. */
pci_memspace_mask = 0x7fffffffUL; pci_memspace_mask = 0x7fffffffUL;
schizo_pbm_init(p, node, portid, chip_type); schizo_pbm_init(p, dp, portid, chip_type);
} }
void schizo_init(int node, char *model_name) void schizo_init(struct device_node *dp, char *model_name)
{ {
__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO); __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO);
} }
void schizo_plus_init(int node, char *model_name) void schizo_plus_init(struct device_node *dp, char *model_name)
{ {
__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS);
} }
void tomatillo_init(int node, char *model_name) void tomatillo_init(struct device_node *dp, char *model_name)
{ {
__schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO); __schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO);
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <asm/pstate.h> #include <asm/pstate.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
#include <asm/prom.h>
#include "pci_impl.h" #include "pci_impl.h"
#include "iommu_common.h" #include "iommu_common.h"
...@@ -646,35 +647,37 @@ static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, u ...@@ -646,35 +647,37 @@ static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, u
/* Recursively descend into the OBP device tree, rooted at toplevel_node, /* Recursively descend into the OBP device tree, rooted at toplevel_node,
* looking for a PCI device matching bus and devfn. * looking for a PCI device matching bus and devfn.
*/ */
static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn) static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn)
{ {
toplevel_node = prom_getchild(toplevel_node); toplevel_node = toplevel_node->child;
while (toplevel_node != 0) { while (toplevel_node != NULL) {
int ret = obp_find(pregs, toplevel_node, bus, devfn); struct linux_prom_pci_registers *regs;
struct property *prop;
int ret;
ret = obp_find(toplevel_node, bus, devfn);
if (ret != 0) if (ret != 0)
return ret; return ret;
ret = prom_getproperty(toplevel_node, "reg", (char *) pregs, prop = of_find_property(toplevel_node, "reg", NULL);
sizeof(*pregs) * PROMREG_MAX); if (!prop)
if (ret == 0 || ret == -1)
goto next_sibling; goto next_sibling;
if (((pregs[0].phys_hi >> 16) & 0xff) == bus && regs = prop->value;
((pregs[0].phys_hi >> 8) & 0xff) == devfn) if (((regs->phys_hi >> 16) & 0xff) == bus &&
((regs->phys_hi >> 8) & 0xff) == devfn)
break; break;
next_sibling: next_sibling:
toplevel_node = prom_getsibling(toplevel_node); toplevel_node = toplevel_node->sibling;
} }
return toplevel_node; return toplevel_node != NULL;
} }
static int pdev_htab_populate(struct pci_pbm_info *pbm) static int pdev_htab_populate(struct pci_pbm_info *pbm)
{ {
struct linux_prom_pci_registers pr[PROMREG_MAX];
u32 devhandle = pbm->devhandle; u32 devhandle = pbm->devhandle;
unsigned int bus; unsigned int bus;
...@@ -685,7 +688,7 @@ static int pdev_htab_populate(struct pci_pbm_info *pbm) ...@@ -685,7 +688,7 @@ static int pdev_htab_populate(struct pci_pbm_info *pbm)
unsigned int device = PCI_SLOT(devfn); unsigned int device = PCI_SLOT(devfn);
unsigned int func = PCI_FUNC(devfn); unsigned int func = PCI_FUNC(devfn);
if (obp_find(pr, pbm->prom_node, bus, devfn)) { if (obp_find(pbm->prom_node, bus, devfn)) {
int err = pdev_htab_add(devhandle, bus, int err = pdev_htab_add(devhandle, bus,
device, func); device, func);
if (err) if (err)
...@@ -812,7 +815,7 @@ static void pbm_scan_bus(struct pci_controller_info *p, ...@@ -812,7 +815,7 @@ static void pbm_scan_bus(struct pci_controller_info *p,
pbm->pci_bus->self->sysdata = cookie; pbm->pci_bus->self->sysdata = cookie;
#endif #endif
pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pci_fill_in_pbm_cookies(pbm->pci_bus, pbm,
pbm->prom_node); 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);
...@@ -822,15 +825,18 @@ static void pbm_scan_bus(struct pci_controller_info *p, ...@@ -822,15 +825,18 @@ static void pbm_scan_bus(struct pci_controller_info *p,
static void pci_sun4v_scan_bus(struct pci_controller_info *p) static void pci_sun4v_scan_bus(struct pci_controller_info *p)
{ {
if (p->pbm_A.prom_node) { struct property *prop;
p->pbm_A.is_66mhz_capable = struct device_node *dp;
prom_getbool(p->pbm_A.prom_node, "66mhz-capable");
if ((dp = p->pbm_A.prom_node) != NULL) {
prop = of_find_property(dp, "66mhz-capable", NULL);
p->pbm_A.is_66mhz_capable = (prop != NULL);
pbm_scan_bus(p, &p->pbm_A); pbm_scan_bus(p, &p->pbm_A);
} }
if (p->pbm_B.prom_node) { if ((dp = p->pbm_B.prom_node) != NULL) {
p->pbm_B.is_66mhz_capable = prop = of_find_property(dp, "66mhz-capable", NULL);
prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); p->pbm_B.is_66mhz_capable = (prop != NULL);
pbm_scan_bus(p, &p->pbm_B); pbm_scan_bus(p, &p->pbm_B);
} }
...@@ -993,13 +999,18 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, ...@@ -993,13 +999,18 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{ {
struct pci_iommu *iommu = pbm->iommu; struct pci_iommu *iommu = pbm->iommu;
struct property *prop;
unsigned long num_tsb_entries, sz; unsigned long num_tsb_entries, sz;
u32 vdma[2], dma_mask, dma_offset; u32 vdma[2], dma_mask, dma_offset;
int err, tsbsize; int tsbsize;
prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
if (prop) {
u32 *val = prop->value;
err = prom_getproperty(pbm->prom_node, "virtual-dma", vdma[0] = val[0];
(char *)&vdma[0], sizeof(vdma)); vdma[1] = val[1];
if (err == 0 || err == -1) { } else {
/* No property, use default values. */ /* No property, use default values. */
vdma[0] = 0x80000000; vdma[0] = 0x80000000;
vdma[1] = 0x80000000; vdma[1] = 0x80000000;
...@@ -1058,27 +1069,23 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) ...@@ -1058,27 +1069,23 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
{ {
unsigned int busrange[2]; struct property *prop;
int prom_node = pbm->prom_node; unsigned int *busrange;
int err;
prop = of_find_property(pbm->prom_node, "bus-range", NULL);
err = prom_getproperty(prom_node, "bus-range",
(char *)&busrange[0], busrange = prop->value;
sizeof(busrange));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
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];
} }
static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle) static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
{ {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
int err, i; struct property *prop;
int len, i;
if (devhandle & 0x40) if (devhandle & 0x40)
pbm = &p->pbm_B; pbm = &p->pbm_B;
...@@ -1086,32 +1093,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 ...@@ -1086,32 +1093,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
pbm = &p->pbm_A; pbm = &p->pbm_A;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = prom_node; pbm->prom_node = dp;
pbm->pci_first_slot = 1; pbm->pci_first_slot = 1;
pbm->devhandle = devhandle; pbm->devhandle = devhandle;
sprintf(pbm->name, "SUN4V-PCI%d PBM%c", pbm->name = dp->full_name;
p->index, (pbm == &p->pbm_A ? 'A' : 'B'));
printk("%s: devhandle[%x] prom_node[%x:%x]\n",
pbm->name, pbm->devhandle,
pbm->prom_node, prom_getchild(pbm->prom_node));
prom_getstring(prom_node, "name", printk("%s: SUN4V PCI Bus Module\n", pbm->name);
pbm->prom_name, sizeof(pbm->prom_name));
err = prom_getproperty(prom_node, "ranges",
(char *) pbm->pbm_ranges,
sizeof(pbm->pbm_ranges));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no ranges property.\n",
pbm->name);
prom_halt();
}
prop = of_find_property(dp, "ranges", &len);
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));
/* Mask out the top 8 bits of the ranges, leaving the real /* Mask out the top 8 bits of the ranges, leaving the real
* physical address. * physical address.
...@@ -1122,24 +1116,13 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 ...@@ -1122,24 +1116,13 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
pci_sun4v_determine_mem_io_space(pbm); pci_sun4v_determine_mem_io_space(pbm);
pbm_register_toplevel_resources(p, pbm); pbm_register_toplevel_resources(p, pbm);
err = prom_getproperty(prom_node, "interrupt-map", prop = of_find_property(dp, "interrupt-map", &len);
(char *)pbm->pbm_intmap, pbm->pbm_intmap = prop->value;
sizeof(pbm->pbm_intmap)); pbm->num_pbm_intmap =
if (err == 0 || err == -1) { (len / sizeof(struct linux_prom_pci_intmap));
prom_printf("%s: Fatal error, no interrupt-map property.\n",
pbm->name);
prom_halt();
}
pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); prop = of_find_property(dp, "interrupt-map-mask", NULL);
err = prom_getproperty(prom_node, "interrupt-map-mask", pbm->pbm_intmask = prop->value;
(char *)&pbm->pbm_intmask,
sizeof(pbm->pbm_intmask));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no interrupt-map-mask.\n",
pbm->name);
prom_halt();
}
pci_sun4v_get_bus_range(pbm); pci_sun4v_get_bus_range(pbm);
pci_sun4v_iommu_init(pbm); pci_sun4v_iommu_init(pbm);
...@@ -1147,16 +1130,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 ...@@ -1147,16 +1130,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
pdev_htab_populate(pbm); pdev_htab_populate(pbm);
} }
void sun4v_pci_init(int node, char *model_name) void sun4v_pci_init(struct device_node *dp, char *model_name)
{ {
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct pci_iommu *iommu;
struct linux_prom64_registers regs; struct property *prop;
struct linux_prom64_registers *regs;
u32 devhandle; u32 devhandle;
int i; int i;
prom_getproperty(node, "reg", (char *)&regs, sizeof(regs)); prop = of_find_property(dp, "reg", NULL);
devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; regs = prop->value;
devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
for (p = pci_controller_root; p; p = p->next) { for (p = pci_controller_root; p; p = p->next) {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
...@@ -1169,7 +1155,7 @@ void sun4v_pci_init(int node, char *model_name) ...@@ -1169,7 +1155,7 @@ void sun4v_pci_init(int node, char *model_name)
&p->pbm_B); &p->pbm_B);
if (pbm->devhandle == (devhandle ^ 0x40)) { if (pbm->devhandle == (devhandle ^ 0x40)) {
pci_sun4v_pbm_init(p, node, devhandle); pci_sun4v_pbm_init(p, dp, devhandle);
return; return;
} }
} }
...@@ -1220,7 +1206,7 @@ void sun4v_pci_init(int node, char *model_name) ...@@ -1220,7 +1206,7 @@ void sun4v_pci_init(int node, char *model_name)
*/ */
pci_memspace_mask = 0x7fffffffUL; pci_memspace_mask = 0x7fffffffUL;
pci_sun4v_pbm_init(p, node, devhandle); pci_sun4v_pbm_init(p, dp, devhandle);
return; return;
fatal_memory_error: fatal_memory_error:
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/iommu.h> #include <asm/iommu.h>
/* The abstraction used here is that there are PCI controllers, /* The abstraction used here is that there are PCI controllers,
...@@ -153,16 +154,15 @@ struct pci_pbm_info { ...@@ -153,16 +154,15 @@ struct pci_pbm_info {
int chip_revision; int chip_revision;
/* Name used for top-level resources. */ /* Name used for top-level resources. */
char name[64]; char *name;
/* OBP specific information. */ /* OBP specific information. */
int prom_node; struct device_node *prom_node;
char prom_name[64]; struct linux_prom_pci_ranges *pbm_ranges;
struct linux_prom_pci_ranges pbm_ranges[PROM_PCIRNG_MAX];
int num_pbm_ranges; int num_pbm_ranges;
struct linux_prom_pci_intmap pbm_intmap[PROM_PCIIMAP_MAX]; struct linux_prom_pci_intmap *pbm_intmap;
int num_pbm_intmap; int num_pbm_intmap;
struct linux_prom_pci_intmask pbm_intmask; struct linux_prom_pci_intmask *pbm_intmask;
u64 ino_bitmap; u64 ino_bitmap;
/* PBM I/O and Memory space resources. */ /* PBM I/O and Memory space resources. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment