summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/powermac
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2008-10-14 14:54:14 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2008-10-14 14:54:14 +0000
commit0d091e41decf056612b1d6a8280ab6401f861f54 (patch)
treec6f1268aba033a8e59745da49122a0eae51600b2 /sys/powerpc/powermac
parente1d3902c1d1d293d29f200516564bb6a8b9acca9 (diff)
downloadFreeBSD-src-0d091e41decf056612b1d6a8280ab6401f861f54.zip
FreeBSD-src-0d091e41decf056612b1d6a8280ab6401f861f54.tar.gz
Convert PowerPC AIM PCI and nexus busses to standard OFW bus interface. This
simplifies certain device attachments (Kauai ATA, for instance), and makes possible others on new hardware. On G5 systems, there are several otherwise standard PCI devices (Serverworks SATA) that will not allow their interrupt properties to be written, so this information must be supplied directly from Open Firmware. Obtained from: sparc64
Diffstat (limited to 'sys/powerpc/powermac')
-rw-r--r--sys/powerpc/powermac/ata_kauai.c60
-rw-r--r--sys/powerpc/powermac/grackle.c36
-rw-r--r--sys/powerpc/powermac/hrowpic.c1
-rw-r--r--sys/powerpc/powermac/macio.c4
-rw-r--r--sys/powerpc/powermac/openpic_macio.c1
-rw-r--r--sys/powerpc/powermac/uninorth.c101
-rw-r--r--sys/powerpc/powermac/uninorthvar.h12
7 files changed, 125 insertions, 90 deletions
diff --git a/sys/powerpc/powermac/ata_kauai.c b/sys/powerpc/powermac/ata_kauai.c
index 0582251..53fc676 100644
--- a/sys/powerpc/powermac/ata_kauai.c
+++ b/sys/powerpc/powermac/ata_kauai.c
@@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
#include <ata_if.h>
#include <dev/ofw/openfirm.h>
-#include <powerpc/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
#include <machine/intr_machdep.h>
#include <dev/pci/pcivar.h>
@@ -194,11 +194,10 @@ ata_kauai_probe(device_t dev)
{
struct ata_channel *ch;
struct ata_kauai_softc *sc;
- u_long startp, countp;
u_int32_t devid;
phandle_t node;
- char *compatstring = NULL;
- int i, found, rid, status;
+ const char *compatstring = NULL;
+ int i, found, rid;
found = 0;
devid = pci_get_devid(dev);
@@ -212,59 +211,18 @@ ata_kauai_probe(device_t dev)
if (!found)
return (ENXIO);
- node = ofw_pci_find_node(dev);
+ node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
bzero(sc, sizeof(struct ata_kauai_softc));
ch = &sc->sc_ch.sc_ch;
- OF_getprop_alloc(node, "compatible", 1, (void **)&compatstring);
- if (strcmp(compatstring,"shasta-ata") == 0)
+ compatstring = ofw_bus_get_compat(dev);
+ if (compatstring != NULL && strcmp(compatstring,"shasta-ata") == 0)
sc->shasta = 1;
- free(compatstring, M_OFWPROP);
-
-
- /*
- * This device seems to ignore writes to the interrupt
- * config register, resulting in interrupt resources
- * not being attached. If this is the case, use
- * Open Firmware to determine the irq, and then attach
- * the resource. This allows the ATA common code to
- * allocate the irq.
- */
- status = bus_get_resource(dev, SYS_RES_IRQ, 0, &startp, &countp);
- if (status == ENOENT) {
- int *irq;
- phandle_t iparent;
- int icells, nintr, i;
-
- /*
- * Horrible hack to handle Kauai devices that have their IRQs
- * set up in an utterly wrong way
- */
- if (!sc->shasta)
- bus_set_resource(dev, SYS_RES_IRQ, 0, 39, 1);
-
- /*
- * For the rest of the interrupts, and the main Shasta
- * interrupt, get the IRQs from firmware.
- */
- if (OF_getprop(node, "interrupt-parent", &iparent,
- sizeof(iparent)) == sizeof(iparent)) {
- OF_getprop(iparent, "#interrupt-cells", &icells,
- sizeof(icells)) ;
- }
-
- nintr = OF_getprop_alloc(node, "interrupts", sizeof(*irq),
- (void **)&irq);
-
- for (i = 0; i < nintr; i += icells)
- bus_set_resource(dev, SYS_RES_IRQ,
- i/icells + !sc->shasta, irq[i], 1);
-
- free(irq, M_OFWPROP);
- }
-
+ /* Regular Kauai controllers apparently need this hack */
+ if (!sc->shasta)
+ bus_set_resource(dev, SYS_RES_IRQ, 0, 39, 1);
rid = PCIR_BARS;
sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
diff --git a/sys/powerpc/powermac/grackle.c b/sys/powerpc/powermac/grackle.c
index b40b77e..08e14ac 100644
--- a/sys/powerpc/powermac/grackle.c
+++ b/sys/powerpc/powermac/grackle.c
@@ -36,19 +36,18 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <machine/bus.h>
#include <machine/md_var.h>
-#include <machine/nexusvar.h>
#include <machine/pio.h>
#include <machine/resource.h>
#include <sys/rman.h>
-#include <powerpc/ofw/ofw_pci.h>
#include <powerpc/powermac/gracklevar.h>
#include <vm/vm.h>
@@ -92,6 +91,11 @@ static void grackle_write_config(device_t, u_int, u_int, u_int,
static int grackle_route_interrupt(device_t, device_t, int);
/*
+ * ofw_bus interface
+ */
+static phandle_t grackle_get_node(device_t bus, device_t dev);
+
+/*
* Local routines.
*/
static int grackle_enable_config(struct grackle_softc *, u_int,
@@ -122,6 +126,9 @@ static device_method_t grackle_methods[] = {
DEVMETHOD(pcib_write_config, grackle_write_config),
DEVMETHOD(pcib_route_interrupt, grackle_route_interrupt),
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, grackle_get_node),
+
{ 0, 0 }
};
@@ -138,10 +145,10 @@ DRIVER_MODULE(grackle, nexus, grackle_driver, grackle_devclass, 0, 0);
static int
grackle_probe(device_t dev)
{
- char *type, *compatible;
+ const char *type, *compatible;
- type = nexus_get_device_type(dev);
- compatible = nexus_get_compatible(dev);
+ type = ofw_bus_get_type(dev);
+ compatible = ofw_bus_get_compat(dev);
if (type == NULL || compatible == NULL)
return (ENXIO);
@@ -162,7 +169,7 @@ grackle_attach(device_t dev)
struct grackle_range *rp, *io, *mem[2];
int nmem, i, error;
- node = nexus_get_node(dev);
+ node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
@@ -244,12 +251,6 @@ grackle_attach(device_t dev)
}
}
- /*
- * Write out the correct PIC interrupt values to config space
- * of all devices on the bus.
- */
- ofw_pci_fixup(dev, sc->sc_bus, sc->sc_node);
-
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -511,6 +512,17 @@ grackle_disable_config(struct grackle_softc *sc)
out32rb(sc->sc_addr, 0);
}
+static phandle_t
+grackle_get_node(device_t bus, device_t dev)
+{
+ struct grackle_softc *sc;
+
+ sc = device_get_softc(bus);
+ /* We only have one child, the PCI bus, which needs our own node. */
+
+ return sc->sc_node;
+}
+
/*
* Driver to swallow Grackle host bridges from the PCI bus side.
*/
diff --git a/sys/powerpc/powermac/hrowpic.c b/sys/powerpc/powermac/hrowpic.c
index 59bb82b..2ed0aa3 100644
--- a/sys/powerpc/powermac/hrowpic.c
+++ b/sys/powerpc/powermac/hrowpic.c
@@ -48,7 +48,6 @@
#include <machine/intr.h>
#include <machine/intr_machdep.h>
#include <machine/md_var.h>
-#include <machine/nexusvar.h>
#include <machine/pio.h>
#include <machine/resource.h>
diff --git a/sys/powerpc/powermac/macio.c b/sys/powerpc/powermac/macio.c
index 9618234..b0f04e0 100644
--- a/sys/powerpc/powermac/macio.c
+++ b/sys/powerpc/powermac/macio.c
@@ -139,6 +139,8 @@ static struct macio_pci_dev {
{ 0x0022106b, "KeyLargo I/O Controller" },
{ 0x0025106b, "Pangea I/O Controller" },
{ 0x003e106b, "Intrepid I/O Controller" },
+ { 0x0041106b, "K2 KeyLargo I/O Controller" },
+ { 0x004f106b, "Shasta I/O Controller" },
{ 0, NULL }
};
@@ -270,7 +272,7 @@ macio_attach(device_t dev)
int error, quirks;
sc = device_get_softc(dev);
- root = sc->sc_node = OF_finddevice("mac-io");
+ root = sc->sc_node = ofw_bus_get_node(dev);
/*
* Locate the device node and it's base address
diff --git a/sys/powerpc/powermac/openpic_macio.c b/sys/powerpc/powermac/openpic_macio.c
index 49d935a..ca7f113 100644
--- a/sys/powerpc/powermac/openpic_macio.c
+++ b/sys/powerpc/powermac/openpic_macio.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/intr_machdep.h>
#include <machine/md_var.h>
-#include <machine/nexusvar.h>
#include <machine/pio.h>
#include <machine/resource.h>
diff --git a/sys/powerpc/powermac/uninorth.c b/sys/powerpc/powermac/uninorth.c
index fc5105b..097532c 100644
--- a/sys/powerpc/powermac/uninorth.c
+++ b/sys/powerpc/powermac/uninorth.c
@@ -34,19 +34,18 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <machine/bus.h>
#include <machine/md_var.h>
-#include <machine/nexusvar.h>
#include <machine/pio.h>
#include <machine/resource.h>
#include <sys/rman.h>
-#include <powerpc/ofw/ofw_pci.h>
#include <powerpc/powermac/uninorthvar.h>
#include <vm/vm.h>
@@ -84,6 +83,12 @@ static void uninorth_write_config(device_t, u_int, u_int, u_int,
static int uninorth_route_interrupt(device_t, device_t, int);
/*
+ * OFW Bus interface
+ */
+
+static phandle_t uninorth_get_node(device_t bus, device_t dev);
+
+/*
* Local routines.
*/
static int uninorth_enable_config(struct uninorth_softc *, u_int,
@@ -112,6 +117,9 @@ static device_method_t uninorth_methods[] = {
DEVMETHOD(pcib_write_config, uninorth_write_config),
DEVMETHOD(pcib_route_interrupt, uninorth_route_interrupt),
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, uninorth_get_node),
+
{ 0, 0 }
};
@@ -128,32 +136,40 @@ DRIVER_MODULE(uninorth, nexus, uninorth_driver, uninorth_devclass, 0, 0);
static int
uninorth_probe(device_t dev)
{
- char *type, *compatible;
+ const char *type, *compatible;
- type = nexus_get_device_type(dev);
- compatible = nexus_get_compatible(dev);
+ type = ofw_bus_get_type(dev);
+ compatible = ofw_bus_get_compat(dev);
if (type == NULL || compatible == NULL)
return (ENXIO);
- if (strcmp(type, "pci") != 0 || strcmp(compatible, "uni-north") != 0)
+ if (strcmp(type, "pci") != 0)
return (ENXIO);
- device_set_desc(dev, "Apple UniNorth Host-PCI bridge");
- return (0);
+ if (strcmp(compatible, "uni-north") == 0) {
+ device_set_desc(dev, "Apple UniNorth Host-PCI bridge");
+ return (0);
+ } else if (strcmp(compatible,"u3-agp") == 0) {
+ device_set_desc(dev, "Apple U3 Host-AGP bridge");
+ return (0);
+ }
+
+ return (ENXIO);
}
static int
uninorth_attach(device_t dev)
{
struct uninorth_softc *sc;
+ const char *compatible;
phandle_t node;
phandle_t child;
u_int32_t reg[2], busrange[2];
struct uninorth_range *rp, *io, *mem[2];
int nmem, i, error;
- node = nexus_get_node(dev);
+ node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8)
@@ -162,15 +178,48 @@ uninorth_attach(device_t dev)
if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
return (ENXIO);
+ sc->sc_u3 = 0;
+ compatible = ofw_bus_get_compat(dev);
+ if (strcmp(compatible,"u3-agp") == 0)
+ sc->sc_u3 = 1;
+
sc->sc_dev = dev;
sc->sc_node = node;
- sc->sc_addr = (vm_offset_t)pmap_mapdev(reg[0] + 0x800000, PAGE_SIZE);
- sc->sc_data = (vm_offset_t)pmap_mapdev(reg[0] + 0xc00000, PAGE_SIZE);
+ if (sc->sc_u3) {
+ sc->sc_addr = (vm_offset_t)pmap_mapdev(reg[1] + 0x800000, PAGE_SIZE);
+ sc->sc_data = (vm_offset_t)pmap_mapdev(reg[1] + 0xc00000, PAGE_SIZE);
+ } else {
+ sc->sc_addr = (vm_offset_t)pmap_mapdev(reg[0] + 0x800000, PAGE_SIZE);
+ sc->sc_data = (vm_offset_t)pmap_mapdev(reg[0] + 0xc00000, PAGE_SIZE);
+ }
sc->sc_bus = busrange[0];
bzero(sc->sc_range, sizeof(sc->sc_range));
- sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range,
- sizeof(sc->sc_range));
+ if (sc->sc_u3) {
+ /*
+ * On Apple U3 systems, we have an otherwise standard
+ * Uninorth controller driving AGP. The one difference
+ * is that it uses a new PCI ranges format, so do the
+ * translation.
+ */
+
+ struct uninorth_range64 range64[6];
+ bzero(range64, sizeof(range64));
+
+ sc->sc_nrange = OF_getprop(node, "ranges", range64,
+ sizeof(range64));
+ for (i = 0; range64[i].pci_hi != 0; i++) {
+ sc->sc_range[i].pci_hi = range64[i].pci_hi;
+ sc->sc_range[i].pci_mid = range64[i].pci_mid;
+ sc->sc_range[i].pci_lo = range64[i].pci_lo;
+ sc->sc_range[i].host = range64[i].host_lo;
+ sc->sc_range[i].size_hi = range64[i].size_hi;
+ sc->sc_range[i].size_lo = range64[i].size_lo;
+ }
+ } else {
+ sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range,
+ sizeof(sc->sc_range));
+ }
if (sc->sc_nrange == -1) {
device_printf(dev, "could not get ranges\n");
@@ -245,13 +294,6 @@ uninorth_attach(device_t dev)
}
}
- /*
- * Write out the correct PIC interrupt values to config space
- * of all devices on the bus. This has to be done after the GEM
- * cell is enabled above.
- */
- ofw_pci_fixup(dev, sc->sc_bus, node);
-
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -275,7 +317,7 @@ uninorth_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
if (uninorth_enable_config(sc, bus, slot, func, reg) != 0) {
switch (width) {
- case 1:
+ case 1:
return (in8rb(caoff));
break;
case 2:
@@ -467,6 +509,17 @@ uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot,
return (1);
}
+static phandle_t
+uninorth_get_node(device_t bus, device_t dev)
+{
+ struct uninorth_softc *sc;
+
+ sc = device_get_softc(bus);
+ /* We only have one child, the PCI bus, which needs our own node. */
+
+ return sc->sc_node;
+}
+
/*
* Driver to swallow UniNorth host bridges from the PCI bus side.
*/
@@ -533,9 +586,9 @@ unin_enable_gmac(void)
static int
unin_chip_probe(device_t dev)
{
- char *name;
+ const char *name;
- name = nexus_get_name(dev);
+ name = ofw_bus_get_name(dev);
if (name == NULL)
return (ENXIO);
@@ -554,7 +607,7 @@ unin_chip_attach(device_t dev)
u_int reg[2];
uncsc = device_get_softc(dev);
- node = nexus_get_node(dev);
+ node = ofw_bus_get_node(dev);
if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8)
return (ENXIO);
diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h
index d2ee8d7..ff789ac 100644
--- a/sys/powerpc/powermac/uninorthvar.h
+++ b/sys/powerpc/powermac/uninorthvar.h
@@ -37,6 +37,16 @@ struct uninorth_range {
u_int32_t size_lo;
};
+struct uninorth_range64 {
+ u_int32_t pci_hi;
+ u_int32_t pci_mid;
+ u_int32_t pci_lo;
+ u_int32_t host_hi;
+ u_int32_t host_lo;
+ u_int32_t size_hi;
+ u_int32_t size_lo;
+};
+
struct uninorth_softc {
device_t sc_dev;
phandle_t sc_node;
@@ -51,6 +61,8 @@ struct uninorth_softc {
bus_space_tag_t sc_iot;
bus_space_tag_t sc_memt;
bus_dma_tag_t sc_dmat;
+
+ int sc_u3;
};
struct unin_chip_softc {
OpenPOWER on IntegriCloud