aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_sabre.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_sabre.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_sabre.c')
-rw-r--r--arch/sparc64/kernel/pci_sabre.c192
1 files changed, 82 insertions, 110 deletions
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index b7d997b55f0a..91d1aa44efc1 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -19,6 +19,7 @@
19#include <asm/irq.h> 19#include <asm/irq.h>
20#include <asm/smp.h> 20#include <asm/smp.h>
21#include <asm/oplib.h> 21#include <asm/oplib.h>
22#include <asm/prom.h>
22 23
23#include "pci_impl.h" 24#include "pci_impl.h"
24#include "iommu_common.h" 25#include "iommu_common.h"
@@ -1160,7 +1161,7 @@ static void sabre_scan_bus(struct pci_controller_info *p)
1160 1161
1161 pbus->sysdata = pbm; 1162 pbus->sysdata = pbm;
1162 pbm->pci_bus = pbus; 1163 pbm->pci_bus = pbus;
1163 pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node); 1164 pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node->node);
1164 pci_record_assignments(pbm, pbus); 1165 pci_record_assignments(pbm, pbus);
1165 pci_assign_unassigned(pbm, pbus); 1166 pci_assign_unassigned(pbm, pbus);
1166 pci_fixup_irq(pbm, pbus); 1167 pci_fixup_irq(pbm, pbus);
@@ -1173,7 +1174,7 @@ static void sabre_scan_bus(struct pci_controller_info *p)
1173 pbm = &p->pbm_A; 1174 pbm = &p->pbm_A;
1174 sabre_bus->sysdata = pbm; 1175 sabre_bus->sysdata = pbm;
1175 pbm->pci_bus = sabre_bus; 1176 pbm->pci_bus = sabre_bus;
1176 pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node); 1177 pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node->node);
1177 pci_record_assignments(pbm, sabre_bus); 1178 pci_record_assignments(pbm, sabre_bus);
1178 pci_assign_unassigned(pbm, sabre_bus); 1179 pci_assign_unassigned(pbm, sabre_bus);
1179 pci_fixup_irq(pbm, sabre_bus); 1180 pci_fixup_irq(pbm, sabre_bus);
@@ -1306,34 +1307,36 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p,
1306 &pbm->mem_space); 1307 &pbm->mem_space);
1307} 1308}
1308 1309
1309static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin) 1310static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin)
1310{ 1311{
1311 struct pci_pbm_info *pbm; 1312 struct pci_pbm_info *pbm;
1312 char namebuf[128]; 1313 struct device_node *node;
1313 u32 busrange[2]; 1314 struct property *prop;
1314 int node, simbas_found; 1315 u32 *busrange;
1316 int len, simbas_found;
1315 1317
1316 simbas_found = 0; 1318 simbas_found = 0;
1317 node = prom_getchild(sabre_node); 1319 node = dp->child;
1318 while ((node = prom_searchsiblings(node, "pci")) != 0) { 1320 while (node != NULL) {
1319 int err; 1321 if (strcmp(node->name, "pci"))
1320
1321 err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
1322 if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))
1323 goto next_pci; 1322 goto next_pci;
1324 1323
1325 err = prom_getproperty(node, "bus-range", 1324 prop = of_find_property(node, "model", NULL);
1326 (char *)&busrange[0], sizeof(busrange)); 1325 if (!prop || strncmp(prop->value, "SUNW,simba", prop->length))
1327 if (err == 0 || err == -1) { 1326 goto next_pci;
1328 prom_printf("APB: Error, cannot get PCI bus-range.\n");
1329 prom_halt();
1330 }
1331 1327
1332 simbas_found++; 1328 simbas_found++;
1329
1330 prop = of_find_property(node, "bus-range", NULL);
1331 busrange = prop->value;
1333 if (busrange[0] == 1) 1332 if (busrange[0] == 1)
1334 pbm = &p->pbm_B; 1333 pbm = &p->pbm_B;
1335 else 1334 else
1336 pbm = &p->pbm_A; 1335 pbm = &p->pbm_A;
1336
1337 pbm->name = node->full_name;
1338 printk("%s: SABRE PCI Bus Module\n", pbm->name);
1339
1337 pbm->chip_type = PBM_CHIP_TYPE_SABRE; 1340 pbm->chip_type = PBM_CHIP_TYPE_SABRE;
1338 pbm->parent = p; 1341 pbm->parent = p;
1339 pbm->prom_node = node; 1342 pbm->prom_node = node;
@@ -1341,83 +1344,68 @@ static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dm
1341 pbm->pci_first_busno = busrange[0]; 1344 pbm->pci_first_busno = busrange[0];
1342 pbm->pci_last_busno = busrange[1]; 1345 pbm->pci_last_busno = busrange[1];
1343 1346
1344 prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name)); 1347 prop = of_find_property(node, "ranges", &len);
1345 err = prom_getproperty(node, "ranges", 1348 if (prop) {
1346 (char *)pbm->pbm_ranges, 1349 pbm->pbm_ranges = prop->value;
1347 sizeof(pbm->pbm_ranges));
1348 if (err != -1)
1349 pbm->num_pbm_ranges = 1350 pbm->num_pbm_ranges =
1350 (err / sizeof(struct linux_prom_pci_ranges)); 1351 (len / sizeof(struct linux_prom_pci_ranges));
1351 else 1352 } else {
1352 pbm->num_pbm_ranges = 0; 1353 pbm->num_pbm_ranges = 0;
1354 }
1353 1355
1354 err = prom_getproperty(node, "interrupt-map", 1356 prop = of_find_property(node, "interrupt-map", &len);
1355 (char *)pbm->pbm_intmap, 1357 if (prop) {
1356 sizeof(pbm->pbm_intmap)); 1358 pbm->pbm_intmap = prop->value;
1357 if (err != -1) { 1359 pbm->num_pbm_intmap =
1358 pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); 1360 (len / sizeof(struct linux_prom_pci_intmap));
1359 err = prom_getproperty(node, "interrupt-map-mask", 1361
1360 (char *)&pbm->pbm_intmask, 1362 prop = of_find_property(node, "interrupt-map-mask",
1361 sizeof(pbm->pbm_intmask)); 1363 NULL);
1362 if (err == -1) { 1364 pbm->pbm_intmask = prop->value;
1363 prom_printf("APB: Fatal error, no interrupt-map-mask.\n");
1364 prom_halt();
1365 }
1366 } else { 1365 } else {
1367 pbm->num_pbm_intmap = 0; 1366 pbm->num_pbm_intmap = 0;
1368 memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
1369 } 1367 }
1370 1368
1371 pbm_register_toplevel_resources(p, pbm); 1369 pbm_register_toplevel_resources(p, pbm);
1372 1370
1373 next_pci: 1371 next_pci:
1374 node = prom_getsibling(node); 1372 node = node->sibling;
1375 if (!node)
1376 break;
1377 } 1373 }
1378 if (simbas_found == 0) { 1374 if (simbas_found == 0) {
1379 int err;
1380
1381 /* No APBs underneath, probably this is a hummingbird 1375 /* No APBs underneath, probably this is a hummingbird
1382 * system. 1376 * system.
1383 */ 1377 */
1384 pbm = &p->pbm_A; 1378 pbm = &p->pbm_A;
1385 pbm->parent = p; 1379 pbm->parent = p;
1386 pbm->prom_node = sabre_node; 1380 pbm->prom_node = dp;
1387 pbm->pci_first_busno = p->pci_first_busno; 1381 pbm->pci_first_busno = p->pci_first_busno;
1388 pbm->pci_last_busno = p->pci_last_busno; 1382 pbm->pci_last_busno = p->pci_last_busno;
1389 1383
1390 prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name)); 1384 prop = of_find_property(dp, "ranges", &len);
1391 err = prom_getproperty(sabre_node, "ranges", 1385 if (prop) {
1392 (char *) pbm->pbm_ranges, 1386 pbm->pbm_ranges = prop->value;
1393 sizeof(pbm->pbm_ranges));
1394 if (err != -1)
1395 pbm->num_pbm_ranges = 1387 pbm->num_pbm_ranges =
1396 (err / sizeof(struct linux_prom_pci_ranges)); 1388 (len / sizeof(struct linux_prom_pci_ranges));
1397 else 1389 } else {
1398 pbm->num_pbm_ranges = 0; 1390 pbm->num_pbm_ranges = 0;
1391 }
1399 1392
1400 err = prom_getproperty(sabre_node, "interrupt-map", 1393 prop = of_find_property(dp, "interrupt-map", &len);
1401 (char *) pbm->pbm_intmap, 1394 if (prop) {
1402 sizeof(pbm->pbm_intmap)); 1395 pbm->pbm_intmap = prop->value;
1403 1396 pbm->num_pbm_intmap =
1404 if (err != -1) { 1397 (len / sizeof(struct linux_prom_pci_intmap));
1405 pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); 1398
1406 err = prom_getproperty(sabre_node, "interrupt-map-mask", 1399 prop = of_find_property(dp, "interrupt-map-mask",
1407 (char *)&pbm->pbm_intmask, 1400 NULL);
1408 sizeof(pbm->pbm_intmask)); 1401 pbm->pbm_intmask = prop->value;
1409 if (err == -1) {
1410 prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n");
1411 prom_halt();
1412 }
1413 } else { 1402 } else {
1414 pbm->num_pbm_intmap = 0; 1403 pbm->num_pbm_intmap = 0;
1415 memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
1416 } 1404 }
1417 1405
1406 pbm->name = dp->full_name;
1407 printk("%s: SABRE PCI Bus Module\n", pbm->name);
1418 1408
1419 sprintf(pbm->name, "SABRE%d PBM%c", p->index,
1420 (pbm == &p->pbm_A ? 'A' : 'B'));
1421 pbm->io_space.name = pbm->mem_space.name = pbm->name; 1409 pbm->io_space.name = pbm->mem_space.name = pbm->name;
1422 1410
1423 /* Hack up top-level resources. */ 1411 /* 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 } 1431 }
1444} 1432}
1445 1433
1446void sabre_init(int pnode, char *model_name) 1434void sabre_init(struct device_node *dp, char *model_name)
1447{ 1435{
1448 struct linux_prom64_registers pr_regs[2]; 1436 struct linux_prom64_registers *pr_regs;
1449 struct pci_controller_info *p; 1437 struct pci_controller_info *p;
1450 struct pci_iommu *iommu; 1438 struct pci_iommu *iommu;
1451 int tsbsize, err; 1439 struct property *prop;
1452 u32 busrange[2]; 1440 int tsbsize;
1453 u32 vdma[2]; 1441 u32 *busrange;
1442 u32 *vdma;
1454 u32 upa_portid, dma_mask; 1443 u32 upa_portid, dma_mask;
1455 u64 clear_irq; 1444 u64 clear_irq;
1456 1445
@@ -1458,13 +1447,15 @@ void sabre_init(int pnode, char *model_name)
1458 if (!strcmp(model_name, "pci108e,a001")) 1447 if (!strcmp(model_name, "pci108e,a001"))
1459 hummingbird_p = 1; 1448 hummingbird_p = 1;
1460 else if (!strcmp(model_name, "SUNW,sabre")) { 1449 else if (!strcmp(model_name, "SUNW,sabre")) {
1461 char compat[64]; 1450 prop = of_find_property(dp, "compatible", NULL);
1451 if (prop) {
1452 const char *compat = prop->value;
1462 1453
1463 if (prom_getproperty(pnode, "compatible", 1454 if (!strcmp(compat, "pci108e,a001"))
1464 compat, sizeof(compat)) > 0 && 1455 hummingbird_p = 1;
1465 !strcmp(compat, "pci108e,a001")) { 1456 }
1466 hummingbird_p = 1; 1457 if (!hummingbird_p) {
1467 } else { 1458 char compat[64];
1468 int cpu_node; 1459 int cpu_node;
1469 1460
1470 /* Of course, Sun has to encode things a thousand 1461 /* Of course, Sun has to encode things a thousand
@@ -1491,7 +1482,10 @@ void sabre_init(int pnode, char *model_name)
1491 } 1482 }
1492 p->pbm_A.iommu = p->pbm_B.iommu = iommu; 1483 p->pbm_A.iommu = p->pbm_B.iommu = iommu;
1493 1484
1494 upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff); 1485 upa_portid = 0xff;
1486 prop = of_find_property(dp, "upa-portid", NULL);
1487 if (prop)
1488 upa_portid = *(u32 *) prop->value;
1495 1489
1496 p->next = pci_controller_root; 1490 p->next = pci_controller_root;
1497 pci_controller_root = p; 1491 pci_controller_root = p;
@@ -1509,13 +1503,9 @@ void sabre_init(int pnode, char *model_name)
1509 /* 1503 /*
1510 * Map in SABRE register set and report the presence of this SABRE. 1504 * Map in SABRE register set and report the presence of this SABRE.
1511 */ 1505 */
1512 err = prom_getproperty(pnode, "reg", 1506
1513 (char *)&pr_regs[0], sizeof(pr_regs)); 1507 prop = of_find_property(dp, "reg", NULL);
1514 if(err == 0 || err == -1) { 1508 pr_regs = prop->value;
1515 prom_printf("SABRE: Error, cannot get U2P registers "
1516 "from PROM.\n");
1517 prom_halt();
1518 }
1519 1509
1520 /* 1510 /*
1521 * First REG in property is base of entire SABRE register space. 1511 * First REG in property is base of entire SABRE register space.
@@ -1523,9 +1513,6 @@ void sabre_init(int pnode, char *model_name)
1523 p->pbm_A.controller_regs = pr_regs[0].phys_addr; 1513 p->pbm_A.controller_regs = pr_regs[0].phys_addr;
1524 p->pbm_B.controller_regs = pr_regs[0].phys_addr; 1514 p->pbm_B.controller_regs = pr_regs[0].phys_addr;
1525 1515
1526 printk("PCI: Found SABRE, main regs at %016lx\n",
1527 p->pbm_A.controller_regs);
1528
1529 /* Clear interrupts */ 1516 /* Clear interrupts */
1530 1517
1531 /* PCI first */ 1518 /* PCI first */
@@ -1544,16 +1531,9 @@ void sabre_init(int pnode, char *model_name)
1544 /* Now map in PCI config space for entire SABRE. */ 1531 /* Now map in PCI config space for entire SABRE. */
1545 p->pbm_A.config_space = p->pbm_B.config_space = 1532 p->pbm_A.config_space = p->pbm_B.config_space =
1546 (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); 1533 (p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
1547 printk("SABRE: Shared PCI config space at %016lx\n", 1534
1548 p->pbm_A.config_space); 1535 prop = of_find_property(dp, "virtual-dma", NULL);
1549 1536 vdma = prop->value;
1550 err = prom_getproperty(pnode, "virtual-dma",
1551 (char *)&vdma[0], sizeof(vdma));
1552 if(err == 0 || err == -1) {
1553 prom_printf("SABRE: Error, cannot get virtual-dma property "
1554 "from PROM.\n");
1555 prom_halt();
1556 }
1557 1537
1558 dma_mask = vdma[0]; 1538 dma_mask = vdma[0];
1559 switch(vdma[1]) { 1539 switch(vdma[1]) {
@@ -1577,21 +1557,13 @@ void sabre_init(int pnode, char *model_name)
1577 1557
1578 sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); 1558 sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);
1579 1559
1580 printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]); 1560 prop = of_find_property(dp, "bus-range", NULL);
1581 1561 busrange = prop->value;
1582 err = prom_getproperty(pnode, "bus-range",
1583 (char *)&busrange[0], sizeof(busrange));
1584 if(err == 0 || err == -1) {
1585 prom_printf("SABRE: Error, cannot get PCI bus-range "
1586 " from PROM.\n");
1587 prom_halt();
1588 }
1589
1590 p->pci_first_busno = busrange[0]; 1562 p->pci_first_busno = busrange[0];
1591 p->pci_last_busno = busrange[1]; 1563 p->pci_last_busno = busrange[1];
1592 1564
1593 /* 1565 /*
1594 * Look for APB underneath. 1566 * Look for APB underneath.
1595 */ 1567 */
1596 sabre_pbm_init(p, pnode, vdma[0]); 1568 sabre_pbm_init(p, dp, vdma[0]);
1597} 1569}