diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-06-21 21:18:47 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-24 02:15:07 -0400 |
commit | e87dc35020bc555969810452f44bceaf8394eafa (patch) | |
tree | b58f14d41f8e147f6ddc2d9657a88813fdb73bdf /arch/sparc64/kernel/pci_psycho.c | |
parent | aaf7cec2769942035985716452107fc5ba0b11f6 (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.c | 108 |
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 | ||
1293 | static void psycho_pbm_init(struct pci_controller_info *p, | 1294 | static 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 | ||
1372 | void psycho_init(int node, char *model_name) | 1369 | void 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 | } |