Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sparc/dev rtc (ds1287a) time of day clock at ebus.



details:   https://anonhg.NetBSD.org/src/rev/8c8346ec6449
branches:  trunk
changeset: 519088:8c8346ec6449
user:      uwe <uwe%NetBSD.org@localhost>
date:      Tue Dec 11 00:29:21 2001 +0000

description:
rtc (ds1287a) time of day clock at ebus.

diffstat:

 sys/arch/sparc/dev/rtc.c |  282 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 282 insertions(+), 0 deletions(-)

diffs (286 lines):

diff -r 62be3cefcfd3 -r 8c8346ec6449 sys/arch/sparc/dev/rtc.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/sparc/dev/rtc.c  Tue Dec 11 00:29:21 2001 +0000
@@ -0,0 +1,282 @@
+/*     $NetBSD: rtc.c,v 1.1 2001/12/11 00:29:21 uwe Exp $ */
+
+/*
+ * Copyright (c) 2001 Valeriy E. Ushakov
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+/*
+ * `rtc' is a DS1287A (== MC146818A) time-of-day clock at EBus.
+ * In Krups it's not used to store idprom so this driver doesn't
+ * support it.  Don't know about other ms-IIep systems.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#ifdef GPROF
+#include <sys/gmon.h>
+#endif
+
+#include <machine/bus.h>
+#include <machine/autoconf.h>
+
+#include <dev/clock_subr.h>
+#include <dev/ic/mc146818reg.h>
+
+#include <sparc/dev/ebusreg.h>
+#include <sparc/dev/ebusvar.h>
+
+struct rtc_ebus_softc {
+       struct device           sc_dev;
+
+       bus_space_tag_t         sc_bt;  /* parent bus tag */
+       bus_space_handle_t      sc_bh;  /* handle for registers */
+};
+
+static int     rtcmatch_ebus(struct device *, struct cfdata *, void *);
+static void    rtcattach_ebus(struct device *, struct device *, void *);
+
+struct cfattach rtc_ebus_ca = {
+       sizeof(struct rtc_ebus_softc), rtcmatch_ebus, rtcattach_ebus
+};
+
+
+/* XXX: global TOD clock handle (sparc/clock.c) */
+extern todr_chip_handle_t todr_handle;
+
+/* todr(9) methods */
+int rtc_gettime(todr_chip_handle_t, struct timeval *);
+int rtc_settime(todr_chip_handle_t, struct timeval *);
+int rtc_getcal(todr_chip_handle_t, int *);
+int rtc_setcal(todr_chip_handle_t, int);
+
+int rtc_auto_century_adjust = 1; /* XXX: do we ever want not to? */
+
+
+/*
+ * MD read/write functions declared in mc146818reg.h
+ */
+#define        RTC_ADDR        0
+#define        RTC_DATA        1
+
+u_int
+mc146818_read(cookie, reg)
+       void *cookie;
+       u_int reg;
+{
+       struct rtc_ebus_softc *sc = cookie;
+
+       bus_space_write_1(sc->sc_bt, sc->sc_bh, RTC_ADDR, reg);
+       return (bus_space_read_1(sc->sc_bt, sc->sc_bh, RTC_DATA));
+}
+
+void
+mc146818_write(cookie, reg, datum)
+       void *cookie;
+       u_int reg;
+       u_int datum;
+{
+       struct rtc_ebus_softc *sc = cookie;
+
+       bus_space_write_1(sc->sc_bt, sc->sc_bh, RTC_ADDR, reg);
+       bus_space_write_1(sc->sc_bt, sc->sc_bh, RTC_DATA, datum);
+}
+
+
+static int
+rtcmatch_ebus(parent, cf, aux)
+       struct device *parent;
+       struct cfdata *cf;
+       void *aux;
+{
+       struct ebus_attach_args *ea = aux;
+
+       return (strcmp(cf->cf_driver->cd_name, ea->ea_name) == 0);
+}
+
+static void
+rtcattach_ebus(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct rtc_ebus_softc *sc = (void *)self;
+       struct ebus_attach_args *ea = aux;
+
+       todr_chip_handle_t handle;
+
+       sc->sc_bt = ea->ea_bustag;
+       if (ebus_bus_map(sc->sc_bt,
+                        BUS_ADDR(ea->ea_reg[0].bar, ea->ea_reg[0].offset),
+                        ea->ea_reg[0].size,
+                        BUS_SPACE_MAP_LINEAR, 0,
+                        &sc->sc_bh) != 0)
+       {
+               printf(": can't map registers\n", self->dv_xname);
+               return;
+       }
+
+       /* XXX: no "model" property in Krups */
+       printf(": time-of-day clock\n");
+
+       /*
+        * Turn interrupts off (clear MC_REGB_?IE bits), just in case
+        * (although they shouldn't be wired to an interrupt
+        * controller on sparcs).
+        */
+       mc146818_write(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
+
+       /* setup our todr_handle */
+       handle = malloc(ALIGN(sizeof(struct todr_chip_handle)),
+                       M_DEVBUF, M_NOWAIT);
+
+       handle->cookie = sc;
+       handle->bus_cookie = NULL; /* unused */
+       handle->todr_gettime = rtc_gettime;
+       handle->todr_settime = rtc_settime;
+       handle->todr_getcal = rtc_getcal;
+       handle->todr_setcal = rtc_setcal;
+       handle->todr_setwen = NULL; /* not necessary, no idprom to protect */
+
+       todr_handle = handle;
+}
+
+
+/*
+ * Get time-of-day and convert to a `struct timeval'
+ * Return 0 on success; an error number otherwise.
+ */
+int
+rtc_gettime(handle, tv)
+       todr_chip_handle_t handle;
+       struct timeval *tv;
+{
+       struct rtc_ebus_softc *sc = handle->cookie;
+       struct clock_ymdhms dt;
+       u_int year;
+
+       /* update in progress; spin loop */
+       while (mc146818_read(sc, MC_REGA) & MC_REGA_UIP)
+               continue;
+
+       /* stop updates (XXX: do we need that???) */
+       mc146818_write(sc, MC_REGB,
+                      (mc146818_read(sc, MC_REGB) | MC_REGB_SET));
+
+       /* read time */
+       dt.dt_sec  = mc146818_read(sc, MC_SEC);
+       dt.dt_min  = mc146818_read(sc, MC_MIN);
+       dt.dt_hour = mc146818_read(sc, MC_HOUR);
+       dt.dt_day  = mc146818_read(sc, MC_DOM);
+       dt.dt_mon  = mc146818_read(sc, MC_MONTH);
+       year       = mc146818_read(sc, MC_YEAR);
+
+       /* reenable updates */
+       mc146818_write(sc, MC_REGB,
+                      (mc146818_read(sc, MC_REGB) & ~MC_REGB_SET));
+
+       /* year in the century 0..99: adjust to AD */
+       year += 1900;
+       if (year < POSIX_BASE_YEAR && rtc_auto_century_adjust != 0)
+               year += 100;
+       dt.dt_year = year;
+
+       /* simple sanity checks */
+       if (dt.dt_mon > 12 || dt.dt_day > 31
+           || dt.dt_hour >= 24 || dt.dt_min >= 60 || dt.dt_sec >= 60)
+               return (ERANGE);
+
+       tv->tv_sec = clock_ymdhms_to_secs(&dt);
+       tv->tv_usec = 0;
+       return (0);
+}
+
+/*
+ * Set the time-of-day clock based on the value of the `struct timeval' arg.
+ * Return 0 on success; an error number otherwise.
+ */
+int
+rtc_settime(handle, tv)
+       todr_chip_handle_t handle;
+       struct timeval *tv;
+{
+       struct rtc_ebus_softc *sc = handle->cookie;
+       struct clock_ymdhms dt;
+       u_int year;
+       u_int wday;
+
+       clock_secs_to_ymdhms(tv->tv_sec, &dt);
+
+       year = dt.dt_year - 1900;
+       if (year >= 100 && rtc_auto_century_adjust != 0)
+               year -= 100;
+
+       wday = dt.dt_wday;
+       if (wday == 0)
+               wday = 7;
+
+       /* stop updates */
+       mc146818_write(sc, MC_REGB,
+                      (mc146818_read(sc, MC_REGB) | MC_REGB_SET));
+
+       mc146818_write(sc, MC_SEC,   dt.dt_sec);
+       mc146818_write(sc, MC_MIN,   dt.dt_min);
+       mc146818_write(sc, MC_HOUR,  dt.dt_hour);
+       mc146818_write(sc, MC_DOW,   wday);
+       mc146818_write(sc, MC_DOM,   dt.dt_day);
+       mc146818_write(sc, MC_MONTH, dt.dt_mon);
+       mc146818_write(sc, MC_YEAR,  year);
+
+       /* reenable updates */
+       mc146818_write(sc, MC_REGB,
+                      (mc146818_read(sc, MC_REGB) & ~MC_REGB_SET));
+       return (0);
+}
+
+
+/*
+ * RTC does not support TOD clock calibration
+ */
+
+/* ARGSUSED */
+int
+rtc_getcal(handle, vp)
+       todr_chip_handle_t handle;
+       int *vp;
+{
+       return (EOPNOTSUPP);
+}
+
+/* ARGSUSED */
+int
+rtc_setcal(handle, v)
+       todr_chip_handle_t handle;
+       int v;
+{
+       return (EOPNOTSUPP);
+}



Home | Main Index | Thread Index | Old Index