diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-09-06 20:09:35 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-09-06 20:09:35 +0000 |
commit | 2fd91aac38ea3f6322903b6921b4b83d15b292a9 (patch) | |
tree | fcff737b4795e5428b2fd74fbc4d830a17f804bd | |
parent | 530de8f9420591168bf062e320611b45167f642a (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/GENERIC | 30 | ||||
-rw-r--r-- | sys/arch/socppc/conf/RB600 | 65 | ||||
-rw-r--r-- | sys/arch/socppc/conf/files.socppc | 11 | ||||
-rw-r--r-- | sys/arch/socppc/dev/com_obio.c | 24 | ||||
-rw-r--r-- | sys/arch/socppc/dev/ehci_obio.c | 11 | ||||
-rw-r--r-- | sys/arch/socppc/dev/if_tsec.c | 51 | ||||
-rw-r--r-- | sys/arch/socppc/dev/ipic.c | 73 | ||||
-rw-r--r-- | sys/arch/socppc/dev/obio.c | 49 | ||||
-rw-r--r-- | sys/arch/socppc/dev/sociic.c | 11 | ||||
-rw-r--r-- | sys/arch/socppc/dev/socpcic.c | 158 | ||||
-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", ®, + 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", ®, 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", ®, 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", ®, 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, |