diff options
Diffstat (limited to 'sys/arch/sgi/hpc/dsclock.c')
| -rw-r--r-- | sys/arch/sgi/hpc/dsclock.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/sys/arch/sgi/hpc/dsclock.c b/sys/arch/sgi/hpc/dsclock.c new file mode 100644 index 00000000000..396d68ec9d9 --- /dev/null +++ b/sys/arch/sgi/hpc/dsclock.c @@ -0,0 +1,192 @@ +/* $OpenBSD: dsclock.c,v 1.1 2012/03/28 20:44:23 miod Exp $ */ +/* $NetBSD: dsclock.c,v 1.5 2011/07/01 18:53:46 dyoung Exp $ */ + +/* + * Copyright (c) 2001 Rafal K. Boni + * Copyright (c) 2001 Christopher Sekiya + * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Portions of this code are derived from software contributed to The + * NetBSD Foundation by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/autoconf.h> +#include <machine/bus.h> + +#include <mips64/archtype.h> +#include <mips64/dev/clockvar.h> + +#include <dev/ic/ds1286reg.h> +#include <sgi/hpc/hpcvar.h> + +#define IRIX_BASE_YEAR 1940 + +struct dsclock_softc { + struct device sc_dev; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; +}; + +int dsclock_match(struct device *, void *, void *); +void dsclock_attach(struct device *, struct device *, void *); + +struct cfdriver dsclock_cd = { + NULL, "dsclock", DV_DULL +}; + +const struct cfattach dsclock_ca = { + sizeof(struct dsclock_softc), dsclock_match, dsclock_attach +}; + +#define ds1286_read(sc,r) \ + bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, ((r) << 2) + 3) +#define ds1286_write(sc,r,v) \ + bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, ((r) << 2) + 3, (v)) + +static inline int frombcd(int); +static inline int tobcd(int); + +static inline int +frombcd(int x) +{ + return (x >> 4) * 10 + (x & 0xf); +} +static inline int +tobcd(int x) +{ + return (x / 10 * 16) + (x % 10); +} + +void dsclock_gettime(void *, time_t, struct tod_time *); +void dsclock_settime(void *, struct tod_time *); + +int +dsclock_match(struct device *parent, void *vcf, void *aux) +{ + struct hpc_attach_args *haa = aux; + + if (strcmp(haa->ha_name, dsclock_cd.cd_name) != 0) + return 0; + + return 1; +} + +void +dsclock_attach(struct device *parent, struct device *self, void *aux) +{ + struct dsclock_softc *sc = (void *)self; + struct hpc_attach_args *haa = aux; + + sc->sc_iot = haa->ha_st; + if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff, + 4 * 8192, &sc->sc_ioh) != 0) { + printf(": can't map registers\n"); + return; + } + + printf("\n"); + + sys_tod.tod_get = dsclock_gettime; + sys_tod.tod_set = dsclock_settime; + sys_tod.tod_cookie = self; +} + +/* + * Get the time of day, based on the clock's value and/or the base value. + */ +void +dsclock_gettime(void *cookie, time_t base, struct tod_time *ct) +{ + struct dsclock_softc *sc = (void *)cookie; + ds1286_todregs regs; + int s; + + s = splhigh(); + DS1286_GETTOD(sc, ®s) + splx(s); + + ct->sec = frombcd(regs[DS1286_SEC]); + ct->min = frombcd(regs[DS1286_MIN]); + + if (regs[DS1286_HOUR] & DS1286_HOUR_12MODE) { + ct->hour = frombcd(regs[DS1286_HOUR] & DS1286_HOUR_12HR_MASK) + + ((regs[DS1286_HOUR] & DS1286_HOUR_12HR_PM) ? 12 : 0); + + /* + * In AM/PM mode, hour range is 01-12, so adding in 12 hours + * for PM gives us 01-24, whereas we want 00-23, so map hour + * 24 to hour 0. + */ + if (ct->hour == 24) + ct->hour = 0; + } else { + ct->hour = frombcd(regs[DS1286_HOUR] & DS1286_HOUR_24HR_MASK); + } + + ct->day = frombcd(regs[DS1286_DOM]); + ct->mon = frombcd(regs[DS1286_MONTH] & DS1286_MONTH_MASK); + ct->year = frombcd(regs[DS1286_YEAR]) + (IRIX_BASE_YEAR - 1900); +} + +/* + * Reset the TODR based on the time value. + */ +void +dsclock_settime(void *cookie, struct tod_time *ct) +{ + struct dsclock_softc *sc = (void *)cookie; + ds1286_todregs regs; + int s; + + s = splhigh(); + DS1286_GETTOD(sc, ®s); + splx(s); + + regs[DS1286_SUBSEC] = 0; + regs[DS1286_SEC] = tobcd(ct->sec); + regs[DS1286_MIN] = tobcd(ct->min); + regs[DS1286_HOUR] = tobcd(ct->hour) & DS1286_HOUR_24HR_MASK; + regs[DS1286_DOW] = tobcd(ct->dow); + regs[DS1286_DOM] = tobcd(ct->day); + + /* Leave wave-generator bits as set originally */ + regs[DS1286_MONTH] &= ~DS1286_MONTH_MASK; + regs[DS1286_MONTH] |= tobcd(ct->mon) & DS1286_MONTH_MASK; + + regs[DS1286_YEAR] = tobcd(ct->year - (IRIX_BASE_YEAR - 1900)); + + s = splhigh(); + DS1286_PUTTOD(sc, ®s); + splx(s); +} |
