aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_psycho.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-06-21 21:18:47 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-24 02:15:07 -0400
commite87dc35020bc555969810452f44bceaf8394eafa (patch)
treeb58f14d41f8e147f6ddc2d9657a88813fdb73bdf /arch/sparc64/kernel/pci_psycho.c
parentaaf7cec2769942035985716452107fc5ba0b11f6 (diff)
[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: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/pci_psycho.c')
-rw-r--r--arch/sparc64/kernel/pci_psycho.c108
1 files changed, 50 insertions, 58 deletions
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 24db22aa9728..40c2b6819983 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -17,6 +17,7 @@
17#include <asm/iommu.h> 17#include <asm/iommu.h>
18#include <asm/irq.h> 18#include <asm/irq.h>
19#include <asm/starfire.h> 19#include <asm/starfire.h>
20#include <asm/prom.h>
20 21
21#include "pci_impl.h" 22#include "pci_impl.h"
22#include "iommu_common.h" 23#include "iommu_common.h"
@@ -1103,7 +1104,7 @@ static void pbm_scan_bus(struct pci_controller_info *p,
1103 pci_fixup_host_bridge_self(pbm->pci_bus); 1104 pci_fixup_host_bridge_self(pbm->pci_bus);
1104 pbm->pci_bus->self->sysdata = cookie; 1105 pbm->pci_bus->self->sysdata = cookie;
1105 1106
1106 pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); 1107 pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node->node);
1107 pci_record_assignments(pbm, pbm->pci_bus); 1108 pci_record_assignments(pbm, pbm->pci_bus);
1108 pci_assign_unassigned(pbm, pbm->pci_bus); 1109 pci_assign_unassigned(pbm, pbm->pci_bus);
1109 pci_fixup_irq(pbm, pbm->pci_bus); 1110 pci_fixup_irq(pbm, pbm->pci_bus);
@@ -1291,11 +1292,12 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
1291#define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL 1292#define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL
1292 1293
1293static void psycho_pbm_init(struct pci_controller_info *p, 1294static void psycho_pbm_init(struct pci_controller_info *p,
1294 int prom_node, int is_pbm_a) 1295 struct device_node *dp, int is_pbm_a)
1295{ 1296{
1296 unsigned int busrange[2]; 1297 unsigned int *busrange;
1298 struct property *prop;
1297 struct pci_pbm_info *pbm; 1299 struct pci_pbm_info *pbm;
1298 int err; 1300 int len;
1299 1301
1300 if (is_pbm_a) { 1302 if (is_pbm_a) {
1301 pbm = &p->pbm_A; 1303 pbm = &p->pbm_A;
@@ -1310,10 +1312,14 @@ static void psycho_pbm_init(struct pci_controller_info *p,
1310 } 1312 }
1311 1313
1312 pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; 1314 pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
1313 pbm->chip_version = 1315 pbm->chip_version = 0;
1314 prom_getintdefault(prom_node, "version#", 0); 1316 prop = of_find_property(dp, "version#", NULL);
1315 pbm->chip_revision = 1317 if (prop)
1316 prom_getintdefault(prom_node, "module-revision#", 0); 1318 pbm->chip_version = *(int *) prop->value;
1319 pbm->chip_revision = 0;
1320 prop = of_find_property(dp, "module-revision#", NULL);
1321 if (prop)
1322 pbm->chip_revision = *(int *) prop->value;
1317 1323
1318 pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE; 1324 pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
1319 pbm->io_space.flags = IORESOURCE_IO; 1325 pbm->io_space.flags = IORESOURCE_IO;
@@ -1322,45 +1328,36 @@ static void psycho_pbm_init(struct pci_controller_info *p,
1322 pbm_register_toplevel_resources(p, pbm); 1328 pbm_register_toplevel_resources(p, pbm);
1323 1329
1324 pbm->parent = p; 1330 pbm->parent = p;
1325 pbm->prom_node = prom_node; 1331 pbm->prom_node = dp;
1326 prom_getstring(prom_node, "name", 1332 pbm->name = dp->full_name;
1327 pbm->prom_name, 1333
1328 sizeof(pbm->prom_name)); 1334 printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n",
1329 1335 pbm->name,
1330 err = prom_getproperty(prom_node, "ranges", 1336 pbm->chip_version, pbm->chip_revision);
1331 (char *)pbm->pbm_ranges, 1337
1332 sizeof(pbm->pbm_ranges)); 1338 prop = of_find_property(dp, "ranges", &len);
1333 if (err != -1) 1339 if (prop) {
1340 pbm->pbm_ranges = prop->value;
1334 pbm->num_pbm_ranges = 1341 pbm->num_pbm_ranges =
1335 (err / sizeof(struct linux_prom_pci_ranges)); 1342 (len / sizeof(struct linux_prom_pci_ranges));
1336 else 1343 } else {
1337 pbm->num_pbm_ranges = 0; 1344 pbm->num_pbm_ranges = 0;
1345 }
1338 1346
1339 err = prom_getproperty(prom_node, "interrupt-map", 1347 prop = of_find_property(dp, "interrupt-map", &len);
1340 (char *)pbm->pbm_intmap, 1348 if (prop) {
1341 sizeof(pbm->pbm_intmap)); 1349 pbm->pbm_intmap = prop->value;
1342 if (err != -1) { 1350 pbm->num_pbm_intmap =
1343 pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); 1351 (len / sizeof(struct linux_prom_pci_intmap));
1344 err = prom_getproperty(prom_node, "interrupt-map-mask", 1352
1345 (char *)&pbm->pbm_intmask, 1353 prop = of_find_property(dp, "interrupt-map-mask", NULL);
1346 sizeof(pbm->pbm_intmask)); 1354 pbm->pbm_intmask = prop->value;
1347 if (err == -1) {
1348 prom_printf("PSYCHO-PBM: Fatal error, no "
1349 "interrupt-map-mask.\n");
1350 prom_halt();
1351 }
1352 } else { 1355 } else {
1353 pbm->num_pbm_intmap = 0; 1356 pbm->num_pbm_intmap = 0;
1354 memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
1355 } 1357 }
1356 1358
1357 err = prom_getproperty(prom_node, "bus-range", 1359 prop = of_find_property(dp, "bus-range", NULL);
1358 (char *)&busrange[0], 1360 busrange = prop->value;
1359 sizeof(busrange));
1360 if (err == 0 || err == -1) {
1361 prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n");
1362 prom_halt();
1363 }
1364 pbm->pci_first_busno = busrange[0]; 1361 pbm->pci_first_busno = busrange[0];
1365 pbm->pci_last_busno = busrange[1]; 1362 pbm->pci_last_busno = busrange[1];
1366 1363
@@ -1369,20 +1366,24 @@ static void psycho_pbm_init(struct pci_controller_info *p,
1369 1366
1370#define PSYCHO_CONFIGSPACE 0x001000000UL 1367#define PSYCHO_CONFIGSPACE 0x001000000UL
1371 1368
1372void psycho_init(int node, char *model_name) 1369void psycho_init(struct device_node *dp, char *model_name)
1373{ 1370{
1374 struct linux_prom64_registers pr_regs[3]; 1371 struct linux_prom64_registers *pr_regs;
1375 struct pci_controller_info *p; 1372 struct pci_controller_info *p;
1376 struct pci_iommu *iommu; 1373 struct pci_iommu *iommu;
1374 struct property *prop;
1377 u32 upa_portid; 1375 u32 upa_portid;
1378 int is_pbm_a, err; 1376 int is_pbm_a;
1379 1377
1380 upa_portid = prom_getintdefault(node, "upa-portid", 0xff); 1378 upa_portid = 0xff;
1379 prop = of_find_property(dp, "upa-portid", NULL);
1380 if (prop)
1381 upa_portid = *(u32 *) prop->value;
1381 1382
1382 for(p = pci_controller_root; p; p = p->next) { 1383 for(p = pci_controller_root; p; p = p->next) {
1383 if (p->pbm_A.portid == upa_portid) { 1384 if (p->pbm_A.portid == upa_portid) {
1384 is_pbm_a = (p->pbm_A.prom_node == 0); 1385 is_pbm_a = (p->pbm_A.prom_node == NULL);
1385 psycho_pbm_init(p, node, is_pbm_a); 1386 psycho_pbm_init(p, dp, is_pbm_a);
1386 return; 1387 return;
1387 } 1388 }
1388 } 1389 }
@@ -1412,23 +1413,14 @@ void psycho_init(int node, char *model_name)
1412 p->resource_adjust = psycho_resource_adjust; 1413 p->resource_adjust = psycho_resource_adjust;
1413 p->pci_ops = &psycho_ops; 1414 p->pci_ops = &psycho_ops;
1414 1415
1415 err = prom_getproperty(node, "reg", 1416 prop = of_find_property(dp, "reg", NULL);
1416 (char *)&pr_regs[0], 1417 pr_regs = prop->value;
1417 sizeof(pr_regs));
1418 if (err == 0 || err == -1) {
1419 prom_printf("PSYCHO: Fatal error, no reg property.\n");
1420 prom_halt();
1421 }
1422 1418
1423 p->pbm_A.controller_regs = pr_regs[2].phys_addr; 1419 p->pbm_A.controller_regs = pr_regs[2].phys_addr;
1424 p->pbm_B.controller_regs = pr_regs[2].phys_addr; 1420 p->pbm_B.controller_regs = pr_regs[2].phys_addr;
1425 printk("PCI: Found PSYCHO, control regs at %016lx\n",
1426 p->pbm_A.controller_regs);
1427 1421
1428 p->pbm_A.config_space = p->pbm_B.config_space = 1422 p->pbm_A.config_space = p->pbm_B.config_space =
1429 (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); 1423 (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
1430 printk("PSYCHO: Shared PCI config space at %016lx\n",
1431 p->pbm_A.config_space);
1432 1424
1433 /* 1425 /*
1434 * Psycho's PCI MEM space is mapped to a 2GB aligned area, so 1426 * 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 psycho_iommu_init(p); 1433 psycho_iommu_init(p);
1442 1434
1443 is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); 1435 is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
1444 psycho_pbm_init(p, node, is_pbm_a); 1436 psycho_pbm_init(p, dp, is_pbm_a);
1445} 1437}