Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/i2c s390rtc(4), an RTC driver for the Seiko Instrume...



details:   https://anonhg.NetBSD.org/src/rev/15ccd2035a5d
branches:  trunk
changeset: 763803:15ccd2035a5d
user:      phx <phx%NetBSD.org@localhost>
date:      Mon Apr 04 17:58:40 2011 +0000

description:
s390rtc(4), an RTC driver for the Seiko Instruments S-35390A chip.

diffstat:

 sys/dev/i2c/files.i2c |    7 +-
 sys/dev/i2c/s390.c    |  249 ++++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/i2c/s390reg.h |   69 +++++++++++++
 3 files changed, 324 insertions(+), 1 deletions(-)

diffs (truncated from 347 to 300 lines):

diff -r 39de71400c0b -r 15ccd2035a5d sys/dev/i2c/files.i2c
--- a/sys/dev/i2c/files.i2c     Mon Apr 04 17:46:22 2011 +0000
+++ b/sys/dev/i2c/files.i2c     Mon Apr 04 17:58:40 2011 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.i2c,v 1.33 2011/02/14 08:50:39 hannken Exp $
+#      $NetBSD: files.i2c,v 1.34 2011/04/04 17:58:40 phx Exp $
 
 defflag        opt_i2cbus.h                            I2C_SCAN
 define i2cbus { }
@@ -58,6 +58,11 @@
 attach pcfrtc at iic
 file   dev/i2c/pcf8583.c                       pcfrtc
 
+# Seiko Instruments S-xx390A Real Time Clock
+device s390rtc
+attach s390rtc at iic
+file   dev/i2c/s390.c                          s390rtc
+
 # Atmel/Microchip 24Cxx Serial EEPROM
 define at24cxx_eeprom
 device seeprom
diff -r 39de71400c0b -r 15ccd2035a5d sys/dev/i2c/s390.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/i2c/s390.c        Mon Apr 04 17:58:40 2011 +0000
@@ -0,0 +1,249 @@
+/*     $NetBSD: s390.c,v 1.1 2011/04/04 17:58:40 phx Exp $     */
+
+/*-
+ * Copyright (c) 2011 Frank Wille.
+ * All rights reserved.
+ *
+ * Written by Frank Wille for The NetBSD Project.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: s390.c,v 1.1 2011/04/04 17:58:40 phx Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+
+#include <dev/clock_subr.h>
+
+#include <dev/i2c/i2cvar.h>
+#include <dev/i2c/s390reg.h>
+
+struct s390rtc_softc {
+       device_t sc_dev;
+       i2c_tag_t sc_tag;
+       i2c_addr_t sc_addr;
+       struct todr_chip_handle sc_todr;
+};
+
+static int s390rtc_match(device_t, cfdata_t, void *);
+static void s390rtc_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(s390rtc, sizeof(struct s390rtc_softc),
+    s390rtc_match, s390rtc_attach, NULL, NULL);
+
+static int s390rtc_gettime(struct todr_chip_handle *, struct timeval *);
+static int s390rtc_settime(struct todr_chip_handle *, struct timeval *);
+static int s390rtc_clock_read(struct s390rtc_softc *, struct clock_ymdhms *);
+static int s390rtc_clock_write(struct s390rtc_softc *, struct clock_ymdhms *);
+static int s390rtc_read(struct s390rtc_softc *, int, uint8_t *, size_t);
+static int s390rtc_write(struct s390rtc_softc *, int, uint8_t *, size_t);
+static uint8_t bitreverse(uint8_t);
+
+static int
+s390rtc_match(device_t parent, cfdata_t cf, void *arg)
+{
+       struct i2c_attach_args *ia = arg;
+
+       if (ia->ia_addr == S390_ADDR)
+               return 1;
+       return 0;
+}
+
+static void
+s390rtc_attach(device_t parent, device_t self, void *arg)
+{
+       struct s390rtc_softc *sc = device_private(self);
+       struct i2c_attach_args *ia = arg;
+       uint8_t reg[1];
+
+       aprint_naive(": Real-time Clock\n");
+       aprint_normal(": Seiko Instruments 35390A Real-time Clock\n");
+
+       sc->sc_tag = ia->ia_tag;
+       sc->sc_addr = ia->ia_addr;
+       sc->sc_dev = self;
+
+       /* Reset the chip and turn on 24h mode, after power-off or battery. */
+       if (!s390rtc_read(sc, S390_STATUS1, reg, sizeof(reg)))
+               return;
+       if (reg[0] & (S390_ST1_POC | S390_ST1_BLD)) {
+               reg[0] |= S390_ST1_24H | S390_ST1_RESET;
+               if (!s390rtc_write(sc, S390_STATUS1, reg, sizeof(reg)))
+                       return;
+       }
+
+       /* Disable the test mode, when enabled. */
+       if (!s390rtc_read(sc, S390_STATUS2, reg, sizeof(reg)))
+               return;
+       if ((reg[0] & S390_ST2_TEST)) {
+               reg[0] &= ~S390_ST2_TEST;
+               if (!s390rtc_write(sc, S390_STATUS2, reg, sizeof(reg)))
+                       return;
+       }
+
+       sc->sc_todr.cookie = sc;
+       sc->sc_todr.todr_gettime = s390rtc_gettime;
+       sc->sc_todr.todr_settime = s390rtc_settime;
+       sc->sc_todr.todr_setwen = NULL;
+       todr_attach(&sc->sc_todr);
+}
+
+static int
+s390rtc_gettime(struct todr_chip_handle *ch, struct timeval *tv)
+{
+       struct s390rtc_softc *sc = ch->cookie;
+       struct clock_ymdhms dt;
+
+       memset(&dt, 0, sizeof(dt));
+
+       if (!s390rtc_clock_read(sc, &dt))
+               return -1;
+
+       tv->tv_sec = clock_ymdhms_to_secs(&dt);
+       tv->tv_usec = 0;
+
+       return 0;
+}
+
+static int
+s390rtc_settime(struct todr_chip_handle *ch, struct timeval *tv)
+{
+       struct s390rtc_softc *sc = ch->cookie;
+       struct clock_ymdhms dt;
+
+       clock_secs_to_ymdhms(tv->tv_sec, &dt);
+
+       if (!s390rtc_clock_write(sc, &dt))
+               return -1;
+
+       return 0;
+}
+
+static int
+s390rtc_clock_read(struct s390rtc_softc *sc, struct clock_ymdhms *dt)
+{
+       uint8_t bcd[S390_RT1_NBYTES];
+
+       if (!s390rtc_read(sc, S390_REALTIME1, bcd, S390_RT1_NBYTES))
+               return 0;
+
+       /*
+        * Convert the register values into something useable.
+        */
+       dt->dt_sec = FROMBCD(bcd[S390_RT1_SECOND]);
+       dt->dt_min = FROMBCD(bcd[S390_RT1_MINUTE]);
+       dt->dt_hour = FROMBCD(bcd[S390_RT1_HOUR] & 0x3f);
+       dt->dt_day = FROMBCD(bcd[S390_RT1_DAY]);
+       dt->dt_mon = FROMBCD(bcd[S390_RT1_MONTH]);
+       dt->dt_year = FROMBCD(bcd[S390_RT1_YEAR]) + 2000;
+
+       return 1;
+}
+
+static int
+s390rtc_clock_write(struct s390rtc_softc *sc, struct clock_ymdhms *dt)
+{
+       uint8_t bcd[S390_RT1_NBYTES];
+
+       /*
+        * Convert our time representation into something the S-xx390
+        * can understand.
+        */
+       bcd[S390_RT1_SECOND] = TOBCD(dt->dt_sec);
+       bcd[S390_RT1_MINUTE] = TOBCD(dt->dt_min);
+       bcd[S390_RT1_HOUR] = TOBCD(dt->dt_hour);
+       bcd[S390_RT1_DAY] = TOBCD(dt->dt_day);
+       bcd[S390_RT1_WDAY] = TOBCD(dt->dt_wday);
+       bcd[S390_RT1_MONTH] = TOBCD(dt->dt_mon);
+       bcd[S390_RT1_YEAR] = TOBCD(dt->dt_year % 100);
+
+       return s390rtc_write(sc, S390_REALTIME1, bcd, S390_RT1_NBYTES);
+}
+
+static int
+s390rtc_read(struct s390rtc_softc *sc, int reg, uint8_t *buf, size_t len)
+{
+       int i;
+
+       if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
+               aprint_error_dev(sc->sc_dev,
+                   "%s: failed to acquire I2C bus\n", __func__);
+               return 0;
+       }
+
+       if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr + reg,
+           NULL, 0, buf, len, I2C_F_POLL)) {
+               iic_release_bus(sc->sc_tag, I2C_F_POLL);
+               aprint_error_dev(sc->sc_dev,
+                   "%s: failed to read reg%d\n", __func__, reg);
+               return 0;
+       }
+
+       iic_release_bus(sc->sc_tag, I2C_F_POLL);
+
+       /* this chip returns each byte in reverse order */
+       for (i = 0; i < len; i++)
+               buf[i] = bitreverse(buf[i]);
+
+       return 1;
+}
+
+static int
+s390rtc_write(struct s390rtc_softc *sc, int reg, uint8_t *buf, size_t len)
+{
+       int i;
+
+       if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
+               aprint_error_dev(sc->sc_dev,
+                   "%s: failed to acquire I2C bus\n", __func__);
+               return 0;
+       }
+
+       /* this chip expects each byte in reverse order */
+       for (i = 0; i < len; i++)
+               buf[i] = bitreverse(buf[i]);
+
+       if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr + reg,
+           NULL, 0, buf, len, I2C_F_POLL)) {
+               iic_release_bus(sc->sc_tag, I2C_F_POLL);
+               aprint_error_dev(sc->sc_dev,
+                   "%s: failed to write reg%d\n", __func__, reg);
+               return 0;
+       }
+
+       iic_release_bus(sc->sc_tag, I2C_F_POLL);
+       return 1;
+}
+
+static uint8_t
+bitreverse(uint8_t x)
+{
+       static unsigned char nibbletab[16] = {
+               0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
+       };
+
+       return (nibbletab[x & 15] << 4) | nibbletab[x >> 4];
+}
diff -r 39de71400c0b -r 15ccd2035a5d sys/dev/i2c/s390reg.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/i2c/s390reg.h     Mon Apr 04 17:58:40 2011 +0000
@@ -0,0 +1,69 @@
+/*     $NetBSD: s390reg.h,v 1.1 2011/04/04 17:58:40 phx Exp $  */
+
+/*-
+ * Copyright (c) 2011 Frank Wille.
+ * All rights reserved.
+ *
+ * Written by Frank Wille for The NetBSD Project.
+ *
+ * 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.
+ *
+ * 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



Home | Main Index | Thread Index | Old Index