summaryrefslogtreecommitdiff
path: root/sys/arch/arm/footbridge/isa/dsrtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/arm/footbridge/isa/dsrtc.c')
-rw-r--r--sys/arch/arm/footbridge/isa/dsrtc.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/sys/arch/arm/footbridge/isa/dsrtc.c b/sys/arch/arm/footbridge/isa/dsrtc.c
new file mode 100644
index 00000000000..b909ed406e1
--- /dev/null
+++ b/sys/arch/arm/footbridge/isa/dsrtc.c
@@ -0,0 +1,279 @@
+/* $OpenBSD: dsrtc.c,v 1.1 2004/02/01 05:09:49 drahn Exp $ */
+/* $NetBSD: dsrtc.c,v 1.5 2003/03/23 14:12:26 chris Exp $ */
+
+/*
+ * Copyright (c) 1998 Mark Brinicombe.
+ * Copyright (c) 1998 Causality Limited.
+ * All rights reserved.
+ *
+ * Written by Mark Brinicombe, Causality Limited
+ *
+ * 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 Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CAUASLITY LIMITED ``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 CAUSALITY LIMITED 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/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+
+#include <machine/rtc.h>
+
+#include <arm/footbridge/todclockvar.h>
+#include <arm/footbridge/isa/ds1687reg.h>
+
+#include <dev/isa/isavar.h>
+
+#define NRTC_PORTS 2
+
+struct dsrtc_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+void dsrtcattach __P((struct device *parent, struct device *self, void *aux));
+int dsrtcmatch __P((struct device *parent, void *cf, void *aux));
+int ds1687_read __P((struct dsrtc_softc *sc, int addr));
+void ds1687_write __P((struct dsrtc_softc *sc, int addr, int data));
+int ds1687_ram_read __P((struct dsrtc_softc *sc, int addr));
+void ds1687_ram_write __P((struct dsrtc_softc *sc, int addr, int data));
+static void ds1687_bank_select __P((struct dsrtc_softc *, int));
+static int dsrtc_write __P((void *, rtc_t *));
+static int dsrtc_read __P((void *, rtc_t *));
+
+int
+ds1687_read(sc, addr)
+ struct dsrtc_softc *sc;
+ int addr;
+{
+
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr);
+ return(bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG));
+}
+
+void
+ds1687_write(sc, addr, data)
+ struct dsrtc_softc *sc;
+ int addr;
+ int data;
+{
+
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr);
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG, data);
+}
+
+static void
+ds1687_bank_select(sc, bank)
+ struct dsrtc_softc *sc;
+ int bank;
+{
+ int data;
+
+ data = ds1687_read(sc, RTC_REG_A);
+ data &= ~RTC_REG_A_BANK_MASK;
+ if (bank)
+ data |= RTC_REG_A_BANK1;
+ ds1687_write(sc, RTC_REG_A, data);
+}
+
+#if 0
+/* Nothing uses these yet */
+int
+ds1687_ram_read(sc, addr)
+ struct dsrtc_softc *sc;
+ int addr;
+{
+ if (addr < RTC_PC_RAM_SIZE)
+ return(ds1687_read(sc, RTC_PC_RAM_START + addr));
+
+ addr -= RTC_PC_RAM_SIZE;
+ if (addr < RTC_BANK0_RAM_SIZE)
+ return(ds1687_read(sc, RTC_BANK0_RAM_START + addr));
+
+ addr -= RTC_BANK0_RAM_SIZE;
+ if (addr < RTC_EXT_RAM_SIZE) {
+ int data;
+
+ ds1687_bank_select(sc, 1);
+ ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr);
+ data = ds1687_read(sc, RTC_EXT_RAM_DATA);
+ ds1687_bank_select(sc, 0);
+ return(data);
+ }
+ return(-1);
+}
+
+void
+ds1687_ram_write(sc, addr, val)
+ struct dsrtc_softc *sc;
+ int addr;
+ int val;
+{
+ if (addr < RTC_PC_RAM_SIZE)
+ return(ds1687_write(sc, RTC_PC_RAM_START + addr, val));
+
+ addr -= RTC_PC_RAM_SIZE;
+ if (addr < RTC_BANK0_RAM_SIZE)
+ return(ds1687_write(sc, RTC_BANK0_RAM_START + addr, val));
+
+ addr -= RTC_BANK0_RAM_SIZE;
+ if (addr < RTC_EXT_RAM_SIZE) {
+ ds1687_bank_select(sc, 1);
+ ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr);
+ ds1687_write(sc, RTC_EXT_RAM_DATA, val);
+ ds1687_bank_select(sc, 0);
+ }
+}
+#endif
+
+static int
+dsrtc_write(arg, rtc)
+ void *arg;
+ rtc_t *rtc;
+{
+ struct dsrtc_softc *sc = arg;
+
+ ds1687_write(sc, RTC_SECONDS, rtc->rtc_sec);
+ ds1687_write(sc, RTC_MINUTES, rtc->rtc_min);
+ ds1687_write(sc, RTC_HOURS, rtc->rtc_hour);
+ ds1687_write(sc, RTC_DAYOFMONTH, rtc->rtc_day);
+ ds1687_write(sc, RTC_MONTH, rtc->rtc_mon);
+ ds1687_write(sc, RTC_YEAR, rtc->rtc_year);
+ ds1687_bank_select(sc, 1);
+ ds1687_write(sc, RTC_CENTURY, rtc->rtc_cen);
+ ds1687_bank_select(sc, 0);
+ return(1);
+}
+
+static int
+dsrtc_read(arg, rtc)
+ void *arg;
+ rtc_t *rtc;
+{
+ struct dsrtc_softc *sc = arg;
+
+ rtc->rtc_micro = 0;
+ rtc->rtc_centi = 0;
+ rtc->rtc_sec = ds1687_read(sc, RTC_SECONDS);
+ rtc->rtc_min = ds1687_read(sc, RTC_MINUTES);
+ rtc->rtc_hour = ds1687_read(sc, RTC_HOURS);
+ rtc->rtc_day = ds1687_read(sc, RTC_DAYOFMONTH);
+ rtc->rtc_mon = ds1687_read(sc, RTC_MONTH);
+ rtc->rtc_year = ds1687_read(sc, RTC_YEAR);
+ ds1687_bank_select(sc, 1);
+ rtc->rtc_cen = ds1687_read(sc, RTC_CENTURY);
+ ds1687_bank_select(sc, 0);
+
+ return(1);
+}
+
+/* device and attach structures */
+struct cfattach ds1687rtc_ca = {
+ sizeof(struct dsrtc_softc), dsrtcmatch, dsrtcattach
+};
+
+struct cfdriver ds1687rtc_cd = {
+ NULL, "dsrtc", DV_DULL
+};
+
+/*
+ * dsrtcmatch()
+ *
+ * Validate the IIC address to make sure its an RTC we understand
+ */
+
+int
+dsrtcmatch(parent, cf, aux)
+ struct device *parent;
+ void *cf;
+ void *aux;
+{
+ struct isa_attach_args *ia = aux;
+
+#ifdef __NetBSD__
+ if (ia->ia_nio < 1 ||
+ ia->ia_iobase == -1)
+ return (0);
+
+ ia->ia_nio = 1;
+ ia->ia_io[0].ir_size = NRTC_PORTS;
+#else
+ ia->ia_iosize = NRTC_PORTS;
+#endif
+
+
+#if 0
+ ia->ia_niomem = 0;
+ ia->ia_nirq = 0;
+ ia->ia_ndrq = 0;
+#endif
+
+ return(1);
+}
+
+/*
+ * dsrtcattach()
+ *
+ * Attach the rtc device
+ */
+
+void
+dsrtcattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct dsrtc_softc *sc = (struct dsrtc_softc *)self;
+ struct isa_attach_args *ia = aux;
+ struct todclock_attach_args ta;
+
+ sc->sc_iot = ia->ia_iot;
+ if (bus_space_map(sc->sc_iot, ia->ia_iobase,
+ ia->ia_iosize, 0, &sc->sc_ioh)) {
+ printf(": cannot map I/O space\n");
+ return;
+ }
+
+ ds1687_write(sc, RTC_REG_A, RTC_REG_A_DV1);
+ ds1687_write(sc, RTC_REG_B, RTC_REG_B_BINARY | RTC_REG_B_24_HOUR);
+
+ if (!(ds1687_read(sc, RTC_REG_D) & RTC_REG_D_VRT))
+ printf(": lithium cell is dead, RTC unreliable");
+ printf("\n");
+
+ ta.ta_name = "todclock";
+ ta.ta_rtc_arg = sc;
+ ta.ta_rtc_write = dsrtc_write;
+ ta.ta_rtc_read = dsrtc_read;
+ ta.ta_flags = 0;
+ config_found(self, &ta, NULL);
+}
+
+/* End of dsrtc.c */