summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-09-06 20:09:35 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-09-06 20:09:35 +0000
commit2fd91aac38ea3f6322903b6921b4b83d15b292a9 (patch)
treefcff737b4795e5428b2fd74fbc4d830a17f804bd
parent530de8f9420591168bf062e320611b45167f642a (diff)
Attach devices to obio(4) based on information from the flattened device
tree. Since that information is also used for the PCI interrupts, devices in mini-PCI slots should work now as well, at least in the rb600.
-rw-r--r--sys/arch/socppc/conf/GENERIC30
-rw-r--r--sys/arch/socppc/conf/RB60065
-rw-r--r--sys/arch/socppc/conf/files.socppc11
-rw-r--r--sys/arch/socppc/dev/com_obio.c24
-rw-r--r--sys/arch/socppc/dev/ehci_obio.c11
-rw-r--r--sys/arch/socppc/dev/if_tsec.c51
-rw-r--r--sys/arch/socppc/dev/ipic.c73
-rw-r--r--sys/arch/socppc/dev/obio.c49
-rw-r--r--sys/arch/socppc/dev/sociic.c11
-rw-r--r--sys/arch/socppc/dev/socpcic.c158
-rw-r--r--sys/arch/socppc/dev/wdc_mainbus.c (renamed from sys/arch/socppc/dev/wdc_obio.c)84
11 files changed, 393 insertions, 174 deletions
diff --git a/sys/arch/socppc/conf/GENERIC b/sys/arch/socppc/conf/GENERIC
index b15a912ced1..b8efe4d471c 100644
--- a/sys/arch/socppc/conf/GENERIC
+++ b/sys/arch/socppc/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.11 2009/05/31 20:43:44 maja Exp $
+# $OpenBSD: GENERIC,v 1.12 2009/09/06 20:09:34 kettenis Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -25,30 +25,37 @@ mainbus0 at root
cpu0 at mainbus0
obio0 at mainbus0
+# On-board CF
+wdc0 at mainbus0
+wdc1 at mainbus0
+wd* at wdc? flags 0x0000
+
# On-board IPIC
-ipic0 at obio? addr 0x00700
+ipic0 at obio?
# On-board I2C
-sociic0 at obio? addr 0x03000 ivec 14
-sociic1 at obio? addr 0x03100 ivec 15
+sociic0 at obio?
+sociic1 at obio?
iic* at sociic?
ricohrtc0 at iic? addr 0x32 # Ricoh RTC
fintek0 at iic? flags 0x0001 # temp/fan controller
# On-board DUART
-com0 at obio? addr 0x04500 ivec 9
-com1 at obio? addr 0x04600 ivec 10
+com0 at obio?
+com1 at obio?
# On-board PCI
-socpcic0 at obio? addr 0x08300
-socpcic1 at obio? addr 0x08380
+socpcic* at mainbus?
+socpcic* at obio?
pci* at socpcic?
pciide* at pci?
wd* at pciide? flags 0x0000
+vge* at pci?
+
# On-board USB
-ehci0 at obio? addr 0x22100 ivec 39
+ehci0 at obio?
usb* at ehci?
# USB devices
@@ -76,12 +83,13 @@ wsdisplay* at udl?
sd* at scsibus?
# On-board TSEC
-tsec0 at obio? addr 0x24000 ivec 32 phy 17
-tsec1 at obio? addr 0x25000 ivec 35 phy 5
+tsec0 at obio?
+tsec1 at obio?
rgephy* at mii? # Realtek 8169S/8110S PHY
eephy* at mii? # Marvell 88E1000 series PHY
rlphy* at mii? # RealTek 8139 internal PHYs
+ciphy* at mii? # Cicada CS8201 10/100/1000 copper PHY
gentbi* at mii? # Generic 1000BASE-X ten-bit PHY
ukphy* at mii? # Generic unknown PHY
diff --git a/sys/arch/socppc/conf/RB600 b/sys/arch/socppc/conf/RB600
deleted file mode 100644
index 940ec6e0913..00000000000
--- a/sys/arch/socppc/conf/RB600
+++ /dev/null
@@ -1,65 +0,0 @@
-# $OpenBSD: RB600,v 1.1 2009/08/26 20:54:53 kettenis Exp $
-#
-# For further information on compiling OpenBSD kernels, see the config(8)
-# man page.
-#
-# For further information on hardware support for this architecture, see
-# the intro(4) man page. For further information about kernel options
-# for this architecture, see the options(4) man page. For an explanation
-# of each device driver in this file see the section 4 man page for the
-# device.
-
-machine socppc powerpc
-include "../../../conf/GENERIC"
-maxusers 32 # estimated number of users
-
-option RB600
-
-option PCIVERBOSE
-option USBVERBOSE
-
-option USER_PCICONF # user-space PCI configuration
-option APERTURE
-
-config bsd swap generic
-
-mainbus0 at root
-cpu0 at mainbus0
-obio0 at mainbus0
-
-# On-board IPIC
-ipic0 at obio? addr 0x00700
-
-# On-board I2C
-sociic0 at obio? addr 0x03000 ivec 14
-sociic1 at obio? addr 0x03100 ivec 15
-iic* at sociic?
-
-# On-board DUART
-com0 at obio? addr 0x04500 ivec 9
-com1 at obio? addr 0x04600 ivec 10
-
-# On-board CF
-wdc0 at obio? addr 0xf9000000 ivec 20
-wdc1 at obio? addr 0xf9200000 ivec 22
-wd* at wdc? flags 0x0000
-
-# On-board PCI
-socpcic0 at obio? addr 0x08300
-pci* at socpcic?
-
-vge* at pci?
-
-# On-board TSEC
-tsec0 at obio? addr 0x24000 ivec 32 phy 1
-tsec1 at obio? addr 0x25000 ivec 35 phy 0
-
-rgephy* at mii? # Realtek 8169S/8110S PHY
-eephy* at mii? # Marvell 88E1000 series PHY
-rlphy* at mii? # RealTek 8139 internal PHYs
-ciphy* at mii? # Cicada CS8201 10/100/1000 copper PHY
-gentbi* at mii? # Generic 1000BASE-X ten-bit PHY
-ukphy* at mii? # Generic unknown PHY
-
-# mouse & keyboard multiplexor pseudo-devices
-pseudo-device wsmux 2
diff --git a/sys/arch/socppc/conf/files.socppc b/sys/arch/socppc/conf/files.socppc
index 02cfc1359b2..8161d122a2f 100644
--- a/sys/arch/socppc/conf/files.socppc
+++ b/sys/arch/socppc/conf/files.socppc
@@ -1,4 +1,4 @@
-# $OpenBSD: files.socppc,v 1.8 2009/08/30 14:57:41 kettenis Exp $
+# $OpenBSD: files.socppc,v 1.9 2009/09/06 20:09:34 kettenis Exp $
#
# macppc-specific configuration info
@@ -30,7 +30,7 @@ attach cpu at mainbus
file arch/socppc/socppc/cpu.c
# MPC8349E on-board devices
-device obio {addr, [ivec = -1], [phy = -1]}
+device obio {[addr = 0], [ivec = -1], [phy = -1]}
attach obio at mainbus
file arch/socppc/dev/obio.c
@@ -49,8 +49,8 @@ attach com at obio with com_obio
file arch/socppc/dev/com_obio.c
# On-board CF
-attach wdc at obio with wdc_obio
-file arch/socppc/dev/wdc_obio.c
+attach wdc at mainbus with wdc_mainbus
+file arch/socppc/dev/wdc_mainbus.c
#
# Media Independent Interface (mii)
@@ -79,7 +79,8 @@ file arch/socppc/dev/pciide_machdep.c pciide
# On-board PCI
device socpcic: pcibus
-attach socpcic at obio
+attach socpcic at mainbus with socpcic_mainbus
+attach socpcic at obio with socpcic_obio
file arch/socppc/dev/socpcic.c
#
diff --git a/sys/arch/socppc/dev/com_obio.c b/sys/arch/socppc/dev/com_obio.c
index 3b1bb2351ec..9cf656754be 100644
--- a/sys/arch/socppc/dev/com_obio.c
+++ b/sys/arch/socppc/dev/com_obio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com_obio.c,v 1.2 2009/08/26 17:47:51 kettenis Exp $ */
+/* $OpenBSD: com_obio.c,v 1.3 2009/09/06 20:09:34 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -23,6 +23,8 @@
#include <machine/autoconf.h>
+#include <dev/ofw/openfirm.h>
+
#include <dev/ic/comreg.h>
#include <dev/ic/comvar.h>
@@ -40,6 +42,17 @@ struct cfdriver com_obio_cd = {
int
com_obio_match(struct device *parent, void *cfdata, void *aux)
{
+ struct obio_attach_args *oa = aux;
+ char buf[32];
+
+ if (OF_getprop(oa->oa_node, "device_type", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "serial") != 0)
+ return (0);
+
+ if (OF_getprop(oa->oa_node, "compatible", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "ns16550") != 0)
+ return (0);
+
return (1);
}
@@ -48,10 +61,17 @@ com_obio_attach(struct device *parent, struct device *self, void *aux)
{
struct com_softc *sc = (void *)self;
struct obio_attach_args *oa = aux;
+ int freq;
+
+ if (OF_getprop(oa->oa_node, "clock-frequency", &freq,
+ sizeof(freq))!= sizeof(freq)) {
+ printf(": unknown clock frequency\n");
+ return;
+ }
sc->sc_iot = oa->oa_iot;
sc->sc_iobase = oa->oa_offset;
- sc->sc_frequency = comconsfreq; /* XXX */
+ sc->sc_frequency = freq;
if (sc->sc_iobase != comconsaddr) {
if (bus_space_map(sc->sc_iot, sc->sc_iobase,
diff --git a/sys/arch/socppc/dev/ehci_obio.c b/sys/arch/socppc/dev/ehci_obio.c
index 93039e45533..b127650daec 100644
--- a/sys/arch/socppc/dev/ehci_obio.c
+++ b/sys/arch/socppc/dev/ehci_obio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehci_obio.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */
+/* $OpenBSD: ehci_obio.c,v 1.2 2009/09/06 20:09:34 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -24,6 +24,8 @@
#include <machine/autoconf.h>
+#include <dev/ofw/openfirm.h>
+
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
@@ -65,6 +67,13 @@ struct powerpc_bus_dma_tag ehci_bus_dma_tag = {
int
ehci_obio_match(struct device *parent, void *cfdata, void *aux)
{
+ struct obio_attach_args *oa = aux;
+ char buf[32];
+
+ if (OF_getprop(oa->oa_node, "compatible", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "fsl-usb2-mph") != 0)
+ return (0);
+
return (1);
}
diff --git a/sys/arch/socppc/dev/if_tsec.c b/sys/arch/socppc/dev/if_tsec.c
index edc396c0453..edbd6f1e5fb 100644
--- a/sys/arch/socppc/dev/if_tsec.c
+++ b/sys/arch/socppc/dev/if_tsec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tsec.c,v 1.25 2009/08/27 20:41:35 miod Exp $ */
+/* $OpenBSD: if_tsec.c,v 1.26 2009/09/06 20:09:34 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -40,6 +40,8 @@
#include <net/if_media.h>
#include <net/if_types.h>
+#include <dev/ofw/openfirm.h>
+
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
@@ -283,6 +285,8 @@ struct cfdriver tsec_cd = {
NULL, "tsec", DV_IFNET
};
+int tsec_find_phy(int, int);
+
uint32_t tsec_read(struct tsec_softc *, bus_addr_t);
void tsec_write(struct tsec_softc *, bus_addr_t, uint32_t);
@@ -325,6 +329,17 @@ void tsec_fill_rx_ring(struct tsec_softc *);
int
tsec_match(struct device *parent, void *cfdata, void *aux)
{
+ struct obio_attach_args *oa = aux;
+ char buf[32];
+
+ if (OF_getprop(oa->oa_node, "device_type", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "network") != 0)
+ return (0);
+
+ if (OF_getprop(oa->oa_node, "compatible", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "gianfar") != 0)
+ return (0);
+
return (1);
}
@@ -334,7 +349,21 @@ tsec_attach(struct device *parent, struct device *self, void *aux)
struct tsec_softc *sc = (void *)self;
struct obio_attach_args *oa = aux;
struct ifnet *ifp;
- int n;
+ int phy, n;
+
+ if (OF_getprop(oa->oa_node, "phy-handle", &phy,
+ sizeof(phy)) == sizeof(phy)) {
+ int node, reg;
+
+ node = tsec_find_phy(OF_peer(0), phy);
+ if (node == -1 || OF_getprop(node, "reg", &reg,
+ sizeof(reg)) != sizeof(reg)) {
+ printf(": can't find PHY\n");
+ return;
+ }
+
+ oa->oa_phy = reg;
+ }
sc->sc_iot = oa->oa_iot;
if (bus_space_map(sc->sc_iot, oa->oa_offset, 3072, 0, &sc->sc_ioh)) {
@@ -400,6 +429,24 @@ tsec_attach(struct device *parent, struct device *self, void *aux)
sc->sc_dev.dv_xname);
}
+int
+tsec_find_phy(int node, int phy)
+{
+ int child, handle;
+
+ if (OF_getprop(node, "linux,phandle", &handle,
+ sizeof(handle)) == sizeof(handle) && phy == handle)
+ return (node);
+
+ for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+ node = tsec_find_phy(child, phy);
+ if (node != -1)
+ return node;
+ }
+
+ return (-1);
+}
+
uint32_t
tsec_read(struct tsec_softc *sc, bus_addr_t addr)
{
diff --git a/sys/arch/socppc/dev/ipic.c b/sys/arch/socppc/dev/ipic.c
index 3512297db75..0bfec255649 100644
--- a/sys/arch/socppc/dev/ipic.c
+++ b/sys/arch/socppc/dev/ipic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipic.c,v 1.8 2009/06/09 01:12:38 deraadt Exp $ */
+/* $OpenBSD: ipic.c,v 1.9 2009/09/06 20:09:34 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -24,6 +24,8 @@
#include <machine/autoconf.h>
#include <machine/intr.h>
+#include <dev/ofw/openfirm.h>
+
#define IPIC_SICFR 0x00
#define IPIC_SIVCR 0x04
#define IPIC_SIPNR_H 0x08
@@ -83,12 +85,20 @@ uint32_t ipic_simsr_h(int);
uint32_t ipic_simsr_l(int);
uint32_t ipic_semsr(int);
+void intr_calculatemasks(void);
void ext_intr(void);
void ipic_do_pending_int(void);
int
ipic_match(struct device *parent, void *cfdata, void *aux)
{
+ struct obio_attach_args *oa = aux;
+ char buf[32];
+
+ if (OF_getprop(oa->oa_node, "device_type", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "ipic") != 0)
+ return (0);
+
return (1);
}
@@ -97,6 +107,7 @@ ipic_attach(struct device *parent, struct device *self, void *aux)
{
struct ipic_softc *sc = (void *)self;
struct obio_attach_args *oa = aux;
+ int ivec;
sc->sc_iot = oa->oa_iot;
if (bus_space_map(sc->sc_iot, oa->oa_offset, 128, 0, &sc->sc_ioh)) {
@@ -104,6 +115,32 @@ ipic_attach(struct device *parent, struct device *self, void *aux)
return;
}
+ /*
+ * Deal with pre-established interrupts.
+ */
+ for (ivec = 0; ivec < IPIC_NVEC; ivec++) {
+ if (ipic_intrhand[ivec]) {
+ int level = ipic_intrhand[ivec]->ih_level;
+ uint32_t mask;
+
+ sc->sc_simsr_h[level] |= ipic_simsr_h(ivec);
+ sc->sc_simsr_l[level] |= ipic_simsr_l(ivec);
+ sc->sc_semsr[level] |= ipic_semsr(ivec);
+ intr_calculatemasks();
+
+ /* Unmask the interrupt. */
+ mask = ipic_read(sc, IPIC_SIMSR_H);
+ mask |= ipic_simsr_h(ivec);
+ ipic_write(sc, IPIC_SIMSR_H, mask);
+ mask = ipic_read(sc, IPIC_SIMSR_L);
+ mask |= ipic_simsr_l(ivec);
+ ipic_write(sc, IPIC_SIMSR_L, mask);
+ mask = ipic_read(sc, IPIC_SEMSR);
+ mask |= ipic_semsr(ivec);
+ ipic_write(sc, IPIC_SEMSR, mask);
+ }
+ }
+
ipic_sc = sc;
printf("\n");
}
@@ -176,7 +213,7 @@ ipic_semsr(int ivec)
return 0;
}
-static void
+void
intr_calculatemasks(void)
{
struct ipic_softc *sc = ipic_sc;
@@ -240,10 +277,12 @@ intr_establish(int ivec, int type, int level,
for (p = &ipic_intrhand[ivec]; (q = *p) != NULL; p = &q->ih_next)
;
- sc->sc_simsr_h[level] |= ipic_simsr_h(ivec);
- sc->sc_simsr_l[level] |= ipic_simsr_l(ivec);
- sc->sc_semsr[level] |= ipic_semsr(ivec);
- intr_calculatemasks();
+ if (sc) {
+ sc->sc_simsr_h[level] |= ipic_simsr_h(ivec);
+ sc->sc_simsr_l[level] |= ipic_simsr_l(ivec);
+ sc->sc_semsr[level] |= ipic_semsr(ivec);
+ intr_calculatemasks();
+ }
ih->ih_fun = ih_fun;
ih->ih_arg = ih_arg;
@@ -253,16 +292,18 @@ intr_establish(int ivec, int type, int level,
evcount_attach(&ih->ih_count, name, NULL, &evcount_intr);
*p = ih;
- /* Unmask the interrupt. */
- mask = ipic_read(sc, IPIC_SIMSR_H);
- mask |= ipic_simsr_h(ivec);
- ipic_write(sc, IPIC_SIMSR_H, mask);
- mask = ipic_read(sc, IPIC_SIMSR_L);
- mask |= ipic_simsr_l(ivec);
- ipic_write(sc, IPIC_SIMSR_L, mask);
- mask = ipic_read(sc, IPIC_SEMSR);
- mask |= ipic_semsr(ivec);
- ipic_write(sc, IPIC_SEMSR, mask);
+ if (sc) {
+ /* Unmask the interrupt. */
+ mask = ipic_read(sc, IPIC_SIMSR_H);
+ mask |= ipic_simsr_h(ivec);
+ ipic_write(sc, IPIC_SIMSR_H, mask);
+ mask = ipic_read(sc, IPIC_SIMSR_L);
+ mask |= ipic_simsr_l(ivec);
+ ipic_write(sc, IPIC_SIMSR_L, mask);
+ mask = ipic_read(sc, IPIC_SEMSR);
+ mask |= ipic_semsr(ivec);
+ ipic_write(sc, IPIC_SEMSR, mask);
+ }
return (ih);
}
diff --git a/sys/arch/socppc/dev/obio.c b/sys/arch/socppc/dev/obio.c
index 78f0820e21c..7aa64c24b7c 100644
--- a/sys/arch/socppc/dev/obio.c
+++ b/sys/arch/socppc/dev/obio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: obio.c,v 1.4 2009/09/02 20:29:39 kettenis Exp $ */
+/* $OpenBSD: obio.c,v 1.5 2009/09/06 20:09:34 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -35,7 +35,6 @@ struct cfdriver obio_cd = {
NULL, "obio", DV_DULL
};
-int obio_search(struct device *, void *, void *);
int obio_print(void *, const char *);
int
@@ -56,28 +55,34 @@ obio_match(struct device *parent, void *cfdata, void *aux)
void
obio_attach(struct device *parent, struct device *self, void *aux)
{
+ struct mainbus_attach_args *ma = aux;
+ struct obio_attach_args oa;
+ char name[32];
+ int node;
+
printf("\n");
- config_search(obio_search, self, aux);
-}
+ for (node = OF_child(ma->ma_node); node != 0; node = OF_peer(node)) {
+ int reg, ivec;
-int
-obio_search(struct device *parent, void *cfdata, void *aux)
-{
- struct mainbus_attach_args *ma = aux;
- struct obio_attach_args oa;
- struct cfdata *cf = cfdata;
-
- bzero(&oa, sizeof oa);
- oa.oa_iot = ma->ma_iot;
- oa.oa_dmat = ma->ma_dmat;
- oa.oa_offset = cf->cf_offset;
- oa.oa_ivec = cf->cf_ivec;
- oa.oa_phy = cf->cf_phy;
- oa.oa_name = cf->cf_driver->cd_name;
- config_found(parent, &oa, obio_print);
-
- return (1);
+ if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
+ continue;
+
+ if (OF_getprop(node, "reg", &reg, sizeof(reg)) <= 0)
+ reg = 0;
+
+ if (OF_getprop(node, "interrupts", &ivec, sizeof(ivec)) <= 0)
+ ivec = -1;
+
+ bzero(&oa, sizeof oa);
+ oa.oa_iot = ma->ma_iot;
+ oa.oa_dmat = ma->ma_dmat;
+ oa.oa_name = name;
+ oa.oa_node = node;
+ oa.oa_offset = reg;
+ oa.oa_ivec = ivec;
+ config_found(self, &oa, obio_print);
+ }
}
int
@@ -86,7 +91,7 @@ obio_print(void *aux, const char *name)
struct obio_attach_args *oa = aux;
if (name)
- printf("%s at %s", oa->oa_name, name);
+ printf("\"%s\" at %s", oa->oa_name, name);
if (oa->oa_offset)
printf(" offset 0x%05x", oa->oa_offset);
if (oa->oa_ivec != -1)
diff --git a/sys/arch/socppc/dev/sociic.c b/sys/arch/socppc/dev/sociic.c
index b35c0397963..36d41c2dadd 100644
--- a/sys/arch/socppc/dev/sociic.c
+++ b/sys/arch/socppc/dev/sociic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sociic.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $OpenBSD: sociic.c,v 1.2 2009/09/06 20:09:34 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -28,6 +28,8 @@
#include <machine/autoconf.h>
#include <machine/bus.h>
+#include <dev/ofw/openfirm.h>
+
#include <dev/i2c/i2cvar.h>
#define I2C_ADR 0x00 /* Address Register */
@@ -84,6 +86,13 @@ int sociic_i2c_exec(void *, i2c_op_t, i2c_addr_t,
int
sociic_match(struct device *parent, void *cfdata, void *aux)
{
+ struct obio_attach_args *oa = aux;
+ char buf[32];
+
+ if (OF_getprop(oa->oa_node, "compatible", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "fsl-i2c") != 0)
+ return (0);
+
return (1);
}
diff --git a/sys/arch/socppc/dev/socpcic.c b/sys/arch/socppc/dev/socpcic.c
index 6207b6143c6..00f6507d2e0 100644
--- a/sys/arch/socppc/dev/socpcic.c
+++ b/sys/arch/socppc/dev/socpcic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: socpcic.c,v 1.6 2009/08/26 20:53:51 kettenis Exp $ */
+/* $OpenBSD: socpcic.c,v 1.7 2009/09/06 20:09:34 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -23,30 +23,50 @@
#include <machine/autoconf.h>
#include <machine/bus.h>
+#include <dev/ofw/openfirm.h>
+
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
struct socpcic_softc {
struct device sc_dev;
+
+ int sc_node;
+
bus_space_tag_t sc_iot;
bus_space_handle_t sc_cfg_ioh;
struct ppc_bus_space sc_mem_bus_space;
struct ppc_bus_space sc_io_bus_space;
+ bus_dma_tag_t sc_dmat;
struct ppc_pci_chipset sc_pc;
+
+ /* Interrupt mapping. */
+ int sc_map_mask[4];
+ int *sc_map;
+ int sc_map_len;
};
-int socpcic_match(struct device *, void *, void *);
-void socpcic_attach(struct device *, struct device *, void *);
+int socpcic_mainbus_match(struct device *, void *, void *);
+void socpcic_mainbus_attach(struct device *, struct device *, void *);
+int socpcic_obio_match(struct device *, void *, void *);
+void socpcic_obio_attach(struct device *, struct device *, void *);
-struct cfattach socpcic_ca = {
- sizeof(struct socpcic_softc), socpcic_match, socpcic_attach
+struct cfattach socpcic_mainbus_ca = {
+ sizeof(struct socpcic_softc),
+ socpcic_mainbus_match, socpcic_mainbus_attach
+};
+
+struct cfattach socpcic_obio_ca = {
+ sizeof(struct socpcic_softc),
+ socpcic_obio_match, socpcic_obio_attach
};
struct cfdriver socpcic_cd = {
NULL, "socpcic", DV_DULL
};
+void socpcic_attach(struct socpcic_softc *sc);
void socpcic_attach_hook(struct device *, struct device *,
struct pcibus_attach_args *);
int socpcic_bus_maxdevs(void *, int);
@@ -65,19 +85,70 @@ int socpcic_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *);
int socpcic_print(void *, const char *);
int
-socpcic_match(struct device *parent, void *cfdata, void *aux)
+socpcic_mainbus_match(struct device *parent, void *cfdata, void *aux)
{
+ struct mainbus_attach_args *ma = aux;
+ char buf[32];
+
+ if (OF_getprop(ma->ma_node, "device_type", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "pci") != 0)
+ return (0);
+
+ if (OF_getprop(ma->ma_node, "compatible", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "fsl,mpc8349-pci") != 0)
+ return (0);
+
return (1);
}
void
-socpcic_attach(struct device *parent, struct device *self, void *aux)
+socpcic_mainbus_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct socpcic_softc *sc = (void *)self;
+ struct mainbus_attach_args *ma = aux;
+ int reg[4];
+
+ if (OF_getprop(ma->ma_node, "reg", &reg, sizeof(reg)) < sizeof(reg)) {
+ printf(": missing registers\n");
+ return;
+ }
+
+ sc->sc_iot = ma->ma_iot;
+ if (bus_space_map(sc->sc_iot, reg[2], 16, 0, &sc->sc_cfg_ioh)) {
+ printf(": can't map configuration registers\n");
+ return;
+ }
+
+ sc->sc_node = ma->ma_node;
+ sc->sc_dmat = ma->ma_dmat;
+ socpcic_attach(sc);
+}
+
+int
+socpcic_obio_match(struct device *parent, void *cfdata, void *aux)
+{
+ struct obio_attach_args *oa = aux;
+ char buf[32];
+
+ if (OF_getprop(oa->oa_node, "device_type", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "pci") != 0)
+ return (0);
+
+ if (OF_getprop(oa->oa_node, "compatible", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "83xx") != 0)
+ return (0);
+
+ return (1);
+}
+
+void
+socpcic_obio_attach(struct device *parent, struct device *self, void *aux)
{
struct socpcic_softc *sc = (void *)self;
struct obio_attach_args *oa = aux;
- struct pcibus_attach_args pba;
- struct extent *io_ex;
- struct extent *mem_ex;
+
+ if (oa->oa_offset == 0x8500)
+ oa->oa_offset = 0x8300;
sc->sc_iot = oa->oa_iot;
if (bus_space_map(sc->sc_iot, oa->oa_offset, 16, 0, &sc->sc_cfg_ioh)) {
@@ -85,6 +156,36 @@ socpcic_attach(struct device *parent, struct device *self, void *aux)
return;
}
+ sc->sc_node = oa->oa_node;
+ sc->sc_dmat = oa->oa_dmat;
+ socpcic_attach(sc);
+}
+
+void
+socpcic_attach(struct socpcic_softc *sc)
+{
+ struct pcibus_attach_args pba;
+ struct extent *io_ex;
+ struct extent *mem_ex;
+ int len;
+
+ if (OF_getprop(sc->sc_node, "interrupt-map-mask", sc->sc_map_mask,
+ sizeof(sc->sc_map_mask)) != sizeof(sc->sc_map_mask)) {
+ printf(": missing interrupt-map-mask\n");
+ return;
+ }
+
+ sc->sc_map_len = OF_getproplen(sc->sc_node, "interrupt-map");
+ if (sc->sc_map_len > 0) {
+ sc->sc_map = malloc(sc->sc_map_len, M_DEVBUF, M_NOWAIT);
+ if (sc->sc_map == NULL)
+ panic("out of memory");
+
+ len = OF_getprop(sc->sc_node, "interrupt-map",
+ sc->sc_map, sc->sc_map_len);
+ KASSERT(len == sc->sc_map_len);
+ }
+
sc->sc_mem_bus_space.bus_base = 0x80000000;
sc->sc_mem_bus_space.bus_size = 0x21000000;
sc->sc_mem_bus_space.bus_io = 0;
@@ -121,7 +222,7 @@ socpcic_attach(struct device *parent, struct device *self, void *aux)
pba.pba_busname = "pci";
pba.pba_iot = &sc->sc_io_bus_space;
pba.pba_memt = &sc->sc_mem_bus_space;
- pba.pba_dmat = oa->oa_dmat;
+ pba.pba_dmat = sc->sc_dmat;
pba.pba_ioex = io_ex;
pba.pba_memex = mem_ex;
pba.pba_pc = &sc->sc_pc;
@@ -130,7 +231,7 @@ socpcic_attach(struct device *parent, struct device *self, void *aux)
printf("\n");
- config_found(self, &pba, socpcic_print);
+ config_found((struct device *)sc, &pba, socpcic_print);
}
void
@@ -214,12 +315,33 @@ int
socpcic_intr_map(void *cpv, pcitag_t tag, int pin, int line,
pci_intr_handle_t *ihp)
{
-#ifdef RB600
- *ihp = 21; /* XXX */
-#else
- *ihp = 20; /* XXX */
-#endif
- return (0);
+ struct socpcic_softc *sc = cpv;
+ int bus, dev, func;
+ int reg[4];
+ int *map;
+ int len;
+
+ pci_decompose_tag(&sc->sc_pc, tag, &bus, &dev, &func);
+
+ reg[0] = (dev << 11) | (func << 8);
+ reg[1] = reg[2] = 0;
+ reg[3] = pin;
+
+ map = sc->sc_map;
+ len = sc->sc_map_len;
+ while (len >= 7 * sizeof(int)) {
+ if ((reg[0] & sc->sc_map_mask[0]) == map[0] &&
+ (reg[1] & sc->sc_map_mask[1]) == map[1] &&
+ (reg[2] & sc->sc_map_mask[2]) == map[2] &&
+ (reg[3] & sc->sc_map_mask[3]) == map[3]) {
+ *ihp = map[5];
+ return (0);
+ }
+ len -= 7 * sizeof(int);
+ map += 7;
+ }
+
+ return (1);
}
const char *
diff --git a/sys/arch/socppc/dev/wdc_obio.c b/sys/arch/socppc/dev/wdc_mainbus.c
index 03ad5921e94..68d48d28000 100644
--- a/sys/arch/socppc/dev/wdc_obio.c
+++ b/sys/arch/socppc/dev/wdc_mainbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdc_obio.c,v 1.2 2009/08/24 17:55:01 kettenis Exp $ */
+/* $OpenBSD: wdc_mainbus.c,v 1.1 2009/09/06 20:09:34 kettenis Exp $ */
/*
* Copyright (c) 2009 Mark Kettenis
@@ -28,10 +28,12 @@
#include <machine/autoconf.h>
+#include <dev/ofw/openfirm.h>
+
#include <dev/ata/atavar.h>
#include <dev/ic/wdcvar.h>
-struct wdc_obio_softc {
+struct wdc_mainbus_softc {
struct wdc_softc sc_wdcdev;
struct channel_softc *sc_chanptr;
struct channel_softc sc_channel;
@@ -39,11 +41,11 @@ struct wdc_obio_softc {
void *sc_ih;
};
-int wdc_obio_match(struct device *, void *, void *);
-void wdc_obio_attach(struct device *, struct device *, void *);
+int wdc_mainbus_match(struct device *, void *, void *);
+void wdc_mainbus_attach(struct device *, struct device *, void *);
-struct cfattach wdc_obio_ca = {
- sizeof(struct wdc_obio_softc), wdc_obio_match, wdc_obio_attach
+struct cfattach wdc_mainbus_ca = {
+ sizeof(struct wdc_mainbus_softc), wdc_mainbus_match, wdc_mainbus_attach
};
/*
@@ -52,20 +54,20 @@ struct cfattach wdc_obio_ca = {
* LAD[11:15], which means we need to waste more than 0.5 MB of
* address space to map 10 8-bit registers.
*/
-#define WDC_OBIO_REG_NPORTS WDC_NREG
-#define WDC_OBIO_REG_SIZE (WDC_OBIO_REG_NPORTS << 16)
-#define WDC_OBIO_REG_OFFSET (8 << 17)
-#define WDC_OBIO_AUXREG_NPORTS 2
-#define WDC_OBIO_AUXREG_SIZE (WDC_OBIO_AUXREG_NPORTS << 16)
-#define WDC_OBIO_AUXREG_OFFSET (6 << 16)
-
-u_int8_t wdc_obio_read_reg(struct channel_softc *chp, enum wdc_regs reg);
-void wdc_obio_write_reg(struct channel_softc *chp, enum wdc_regs reg,
+#define WDC_MAINBUS_REG_NPORTS WDC_NREG
+#define WDC_MAINBUS_REG_SIZE (WDC_MAINBUS_REG_NPORTS << 16)
+#define WDC_MAINBUS_REG_OFFSET (8 << 17)
+#define WDC_MAINBUS_AUXREG_NPORTS 2
+#define WDC_MAINBUS_AUXREG_SIZE (WDC_MAINBUS_AUXREG_NPORTS << 16)
+#define WDC_MAINBUS_AUXREG_OFFSET (6 << 16)
+
+u_int8_t wdc_mainbus_read_reg(struct channel_softc *chp, enum wdc_regs reg);
+void wdc_mainbus_write_reg(struct channel_softc *chp, enum wdc_regs reg,
u_int8_t val);
-struct channel_softc_vtbl wdc_obio_vtbl = {
- wdc_obio_read_reg,
- wdc_obio_write_reg,
+struct channel_softc_vtbl wdc_mainbus_vtbl = {
+ wdc_mainbus_read_reg,
+ wdc_mainbus_write_reg,
wdc_default_lba48_write_reg,
wdc_default_read_raw_multi_2,
wdc_default_write_raw_multi_2,
@@ -74,33 +76,52 @@ struct channel_softc_vtbl wdc_obio_vtbl = {
};
int
-wdc_obio_match(struct device *parent, void *cfdata, void *aux)
+wdc_mainbus_match(struct device *parent, void *cfdata, void *aux)
{
+ struct mainbus_attach_args *ma = aux;
+ char buf[32];
+
+ if (OF_getprop(ma->ma_node, "device_type", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "rb,cf") != 0)
+ return (0);
+
return (1);
}
void
-wdc_obio_attach(struct device *parent, struct device *self, void *aux)
+wdc_mainbus_attach(struct device *parent, struct device *self, void *aux)
{
- struct wdc_obio_softc *sc = (void *)self;
- struct obio_attach_args *oa = aux;
+ struct wdc_mainbus_softc *sc = (void *)self;
+ struct mainbus_attach_args *ma = aux;
struct channel_softc *chp = &sc->sc_channel;
+ int reg[2];
+ int ivec;
+
+ if (OF_getprop(ma->ma_node, "reg", &reg, sizeof(reg)) < sizeof(reg)) {
+ printf(": missing registers\n");
+ return;
+ }
+
+ if (OF_getprop(ma->ma_node, "interrupts", &ivec, sizeof(ivec)) <= 0) {
+ printf(": missing interrupts\n");
+ return;
+ }
- chp->cmd_iot = chp->ctl_iot = oa->oa_iot;
- chp->_vtbl = &wdc_obio_vtbl;
+ chp->cmd_iot = chp->ctl_iot = ma->ma_iot;
+ chp->_vtbl = &wdc_mainbus_vtbl;
- if (bus_space_map(chp->cmd_iot, oa->oa_offset + WDC_OBIO_REG_OFFSET,
- WDC_OBIO_REG_SIZE, 0, &chp->cmd_ioh)) {
+ if (bus_space_map(chp->cmd_iot, reg[0] + WDC_MAINBUS_REG_OFFSET,
+ WDC_MAINBUS_REG_SIZE, 0, &chp->cmd_ioh)) {
printf(": can't map registers\n");
return;
}
- if (bus_space_map(chp->ctl_iot, oa->oa_offset + WDC_OBIO_AUXREG_OFFSET,
- WDC_OBIO_AUXREG_SIZE, 0, &chp->ctl_ioh)) {
+ if (bus_space_map(chp->ctl_iot, reg[0] + WDC_MAINBUS_AUXREG_OFFSET,
+ WDC_MAINBUS_AUXREG_SIZE, 0, &chp->ctl_ioh)) {
printf(": can't map registers\n");
return;
}
- sc->sc_ih = intr_establish(oa->oa_ivec, IST_LEVEL, IPL_BIO, wdcintr,
+ sc->sc_ih = intr_establish(ivec, IST_LEVEL, IPL_BIO, wdcintr,
chp, self->dv_xname);
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_PREATA;
@@ -127,7 +148,7 @@ wdc_obio_attach(struct device *parent, struct device *self, void *aux)
}
u_int8_t
-wdc_obio_read_reg(struct channel_softc *chp, enum wdc_regs reg)
+wdc_mainbus_read_reg(struct channel_softc *chp, enum wdc_regs reg)
{
uint8_t val;
@@ -146,7 +167,8 @@ wdc_obio_read_reg(struct channel_softc *chp, enum wdc_regs reg)
}
void
-wdc_obio_write_reg(struct channel_softc *chp, enum wdc_regs reg, u_int8_t val)
+wdc_mainbus_write_reg(struct channel_softc *chp, enum wdc_regs reg,
+ u_int8_t val)
{
if (reg & _WDC_AUX)
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh,