summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorfredette <fredette@NetBSD.org>2001-04-10 12:46:26 +0000
committerfredette <fredette@NetBSD.org>2001-04-10 12:46:26 +0000
commitb27eda4ead5cece523b91c2e6239ac4c91985221 (patch)
treea04c3bdbbfa2d3ad63e71e0ffcd952250a31efc5 /sys/dev
parent1dfde059abb152fc3c02b6df19e1b78bcaaa6faf (diff)
Added.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/am9513reg.h281
-rw-r--r--sys/dev/ic/mm58167.c282
-rw-r--r--sys/dev/ic/mm58167var.h92
3 files changed, 655 insertions, 0 deletions
diff --git a/sys/dev/ic/am9513reg.h b/sys/dev/ic/am9513reg.h
new file mode 100644
index 00000000000..4ecafd092c9
--- /dev/null
+++ b/sys/dev/ic/am9513reg.h
@@ -0,0 +1,281 @@
+/* $NetBSD: am9513reg.h,v 1.1 2001/04/10 12:50:17 fredette Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthew Fredette.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+#ifndef _AM9513REG_H
+#define _AM9513REG_H
+
+/*
+ * Driver support for the Am9513 timer chip. See
+ * http://www.amd.com/products/cpg/techdocs/misc/03402/03402.html
+ * for data sheets.
+ */
+
+struct am9513 {
+ u_int16_t am9513_clk_data; /* data register */
+ u_int16_t am9513_clk_cmd; /* command register */
+};
+
+#define AM9513_CLK_DATA 0
+#define AM9513_CLK_CMD 2
+
+/*
+ * All of the below macros are for use in bitfields in the Counter
+ * Mode (CM) Register.
+ */
+
+/* Gating control, CM[13:15]: */
+/*
+ * Legend: A[HL][LE]?
+ * | | `-> L = level, E = edge
+ * | `-> H = high, L = low
+ * `-> active
+ *
+ * P1 = plus one, M1 = minus one
+ */
+#define AM9513_CM_GATING_NONE (0x0 << 13)
+#define AM9513_CM_GATING_AH_TCN_M1 (0x1 << 13)
+#define AM9513_CM_GATING_AHL_GATEN_P1 (0x2 << 13)
+#define AM9513_CM_GATING_AHL_GATEN_M1 (0x3 << 13)
+#define AM9513_CM_GATING_AHL_GATEN (0x4 << 13)
+#define AM9513_CM_GATING_ALL_GATEN (0x5 << 13)
+#define AM9513_CM_GATING_AHE_GATEN (0x6 << 13)
+#define AM9513_CM_GATING_ALE_GATEN (0x7 << 13)
+
+/* Source edge, CM[12]: */
+#define AM9513_CM_SOURCE_EDGE_RISING (0 << 12)
+#define AM9513_CM_SOURCE_EDGE_FALLING (1 << 12)
+
+/* Count sources, CM[8:11]: */
+#define AM9513_CM_SOURCE_TCN1 (0x0 << 8)
+#define AM9513_CM_SOURCE_SRC1 (0x1 << 8)
+#define AM9513_CM_SOURCE_SRC2 (0x2 << 8)
+#define AM9513_CM_SOURCE_SRC3 (0x3 << 8)
+#define AM9513_CM_SOURCE_SRC4 (0x4 << 8)
+#define AM9513_CM_SOURCE_SRC5 (0x5 << 8)
+#define AM9513_CM_SOURCE_GATE1 (0x6 << 8)
+#define AM9513_CM_SOURCE_GATE2 (0x7 << 8)
+#define AM9513_CM_SOURCE_GATE3 (0x8 << 8)
+#define AM9513_CM_SOURCE_GATE4 (0x9 << 8)
+#define AM9513_CM_SOURCE_GATE5 (0xA << 8)
+#define AM9513_CM_SOURCE_F1 (0xB << 8)
+#define AM9513_CM_SOURCE_F2 (0xC << 8)
+#define AM9513_CM_SOURCE_F3 (0xD << 8)
+#define AM9513_CM_SOURCE_F4 (0xE << 8)
+#define AM9513_CM_SOURCE_F5 (0xF << 8)
+
+/* Count control, CM[7]: */
+#define AM9513_CM_SPECIAL_GATE_ENA (1 << 7)
+#define AM9513_CM_SPECIAL_GATE_DIS (0 << 7)
+
+/* Counter reload source, CM[6]: */
+#define AM9513_CM_RELOAD_SOURCE_LOAD (0 << 6)
+#define AM9513_CM_RELOAD_SOURCE_LOAD_OR_HOLD (1 << 6)
+
+/* Counter repeat control, CM[5]: */
+#define AM9513_CM_REPEAT_DIS (0 << 5)
+#define AM9513_CM_REPEAT_ENA (1 << 5)
+
+/* Counter type, CM[4]: */
+#define AM9513_CM_TYPE_BIN (0 << 4)
+#define AM9513_CM_TYPE_BCD (1 << 4)
+
+/* Counter direction, CM[3]: */
+#define AM9513_CM_DIR_DOWN (0 << 3)
+#define AM9513_CM_DIR_UP (1 << 3)
+
+/* Output control, CM[0:2]: */
+#define AM9513_CM_OUTPUT_OL (0x0 << 0) /* inactive, output low */
+#define AM9513_CM_OUTPUT_AHTCP (0x1 << 0) /* active high terminal count pulse */
+#define AM9513_CM_OUTPUT_TC_TOGGLED (0x2 << 0) /* TC toggled */
+#define AM9513_CM_OUTPUT_OHI (0x4 << 0) /* inactive, output high impedance */
+#define AM9513_CM_OUTPUT_ALTCP (0x5 << 0) /* active low terminal count pulse */
+
+/* The modes are various combinations of the above: */
+
+/* Mode A: */
+#define AM9513_CM_MODE_A (AM9513_CM_GATING_NONE \
+ | AM9513_CM_SPECIAL_GATE_DIS \
+ | AM9513_CM_RELOAD_SOURCE_LOAD \
+ | AM9513_CM_REPEAT_DIS)
+
+/*
+ * Mode B is just like mode A, except you OR in the
+ * AM9513_CM_GATING_ value for the *level* you want:
+ */
+#define AM9513_CM_MODE_B AM9513_CM_MODE_A
+
+/*
+ * Mode C is just like mode A, except you OR in the
+ * AM9513_CM_GATING_ value for the *edge* you want:
+ */
+#define AM9513_CM_MODE_C AM9513_CM_MODE_A
+
+/* Mode D: */
+#define AM9513_CM_MODE_D (AM9513_CM_GATING_NONE \
+ | AM9513_CM_SPECIAL_GATE_DIS \
+ | AM9513_CM_RELOAD_SOURCE_LOAD \
+ | AM9513_CM_REPEAT_ENA)
+
+/*
+ * Mode E is just like mode D, except you OR in the
+ * AM9513_CM_GATING_ value for the *level* you want:
+ */
+#define AM9513_CM_MODE_E AM9513_CM_MODE_D
+
+/*
+ * Mode F is just like mode D, except you OR in the
+ * AM9513_CM_GATING_ value for the *edge* you want:
+ */
+#define AM9513_CM_MODE_F AM9513_CM_MODE_D
+
+/* Mode G: */
+#define AM9513_CM_MODE_G (AM9513_CM_GATING_NONE \
+ | AM9513_CM_SPECIAL_GATE_DIS \
+ | AM9513_CM_RELOAD_SOURCE_LOAD_OR_HOLD \
+ | AM9513_CM_REPEAT_DIS)
+
+/*
+ * Mode H is just like mode G, except you OR in the
+ * AM9513_CM_GATING_ value for the *level* you want:
+ */
+#define AM9513_CM_MODE_H AM9513_CM_MODE_G
+
+/*
+ * Mode I is just like mode G, except you OR in the
+ * AM9513_CM_GATING_ value for the *edge* you want:
+ */
+#define AM9513_CM_MODE_I AM9513_CM_MODE_G
+
+/* Mode J: */
+#define AM9513_CM_MODE_J (AM9513_CM_GATING_NONE \
+ | AM9513_CM_SPECIAL_GATE_DIS \
+ | AM9513_CM_RELOAD_SOURCE_LOAD_OR_HOLD \
+ | AM9513_CM_REPEAT_ENA)
+
+/*
+ * Mode K is just like mode J, except you OR in the
+ * AM9513_CM_GATING_ value for the *level* you want:
+ */
+#define AM9513_CM_MODE_K AM9513_CM_MODE_J
+
+/*
+ * Mode L is just like mode J, except you OR in the
+ * AM9513_CM_GATING_ value for the *edge* you want:
+ */
+#define AM9513_CM_MODE_L AM9513_CM_MODE_J
+
+/* Mode N: */
+#define AM9513_CM_MODE_N (AM9513_CM_GATING_NONE \
+ | AM9513_CM_SPECIAL_GATE_ENA \
+ | AM9513_CM_RELOAD_SOURCE_LOAD \
+ | AM9513_CM_REPEAT_DIS)
+
+/*
+ * Mode O is just like mode N, except you OR in the
+ * AM9513_CM_GATING_ value for the *edge* you want:
+ */
+#define AM9513_CM_MODE_O AM9513_CM_MODE_N
+
+/* Mode Q; OR in the AM9513_CM_GATING_ value for the *level* you want: */
+#define AM9513_CM_MODE_Q (AM9513_CM_GATING_NONE \
+ | AM9513_CM_SPECIAL_GATE_ENA \
+ | AM9513_CM_RELOAD_SOURCE_LOAD \
+ | AM9513_CM_REPEAT_ENA)
+
+/*
+ * Mode R is just like mode N, except you OR in the
+ * AM9513_CM_GATING_ value for the *edge* you want:
+ */
+#define AM9513_CM_MODE_R AM9513_CM_MODE_Q
+
+/* Mode S: */
+#define AM9513_CM_MODE_S (AM9513_CM_GATING_NONE \
+ | AM9513_CM_SPECIAL_GATE_ENA \
+ | AM9513_CM_RELOAD_SOURCE_LOAD_OR_HOLD \
+ | AM9513_CM_REPEAT_DIS)
+
+/* Mode V: */
+#define AM9513_CM_MODE_V (AM9513_CM_GATING_NONE \
+ | AM9513_CM_SPECIAL_GATE_ENA \
+ | AM9513_CM_RELOAD_SOURCE_LOAD_OR_HOLD \
+ | AM9513_CM_REPEAT_ENA)
+
+/* Given an AM9513_CM_SOURCE_F? value, return the divisor: */
+#define AM9513_CM_SOURCE_Fn_DIV(func) (1 << (((func) - AM9513_CM_SOURCE_F1) >> 6))
+
+/*
+ * Given a basic frequency and an AM9513_CM_SOURCE_F? value, returns
+ * the number of clock ticks for a certain frequency:
+ */
+#define AM9513_TICKS(basic, func, hz) (((basic) / AM9513_CM_SOURCE_Fn_DIV(func)) / (hz))
+
+/* These are the timer numbers: */
+#define AM9513_TIMER1 (1)
+#define AM9513_TIMER2 (2)
+#define AM9513_TIMER3 (3)
+#define AM9513_TIMER4 (4)
+#define AM9513_TIMER5 (5)
+
+/*
+ * This macro is used to compose a bitmask of times for those
+ * commands that take a bitmask:
+ */
+#define AM9513_TIMER_BIT(timer) (1 << ((timer) - 1))
+
+/* When in 16-bit mode, the high 8 bits of every command must be ones: */
+#define _AM9513_CMD(x) (0xFF00 | (x))
+
+/* Commands: */
+#define AM9513_CMD_LOAD_MODE(timer) _AM9513_CMD(0x00 | (timer))
+#define AM9513_CMD_LOAD_LOAD(timer) _AM9513_CMD(0x08 | (timer))
+#define AM9513_CMD_LOAD_HOLD(timer) _AM9513_CMD(0x10 | (timer))
+#define AM9513_CMD_ARM(timers) _AM9513_CMD(0x20 | (timers))
+#define AM9513_CMD_LOAD(timers) _AM9513_CMD(0x40 | (timers))
+#define AM9513_CMD_LOAD_ARM(timers) _AM9513_CMD(0x60 | (timers))
+#define AM9513_CMD_SAVE(timers) _AM9513_CMD(0xA0 | (timers))
+#define AM9513_CMD_DISARM(timers) _AM9513_CMD(0xC0 | (timers))
+#define AM9513_CMD_CLEAR_OUTPUT(timer) _AM9513_CMD(0xE0 | (timer))
+#define AM9513_CMD_RESET _AM9513_CMD(0xFF)
+
+/* These are mode register values for various uses */
+#define AM9513_TICK_MODE (AM9513_F2+0x22) /* F2 + Operating mode D */
+#define AM9513_UART_MODE (AM9513_F1+0x22) /* F1 + Operating mode D */
+#define AM9513_FAST_LO_MODE (AM9513_F3+0x28) /* F3, repeat, count up */
+#define AM9513_FAST_HI_MODE (0x0028) /* TC of LO, repeat, count up */
+
+#endif /* _AM9513REG_H */
diff --git a/sys/dev/ic/mm58167.c b/sys/dev/ic/mm58167.c
new file mode 100644
index 00000000000..cdf66748b43
--- /dev/null
+++ b/sys/dev/ic/mm58167.c
@@ -0,0 +1,282 @@
+/* $NetBSD: mm58167.c,v 1.1 2001/04/10 12:50:18 fredette Exp $ */
+
+/*
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthew Fredette.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+/*
+ * National Semiconductor MM58167 time-of-day chip subroutines.
+ */
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <dev/clock_subr.h>
+#include <dev/ic/mm58167var.h>
+
+int mm58167_gettime __P((todr_chip_handle_t, struct timeval *));
+int mm58167_settime __P((todr_chip_handle_t, struct timeval *));
+int mm58167_getcal __P((todr_chip_handle_t, int *));
+int mm58167_setcal __P((todr_chip_handle_t, int));
+
+/*
+ * To quote SunOS's todreg.h:
+ * "This brain damaged chip insists on keeping the time in
+ * MM/DD HH:MM:SS format, even though it doesn't know about
+ * leap years and Feb. 29, thus making it nearly worthless."
+ */
+#define mm58167_read(sc, r) bus_space_read_1(sc->mm58167_regt, sc->mm58167_regh, sc-> r)
+#define mm58167_write(sc, r, v) bus_space_write_1(sc->mm58167_regt, sc->mm58167_regh, sc-> r, v)
+
+todr_chip_handle_t
+mm58167_attach(sc)
+ struct mm58167_softc *sc;
+{
+ struct todr_chip_handle *handle;
+
+ printf(": mm58167");
+
+ handle = &sc->_mm58167_todr_handle;
+ bzero(handle, sizeof(handle));
+ handle->cookie = sc;
+ handle->todr_gettime = mm58167_gettime;
+ handle->todr_settime = mm58167_settime;
+ handle->todr_getcal = mm58167_getcal;
+ handle->todr_setcal = mm58167_setcal;
+ return (handle);
+}
+
+/*
+ * Set up the system's time, given a `reasonable' time value.
+ */
+int
+mm58167_gettime(handle, tv)
+ todr_chip_handle_t handle;
+ struct timeval *tv;
+{
+ struct mm58167_softc *sc = handle->cookie;
+ struct clock_ymdhms dt_hardware;
+ struct clock_ymdhms dt_reasonable;
+ int s;
+ u_int8_t byte_value;
+ int leap_year, had_leap_day;
+
+ /* First, read the date out of the chip. */
+
+ /* No interrupts while we're in the chip. */
+ s = splhigh();
+
+ /* Reset the status bit: */
+ byte_value = mm58167_read(sc, mm58167_status);
+
+ /*
+ * Read the date values until we get a coherent read (one
+ * where the status stays zero, indicating no increment was
+ * rippling through while we were reading).
+ */
+ do {
+#define _MM58167_GET(dt_f, mm_f) byte_value = mm58167_read(sc, mm_f); dt_hardware.dt_f = FROMBCD(byte_value)
+ _MM58167_GET(dt_mon, mm58167_mon);
+ _MM58167_GET(dt_day, mm58167_day);
+ _MM58167_GET(dt_hour, mm58167_hour);
+ _MM58167_GET(dt_min, mm58167_min);
+ _MM58167_GET(dt_sec, mm58167_sec);
+#undef _MM58167_GET
+ } while ((mm58167_read(sc, mm58167_status) & 1) == 0);
+
+ splx(s);
+
+ /* Convert the reasonable time into a date: */
+ clock_secs_to_ymdhms(tv->tv_sec, &dt_reasonable);
+
+ /*
+ * We need to fake a hardware year. if the hardware MM/DD
+ * HH:MM:SS date is less than the reasonable MM/DD
+ * HH:MM:SS, call it the reasonable year plus one, else call
+ * it the reasonable year.
+ */
+ if (dt_hardware.dt_mon < dt_reasonable.dt_mon ||
+ (dt_hardware.dt_mon == dt_reasonable.dt_mon &&
+ (dt_hardware.dt_day < dt_reasonable.dt_day ||
+ (dt_hardware.dt_day == dt_reasonable.dt_day &&
+ (dt_hardware.dt_hour < dt_reasonable.dt_hour ||
+ (dt_hardware.dt_hour == dt_reasonable.dt_hour &&
+ (dt_hardware.dt_min < dt_reasonable.dt_min ||
+ (dt_hardware.dt_min == dt_reasonable.dt_min &&
+ (dt_hardware.dt_sec < dt_reasonable.dt_sec))))))))) {
+ dt_hardware.dt_year = dt_reasonable.dt_year + 1;
+ } else {
+ dt_hardware.dt_year = dt_reasonable.dt_year;
+ }
+
+ /* convert the hardware date into a time: */
+ tv->tv_sec = clock_ymdhms_to_secs(&dt_hardware);
+ tv->tv_usec = 0;
+
+ /*
+ * Make a reasonable effort to see if a leap day has passed
+ * that we need to account for. This does the right thing
+ * only when the system was shut down before a leap day, and
+ * it is now after that leap day. It doesn't do the right
+ * thing when a leap day happened while the machine was last
+ * up. When that happens, the hardware clock becomes
+ * instantly wrong forever, until it gets fixed for some
+ * reason. Use NTP to deal.
+ */
+
+ /*
+ * This may have happened if the hardware says we're into
+ * March in the following year. Check that following year for
+ * a leap day.
+ */
+ if (dt_hardware.dt_year > dt_reasonable.dt_year &&
+ dt_hardware.dt_mon >= 3) {
+ leap_year = dt_hardware.dt_year;
+ }
+
+ /*
+ * This may have happened if the hardware says we're in the
+ * following year, and the system was shut down before March
+ * the previous year. check that previous year for a leap
+ * day.
+ */
+ else if (dt_hardware.dt_year > dt_reasonable.dt_year &&
+ dt_reasonable.dt_mon < 3) {
+ leap_year = dt_reasonable.dt_year;
+ }
+
+ /*
+ * This may have happened if the hardware says we're in the
+ * same year, but we weren't to March before, and we're in or
+ * past March now. Check this year for a leap day.
+ */
+ else if (dt_hardware.dt_year == dt_reasonable.dt_year
+ && dt_reasonable.dt_mon < 3
+ && dt_hardware.dt_mon >= 3) {
+ leap_year = dt_reasonable.dt_year;
+ }
+
+ /*
+ * Otherwise, no leap year to check.
+ */
+ else {
+ leap_year = 0;
+ }
+
+ /* Do the real leap day check. */
+ had_leap_day = 0;
+ if (leap_year > 0) {
+ if ((leap_year & 3) == 0) {
+ had_leap_day = 1;
+ if ((leap_year % 100) == 0) {
+ had_leap_day = 0;
+ if ((leap_year % 400) == 0)
+ had_leap_day = 1;
+ }
+ }
+ }
+
+ /*
+ * If we had a leap day, adjust the value we will return, and
+ * also update the hardware clock.
+ */
+ /*
+ * XXX - Since this update just writes back a corrected
+ * version of what we read out above, we lose whatever
+ * amount of time the clock has advanced since that read.
+ * Use NTP to deal.
+ */
+ if (had_leap_day) {
+ tv->tv_sec += SECDAY;
+ todr_settime(handle, tv);
+ }
+
+ return (0);
+}
+
+int
+mm58167_settime(handle, tv)
+ todr_chip_handle_t handle;
+ struct timeval *tv;
+{
+ struct mm58167_softc *sc = handle->cookie;
+ struct clock_ymdhms dt_hardware;
+ int s;
+ u_int8_t byte_value;
+
+ /* Convert the seconds into ymdhms. */
+ clock_secs_to_ymdhms(tv->tv_sec, &dt_hardware);
+
+ /* No interrupts while we're in the chip. */
+ s = splhigh();
+
+ /*
+ * Issue a GO command to reset everything less significant
+ * than the minutes to zero.
+ */
+ mm58167_write(sc, mm58167_go, 0xFF);
+
+ /* Load everything. */
+#define _MM58167_PUT(dt_f, mm_f) byte_value = TOBCD(dt_hardware.dt_f); mm58167_write(sc, mm_f, byte_value)
+ _MM58167_PUT(dt_mon, mm58167_mon);
+ _MM58167_PUT(dt_day, mm58167_day);
+ _MM58167_PUT(dt_hour, mm58167_hour);
+ _MM58167_PUT(dt_min, mm58167_min);
+ _MM58167_PUT(dt_sec, mm58167_sec);
+#undef _MM58167_PUT
+
+ splx(s);
+ return (0);
+}
+
+int
+mm58167_getcal(handle, vp)
+ todr_chip_handle_t handle;
+ int *vp;
+{
+ return (EOPNOTSUPP);
+}
+
+int
+mm58167_setcal(handle, v)
+ todr_chip_handle_t handle;
+ int v;
+{
+ return (EOPNOTSUPP);
+}
diff --git a/sys/dev/ic/mm58167var.h b/sys/dev/ic/mm58167var.h
new file mode 100644
index 00000000000..255ec7d0768
--- /dev/null
+++ b/sys/dev/ic/mm58167var.h
@@ -0,0 +1,92 @@
+/* $NetBSD: mm58167var.h,v 1.1 2001/04/10 12:50:18 fredette Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthew Fredette.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+#ifndef _MM58167VAR_H
+#define _MM58167VAR_H
+
+/*
+ * Driver support for the National Semiconductor MM58167
+ * time-of-day chip. See
+ * http://www.national.com/ds/MM/MM58167B.pdf for data sheets.
+ */
+
+struct mm58167_softc {
+ struct device mm58167_dev;
+
+ /* Pointers to bus_space */
+ bus_space_tag_t mm58167_regt;
+ bus_space_handle_t mm58167_regh;
+
+ /*
+ * Pointers to MM58167 registers. All of these values are in
+ * BCD.
+ */
+
+ /*
+ * The most significant digit of this first value is the
+ * milliseconds unit; least significant digit is undefined:
+ */
+ bus_size_t mm58167_msec_xxx;
+ /* both digits of this value make up centiseconds: */
+ bus_size_t mm58167_csec;
+ bus_size_t mm58167_sec;
+ bus_size_t mm58167_min;
+ bus_size_t mm58167_hour;
+ bus_size_t mm58167_wday;
+ bus_size_t mm58167_day;
+ bus_size_t mm58167_mon;
+
+ /*
+ * The MM58167 has compare latches that line up with the
+ * above, interrupt registers, etc., but we don't use them, so
+ * we don't mention them here.
+ */
+ bus_size_t mm58167_status; /* bad counter read status */
+ bus_size_t mm58167_go; /* GO - start at integral seconds */
+
+ /*
+ * We keep a TODR handle in the softc to save
+ * us from having to allocate it ourselves.
+ * However, only mm58167.c should know this.
+ */
+ struct todr_chip_handle _mm58167_todr_handle;
+};
+
+todr_chip_handle_t mm58167_attach __P((struct mm58167_softc *));
+
+#endif /* _MM58167VAR_H */