summaryrefslogtreecommitdiff
path: root/sys/arch/mvme68k/dev/ofobio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mvme68k/dev/ofobio.c')
-rw-r--r--sys/arch/mvme68k/dev/ofobio.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/sys/arch/mvme68k/dev/ofobio.c b/sys/arch/mvme68k/dev/ofobio.c
new file mode 100644
index 00000000000..35d469e609e
--- /dev/null
+++ b/sys/arch/mvme68k/dev/ofobio.c
@@ -0,0 +1,214 @@
+/* $OpenBSD: ofobio.c,v 1.1 2009/03/01 22:08:13 miod Exp $ */
+
+/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * MVME141 On-board resources (One-Four-One OBIO)
+ *
+ * Unlike other MVME boards supported under OpenBSD/mvme68k, there is no
+ * specific ASIC (lrc, mc2, pcc, pcc2...) providing a solid base to which
+ * all other devices are related.
+ *
+ * Instead, we have four registers, and no timers. The onboard devices
+ * (MC6861 providing serial ports and the clock, VMEchip, VSBchip and
+ * NVRAM) may as well attach to mainbus. We nevertheless attach them at
+ * ofobio to make things simpler in the kernel.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+
+#include <mvme68k/dev/ofobioreg.h>
+#include <mvme68k/dev/dartreg.h>
+
+struct ofobioreg *sys_ofobio;
+
+struct ofobiosoftc {
+ struct device sc_dev;
+ struct ofobioreg *sc_regs;
+ struct intrhand sc_abortih;
+};
+
+int ofobioabort(void *);
+void ofobioattach(struct device *, struct device *, void *);
+int ofobiomatch(struct device *, void *, void *);
+int ofobioprint(void *, const char *);
+int ofobioscan(struct device *, void *, void *);
+
+struct cfattach ofobio_ca = {
+ sizeof(struct ofobiosoftc), ofobiomatch, ofobioattach
+};
+
+struct cfdriver ofobio_cd = {
+ NULL, "ofobio", DV_DULL
+};
+
+int
+ofobiomatch(struct device *parent, void *cf, void *aux)
+{
+ if (cputyp != CPU_141 || sys_ofobio != NULL)
+ return (0);
+
+ return (1);
+}
+
+void
+ofobioattach(struct device *parent, struct device *self, void *aux)
+{
+#if 0
+ struct confargs *ca = aux;
+#endif
+ struct ofobiosoftc *sc = (struct ofobiosoftc *)self;
+
+ sys_ofobio = sc->sc_regs = (struct ofobioreg *)IIOV(OFOBIO_CSR_ADDR);
+
+ /* disable VSB and timer interrupts */
+ sc->sc_regs->csr_b |= OFO_CSRB_VSB_INTDIS | OFO_CSRB_TIMER_INTDIS;
+ /* enable A32 addressing and device interrupts */
+ sc->sc_regs->csr_b &= ~(OFO_CSRB_GLOBAL_INTDIS | OFO_CSRB_DISABLE_A24);
+
+ /*
+ * A note regarding the board cache: the on-board 32KB are used
+ * during early BUG bootstrap, until off-board memory is found,
+ * and is intended to be used by the operating system as cache
+ * memory (in addition to the small instruction cache internal to
+ * the 68030).
+ *
+ * The cache flush and cache invalidation routines in locore
+ * are not modified to invalidate the board cache as well,
+ * since its snooping appears to be good enough to make it
+ * completely transparent (the fact that vsbic(4) works, relying
+ * to proper invalidate behaviour, is a good omen).
+ */
+
+ /* clear board cache, then enable it */
+ sc->sc_regs->csr_a |= OFO_CSRA_CACHE_WDIS | OFO_CSRA_CACHE_RDIS;
+ sc->sc_regs->csr_a |= OFO_CSRA_CACHE_CLEAR;
+ sc->sc_regs->csr_a = OFO_CSRA_CACHE_MONITOR;
+
+ printf(": board cache enabled\n");
+
+ sc->sc_abortih.ih_fn = ofobioabort;
+ sc->sc_abortih.ih_ipl = IPL_HIGH;
+ sc->sc_abortih.ih_wantframe = 1;
+ intr_establish(OFOBIOVEC_ABORT, &sc->sc_abortih, self->dv_xname);
+
+ config_search(ofobioscan, self, aux);
+}
+
+int
+ofobioprint(void *aux, const char *pnp)
+{
+ struct confargs *ca = aux;
+
+ if (ca->ca_offset != -1)
+ printf(" offset 0x%x", ca->ca_offset);
+ if (ca->ca_ipl > 0)
+ printf(" ipl %d", ca->ca_ipl);
+ return (UNCONF);
+}
+
+int
+ofobioscan(struct device *parent, void *self, void *aux)
+{
+ struct cfdata *cf = self;
+#if 0
+ struct ofobiosoftc *sc = (struct ofobiosoftc *)parent;
+#endif
+ struct confargs *ca = aux;
+ struct confargs oca;
+
+ bzero(&oca, sizeof oca);
+ oca.ca_iot = ca->ca_iot;
+ oca.ca_dmat = ca->ca_dmat;
+ oca.ca_offset = cf->cf_loc[0];
+ oca.ca_ipl = cf->cf_loc[1];
+ if (oca.ca_offset != -1) {
+ oca.ca_paddr = ca->ca_paddr + oca.ca_offset;
+ oca.ca_vaddr = IIOV(oca.ca_paddr);
+ } else {
+ oca.ca_vaddr = (vaddr_t)-1;
+ oca.ca_paddr = (paddr_t)-1;
+ }
+ oca.ca_bustype = BUS_OFOBIO;
+ oca.ca_name = cf->cf_driver->cd_name;
+
+ if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0)
+ return (0);
+
+ config_attach(parent, cf, &oca, ofobioprint);
+
+ return (1);
+}
+
+int
+ofobioabort(void *frame)
+{
+ /*
+ * Latch the condition; this will debounce the interrupt,
+ * acknowledge it, and both the CSRD_ABORT and CRSD_ABORT_LATCH
+ * bits will clear.
+ */
+ sys_ofobio->csr_d |= OFO_CSRD_ABORT_LATCH;
+
+ nmihand(frame);
+
+ return (1);
+}
+
+void
+ofobio_clocksetup()
+{
+ volatile uint8_t *dartregs =
+ (volatile uint8_t *)IIOV(MVME141_DART_BASE);
+ uint limit;
+ uint8_t dummy;
+
+ /*
+ * Note that the dart(4) driver already may have programmed the
+ * OPCR register during attachment.
+ * It is very unfortunate that we have to override this. However
+ * since dart(4) never needs to change the setting of this register,
+ * ve'll simply keep the serial-related bits and add our own.
+ */
+
+ /* disable timer output during programming */
+ dartregs[DART_OPCR] = OPSET;
+
+ /*
+ * The DUART runs at 3.6864 MHz; by using the second waveform
+ * generator we'll get a CLK/32 master rate.
+ */
+ limit = (3686400 / 32) / hz;
+
+ dartregs[DART_CTUR] = limit >> 8;
+ dartregs[DART_CTLR] = limit & 0xff;
+ dartregs[DART_ACR] = BDSET2 | CCLK1 | IPDCDB | IPDCDA;
+ dartregs[DART_OPCR] = OPSETTO;
+ /* start counter */
+ dummy = dartregs[DART_CTSTART];
+
+ /* enable timer interrupts */
+ sys_ofobio->csr_b &= ~OFO_CSRB_TIMER_INTDIS;
+}