/* $NetBSD: s3c2440_rtc.c,v 1.3 2020/01/02 22:24:11 thorpej Exp $ */ /*-- * Copyright (c) 2012 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Fleischer * * 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 #include #include #include #include #include #include #include #include #include #ifdef SSRTC_DEBUG #define DPRINTF(s) do { printf s; } while (/*CONSTCOND*/0) #else #define DPRINTF(s) do {} while (/*CONSTCOND*/0) #endif /* As the RTC keeps track of Leap years, we need to use the right zero-year */ #define SSRTC_YEAR_ZERO 2000 struct ssrtc_softc { device_t sc_dev; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; struct todr_chip_handle sc_todr; }; static int ssrtc_match(device_t, cfdata_t, void *); static void ssrtc_attach(device_t, device_t, void *); CFATTACH_DECL_NEW(ssrtc, sizeof(struct ssrtc_softc), ssrtc_match, ssrtc_attach, NULL, NULL); static int ssrtc_todr_gettime_ymdhms(struct todr_chip_handle *, struct clock_ymdhms *); static int ssrtc_todr_settime_ymdhms(struct todr_chip_handle *, struct clock_ymdhms *); static int ssrtc_match(device_t parent, cfdata_t cf, void *aux) { return 1; } static void ssrtc_attach(device_t parent, device_t self, void *aux) { struct ssrtc_softc *sc = device_private(self); struct s3c2xx0_attach_args *sa = aux; sc->sc_dev = self; sc->sc_iot = sa->sa_iot; if (bus_space_map(sc->sc_iot, S3C2440_RTC_BASE, S3C2440_RTC_SIZE, 0, &sc->sc_ioh)) { aprint_error(": failed to map registers"); return; } aprint_normal(": RTC \n"); sc->sc_todr.cookie = sc; sc->sc_todr.todr_gettime = NULL; sc->sc_todr.todr_settime = NULL; sc->sc_todr.todr_gettime_ymdhms = ssrtc_todr_gettime_ymdhms; sc->sc_todr.todr_settime_ymdhms = ssrtc_todr_settime_ymdhms; sc->sc_todr.todr_setwen = NULL; todr_attach(&sc->sc_todr); } static int ssrtc_todr_gettime_ymdhms(struct todr_chip_handle *h, struct clock_ymdhms *dt) { struct ssrtc_softc *sc = h->cookie; uint8_t reg; reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_BCDSEC); DPRINTF(("BCDSEC: %02X\n", reg)); dt->dt_sec = bcdtobin(reg); reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_BCDMIN); DPRINTF(("BCDMIN: %02X\n", reg)); dt->dt_min = bcdtobin(reg); reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_BCDHOUR); DPRINTF(("BCDHOUR: %02X\n", reg)); dt->dt_hour = bcdtobin(reg); reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_BCDDATE); DPRINTF(("BCDDATE: %02X\n", reg)); dt->dt_day = bcdtobin(reg); reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_BCDDAY); DPRINTF(("BCDDAY: %02X\n", reg)); dt->dt_wday = bcdtobin(reg); reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_BCDMON); DPRINTF(("BCDMON: %02X\n", reg)); dt->dt_mon = bcdtobin(reg); reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_BCDYEAR); DPRINTF(("BCDYEAR: %02X\n", reg)); dt->dt_year = SSRTC_YEAR_ZERO + bcdtobin(reg); DPRINTF(("Seconds: %d\n", dt->dt_sec)); DPRINTF(("Minutes: %d\n", dt->dt_min)); DPRINTF(("Hour: %d\n", dt->dt_hour)); DPRINTF(("Mon: %d\n", dt->dt_mon)); DPRINTF(("Date: %d\n", dt->dt_day)); DPRINTF(("Day: %d\n", dt->dt_wday)); DPRINTF(("Year: %d\n", dt->dt_year)); return 0; } static int ssrtc_todr_settime_ymdhms(struct todr_chip_handle *h, struct clock_ymdhms *dt) { struct ssrtc_softc *sc = h->cookie; uint8_t reg; DPRINTF(("ssrtc_todr_settime")); /* Set RTCEN */ reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_RTCCON); bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_RTCCON, reg | RTCCON_RTCEN); bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_BCDSEC, bintobcd(dt->dt_sec)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_BCDMIN, bintobcd(dt->dt_min)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_BCDHOUR, bintobcd(dt->dt_hour)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_BCDDATE, bintobcd(dt->dt_day)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_BCDDAY, bintobcd(dt->dt_wday)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_BCDMON, bintobcd(dt->dt_mon)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_BCDYEAR, bintobcd(dt->dt_year-SSRTC_YEAR_ZERO)); /* Clear RTCEN */ reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_RTCCON); bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_RTCCON, reg & ~RTCCON_RTCEN); return 0; }