diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-05-23 21:20:13 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-05-23 21:20:13 +0000 |
commit | 662f84d26febf251dab6125867b1c2f378a9b295 (patch) | |
tree | 4d7c3d7a8dcf00a89efb3dded8955eff02772e66 /sys/arch | |
parent | 997a74cdac80c7f0931bfbd62a58790e0591ff50 (diff) |
TOD clock support for AngelFire boards
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/mvme88k/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/mvme88k/conf/M181 | 3 | ||||
-rw-r--r-- | sys/arch/mvme88k/conf/RAMDISK | 3 | ||||
-rw-r--r-- | sys/arch/mvme88k/conf/files.mvme88k | 6 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/ds1216.c | 298 | ||||
-rw-r--r-- | sys/arch/mvme88k/include/mvme181.h | 4 |
6 files changed, 311 insertions, 6 deletions
diff --git a/sys/arch/mvme88k/conf/GENERIC b/sys/arch/mvme88k/conf/GENERIC index 09067dc91bb..be54b20a3e5 100644 --- a/sys/arch/mvme88k/conf/GENERIC +++ b/sys/arch/mvme88k/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.57 2013/05/17 22:51:59 miod Exp $ +# $OpenBSD: GENERIC,v 1.58 2013/05/23 21:20:12 miod Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -39,6 +39,7 @@ mainbus0 at root angelfire0 at mainbus0 addr 0xff800000 vme0 at angelfire0 offset 0x680000 dart0 at angelfire0 offset 0x640000 ipl 5 +dsrtc0 at angelfire0 offset 0x10000 # MVME1x7 devices pcctwo0 at mainbus0 addr 0xfff00000 # MVME187 diff --git a/sys/arch/mvme88k/conf/M181 b/sys/arch/mvme88k/conf/M181 index f7f90acd9ef..f27262d33c5 100644 --- a/sys/arch/mvme88k/conf/M181 +++ b/sys/arch/mvme88k/conf/M181 @@ -1,4 +1,4 @@ -# $OpenBSD: M181,v 1.1 2013/05/17 22:51:59 miod Exp $ +# $OpenBSD: M181,v 1.2 2013/05/23 21:20:12 miod Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -34,6 +34,7 @@ mainbus0 at root angelfire0 at mainbus0 addr 0xff800000 vme0 at angelfire0 offset 0x680000 dart0 at angelfire0 offset 0x640000 ipl 5 +dsrtc0 at angelfire0 offset 0x10000 vmes0 at vme0 vmel0 at vme0 diff --git a/sys/arch/mvme88k/conf/RAMDISK b/sys/arch/mvme88k/conf/RAMDISK index e96f973950c..4d6e966d017 100644 --- a/sys/arch/mvme88k/conf/RAMDISK +++ b/sys/arch/mvme88k/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.36 2013/05/17 22:51:59 miod Exp $ +# $OpenBSD: RAMDISK,v 1.37 2013/05/23 21:20:12 miod Exp $ machine mvme88k m88k @@ -41,6 +41,7 @@ mainbus0 at root angelfire0 at mainbus0 addr 0xff800000 vme0 at angelfire0 offset 0x680000 dart0 at angelfire0 offset 0x640000 ipl 5 +dsrtc0 at angelfire0 offset 0x10000 # MVME1x7 devices pcctwo0 at mainbus0 addr 0xfff00000 # MVME187 diff --git a/sys/arch/mvme88k/conf/files.mvme88k b/sys/arch/mvme88k/conf/files.mvme88k index 64dda5ee2bc..6b7e4b39b2c 100644 --- a/sys/arch/mvme88k/conf/files.mvme88k +++ b/sys/arch/mvme88k/conf/files.mvme88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.mvme88k,v 1.48 2013/05/17 22:51:59 miod Exp $ +# $OpenBSD: files.mvme88k,v 1.49 2013/05/23 21:20:12 miod Exp $ # maxpartitions 16 @@ -37,6 +37,10 @@ device nvram attach nvram at pcctwo, syscon file arch/mvme88k/dev/nvram.c nvram needs-count +device dsrtc +attach dsrtc at angelfire +file arch/mvme88k/dev/ds1216.c dsrtc + device cl: tty attach cl at pcctwo file arch/mvme88k/dev/cl.c cl needs-count diff --git a/sys/arch/mvme88k/dev/ds1216.c b/sys/arch/mvme88k/dev/ds1216.c new file mode 100644 index 00000000000..aeb29acf216 --- /dev/null +++ b/sys/arch/mvme88k/dev/ds1216.c @@ -0,0 +1,298 @@ +/* $OpenBSD: ds1216.c,v 1.1 2013/05/23 21:20:12 miod Exp $ */ + +/* + * Copyright (c) 2013 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. + */ + +/* + * AngelFire Dallas DS1216 TOD clock support. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/time.h> + +#include <machine/autoconf.h> +#include <machine/board.h> +#include <machine/bus.h> + +#include <machine/mvme181.h> + +#include <mvme88k/mvme88k/clockvar.h> + +struct ds1216_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; +}; + +int ds1216_match(struct device *, void *, void *); +void ds1216_attach(struct device *, struct device *, void *); + +const struct cfattach dsrtc_ca = { + sizeof(struct ds1216_softc), ds1216_match, ds1216_attach +}; + +struct cfdriver dsrtc_cd = { + NULL, "dsrtc", DV_DULL +}; + +void ds1216_write_byte(struct ds1216_softc *, uint8_t); +uint8_t ds1216_read_byte(struct ds1216_softc *); +void ds1216_select(struct ds1216_softc *); +void ds1216_unselect(struct ds1216_softc *); + +time_t ds1216_inittodr(void); +void ds1216_resettodr(void); + +/* + * Register layout. All numerical values are in BCD. + */ + +#define DS1216_FRAC 0 /* hundredths of seconds (00-99) */ +#define DS1216_SEC 1 /* seconds (00-59) */ +#define DS1216_MIN 2 /* minutes (00-59) */ +#define DS1216_HOUR 3 /* hour (01-12/00-23) and hour control */ +#define DS1216_HOUR_12 0x80 /* 12 hour mode */ +#define DS1216_HOUR_PM 0x20 /* PM bit in 12 hour mode */ +#define DS1216_HOUR_12_MASK 0x1f /* valid digit bits in 12 hour mode */ +#define DS1216_HOUR_24_MASK 0x3f /* valid digit bits in 24 hour mode */ +#define DS1216_DOW 4 /* day of week (01-07) and controls */ +#define DS1216_STOP 0x20 /* oscillator stop */ +#define DS1216_RESET 0x10 /* reset (active low) */ +#define DS1216_DOW_MASK 0x07 /* valid dow bits */ +#define DS1216_DAY 5 /* day of month (01-31) */ +#define DS1216_MONTH 6 /* month (01-12) */ +#define DS1216_YEAR 7 /* year (00-99) */ + +#define DS1216_NREGS 8 + +/* + * Low-level access routines. + */ + +/* + * Access to the Dallas chip is performed by sending a magic sequence + * first, bit by bit. Two low-order address bits select whether the + * TOD registers or the on-chip memory is accessed. + * + * After the sequence is sent, it is possible to read or write the TOD + * register or the on-chip memory, using a similar bit-by-bit operation, + * as a whole. + * + * When the read or write sequence completes, the Dallas chip becomes + * pass-through again. + */ + +#define NCYCLES 64 + +const uint8_t ds1216_unlock_pattern[NCYCLES / 8] = { + 0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c +}; + +/* + * On the MVME181, the Dallas chip is connected to cpu A2 onwards (this is + * similar to the DART wiring), so the A0 and A2 lines are actually A2 and A4. + */ +#define A0 ((1 << 0) << 2) +#define A2 ((1 << 2) << 2) +#define DQ0 (1 << 0) + +/* + * Write 8 bits. A2 low for writing, data in A0. + */ +void +ds1216_write_byte(struct ds1216_softc *sc, uint8_t b) +{ + uint i; + + for (i = 8; i != 0; i--) { + bus_space_read_1(sc->sc_iot, sc->sc_ioh, b & DQ0 ? A0 : 0); + b >>= 1; + } +} + +/* + * Read 8 bits. A2 high for reading, data in DQ0. + */ +uint8_t +ds1216_read_byte(struct ds1216_softc *sc) +{ + uint8_t b = 0, bit = DQ0; + uint i; + + for (i = 8; i != 0; i--) { + if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, A2) & DQ0) + b |= bit; + bit <<= 1; + } + + return b; +} + +/* + * Select the Dallas chip: read once with A2 high, then issue the 64-bit + * unlock sequence on A0 with A2 low. + */ +void +ds1216_select(struct ds1216_softc *sc) +{ + const uint8_t *bsrc = ds1216_unlock_pattern; + uint8_t b; + uint i; + + bus_space_read_1(sc->sc_iot, sc->sc_ioh, A2); + for (i = NCYCLES; i != 0; i--) { + if ((i % 8) == 0) + b = *bsrc++; + bus_space_read_1(sc->sc_iot, sc->sc_ioh, b & DQ0 ? A0 : 0); + b >>= 1; + } +} + +/* + * Make sure the Dallas chip is not currently selected by performing enough + * dummy read cycles to switch it to pass-through mode, if it wasn't already + * in this state. + */ +void +ds1216_unselect(struct ds1216_softc *sc) +{ + uint i; + + for (i = NCYCLES; i != 0; i--) { + bus_space_read_1(sc->sc_iot, sc->sc_ioh, A2 | A0); + } +} + +/* + * Kernel TOD glue. + */ + +time_t +ds1216_inittodr() +{ + struct ds1216_softc *sc = (struct ds1216_softc *)dsrtc_cd.cd_devs[0]; + struct clock_ymdhms c; + uint8_t regs[DS1216_NREGS]; + uint i; + + ds1216_select(sc); + for (i = 0; i < DS1216_NREGS; i++) + regs[i] = ds1216_read_byte(sc); + + c.dt_sec = FROMBCD(regs[DS1216_SEC]); + c.dt_min = FROMBCD(regs[DS1216_MIN]); + /* + * BUG should have set up the clock in 24 hour mode. Allow for + * 12 hour mode, just in case. + */ + if (ISSET(regs[DS1216_HOUR], DS1216_HOUR_12)) { + c.dt_hour = FROMBCD(regs[DS1216_HOUR] & DS1216_HOUR_12_MASK); + if (c.dt_hour == 12) + c.dt_hour = 0; + if (ISSET(regs[DS1216_HOUR], DS1216_HOUR_PM)) + c.dt_hour += 12; + } else + c.dt_hour = FROMBCD(regs[DS1216_HOUR] & DS1216_HOUR_24_MASK); + c.dt_day = FROMBCD(regs[DS1216_DAY]); + c.dt_mon = FROMBCD(regs[DS1216_MONTH]); + c.dt_year = FROMBCD(regs[DS1216_YEAR]) + 1900; + /* XXX 2-digit year => Y2070 problem */ + if (c.dt_year < POSIX_BASE_YEAR) + c.dt_year += 100; + + return clock_ymdhms_to_secs(&c); +} + +void +ds1216_resettodr() +{ + struct ds1216_softc *sc = (struct ds1216_softc *)dsrtc_cd.cd_devs[0]; + struct clock_ymdhms c; + uint8_t regs[DS1216_NREGS]; + uint i; + + clock_secs_to_ymdhms(time_second, &c); + + regs[DS1216_FRAC] = 0; + regs[DS1216_SEC] = TOBCD(c.dt_sec); + regs[DS1216_MIN] = TOBCD(c.dt_min); + regs[DS1216_HOUR] = TOBCD(c.dt_hour); + regs[DS1216_DOW] = DS1216_RESET | c.dt_wday; + regs[DS1216_DAY] = TOBCD(c.dt_day); + regs[DS1216_MONTH] = TOBCD(c.dt_mon); + regs[DS1216_YEAR] = TOBCD(c.dt_year % 100); + + ds1216_select(sc); + for (i = 0; i < DS1216_NREGS; i++) + ds1216_write_byte(sc, regs[i]); +} + +/* + * Autoconf glue. + */ + +int +ds1216_match(struct device *parent, void *vcf, void *aux) +{ + struct confargs *ca = (struct confargs *)aux; + + switch (brdtyp) { +#ifdef MVME181 + case BRD_180: + case BRD_181: + break; +#endif + default: + return 0; + } + + if (ca->ca_paddr != M181_DSRTC) + return 0; + + /* + * Can't use badaddr() here - the Dallas chip overlaps the BUG image + * when selected; therefore access never fails even if the chip + * were to be missing. + */ + return 1; +} + +void +ds1216_attach(struct device *parent, struct device *self, void *aux) +{ + struct ds1216_softc *sc = (struct ds1216_softc *)self; + struct confargs *ca = (struct confargs *)aux; + + sc->sc_iot = ca->ca_iot; + if (bus_space_map(ca->ca_iot, ca->ca_paddr, A2 << 1, 0, + &sc->sc_ioh) != 0) { + printf(": can't map registers\n"); + return; + } + + printf("\n"); + + /* + * Force the chip out of selection. This is unlikely necessary, + * the BUG is expected to have done this for us. + */ + ds1216_unselect(sc); + + md_inittodr = ds1216_inittodr; + md_resettodr = ds1216_resettodr; +} diff --git a/sys/arch/mvme88k/include/mvme181.h b/sys/arch/mvme88k/include/mvme181.h index ec980abc4af..d8140eb1c3d 100644 --- a/sys/arch/mvme88k/include/mvme181.h +++ b/sys/arch/mvme88k/include/mvme181.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mvme181.h,v 1.1 2013/05/17 22:51:59 miod Exp $ */ +/* $OpenBSD: mvme181.h,v 1.2 2013/05/23 21:20:12 miod Exp $ */ /* * Copyright (c) 2013 Miodrag Vallat. @@ -31,7 +31,7 @@ #define M181_CLRABRT 0xffee0000 /* clear abort interrupt */ #define M181_DUART 0xffe40000 /* base address of DUART chip */ -#define M181_DSRTC 0xff800000 /* base address of TODclock */ +#define M181_DSRTC 0xff810000 /* base address of TODclock */ /* * Control and Status Register interrupt bits - 180 only has the lower 8 bits |