diff options
Diffstat (limited to 'sys/arch/mvme68k/dev/ofobio.c')
-rw-r--r-- | sys/arch/mvme68k/dev/ofobio.c | 214 |
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; +} |