summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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,