1 /* $NetBSD: rtclock.c,v 1.25 2023/12/20 00:40:44 thorpej Exp $ */ 2 3 /* 4 * Copyright 1993, 1994 Masaru Oki 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Masaru Oki. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * X680x0 internal real time clock interface 35 * alarm is not supported. 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: rtclock.c,v 1.25 2023/12/20 00:40:44 thorpej Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/buf.h> 44 #include <sys/proc.h> 45 #include <sys/reboot.h> 46 #include <sys/file.h> 47 #include <sys/kernel.h> 48 #include <sys/device.h> 49 50 #include <machine/bus.h> 51 52 #include <dev/clock_subr.h> 53 54 #include <arch/x68k/dev/rtclock_var.h> 55 #include <arch/x68k/dev/intiovar.h> 56 57 static int rtgettod(todr_chip_handle_t, struct clock_ymdhms *); 58 static int rtsettod(todr_chip_handle_t, struct clock_ymdhms *); 59 60 static int rtc_match(device_t, cfdata_t, void *); 61 static void rtc_attach(device_t, device_t, void *); 62 63 CFATTACH_DECL_NEW(rtc, sizeof(struct rtc_softc), 64 rtc_match, rtc_attach, NULL, NULL); 65 66 static int rtc_attached; 67 68 static int 69 rtc_match(device_t parent, cfdata_t cf, void *aux) 70 { 71 struct intio_attach_args *ia = aux; 72 73 if (strcmp(ia->ia_name, "rtc") != 0) 74 return (0); 75 if (rtc_attached) 76 return (0); 77 78 /* fixed address */ 79 if (ia->ia_addr != RTC_ADDR) 80 return (0); 81 if (ia->ia_intr != -1) 82 return (0); 83 84 return (1); 85 } 86 87 static void 88 rtc_attach(device_t parent, device_t self, void *aux) 89 { 90 struct rtc_softc *sc = device_private(self); 91 struct intio_attach_args *ia = aux; 92 int r __diagused; 93 94 rtc_attached = 1; 95 96 ia->ia_size = 0x20; 97 r = intio_map_allocate_region(parent, ia, INTIO_MAP_ALLOCATE); 98 #ifdef DIAGNOSTIC 99 if (r) 100 panic("IO map for RTC corruption??"); 101 #endif 102 103 104 sc->sc_bst = ia->ia_bst; 105 bus_space_map(sc->sc_bst, ia->ia_addr, 0x2000, 0, &sc->sc_bht); 106 107 sc->sc_todr.cookie = sc; 108 sc->sc_todr.todr_gettime_ymdhms = rtgettod; 109 sc->sc_todr.todr_settime_ymdhms = rtsettod; 110 todr_attach(&sc->sc_todr); 111 112 aprint_normal(": RP5C15\n"); 113 } 114 115 static int 116 rtgettod(todr_chip_handle_t tch, struct clock_ymdhms *dt) 117 { 118 struct rtc_softc *rtc = tch->cookie; 119 120 /* hold clock */ 121 RTC_WRITE(RTC_MODE, RTC_HOLD_CLOCK); 122 123 /* read it */ 124 dt->dt_sec = RTC_REG(RTC_SEC10) * 10 + RTC_REG(RTC_SEC); 125 dt->dt_min = RTC_REG(RTC_MIN10) * 10 + RTC_REG(RTC_MIN); 126 dt->dt_hour = RTC_REG(RTC_HOUR10) * 10 + RTC_REG(RTC_HOUR); 127 dt->dt_day = RTC_REG(RTC_DAY10) * 10 + RTC_REG(RTC_DAY); 128 dt->dt_mon = RTC_REG(RTC_MON10) * 10 + RTC_REG(RTC_MON); 129 dt->dt_year = RTC_REG(RTC_YEAR10) * 10 + RTC_REG(RTC_YEAR) 130 +RTC_BASE_YEAR; 131 132 /* let it run again.. */ 133 RTC_WRITE(RTC_MODE, RTC_FREE_CLOCK); 134 135 return 0; 136 } 137 138 static int 139 rtsettod(todr_chip_handle_t tch, struct clock_ymdhms *dt) 140 { 141 struct rtc_softc *rtc = tch->cookie; 142 u_char sec1, sec2; 143 u_char min1, min2; 144 u_char hour1, hour2; 145 u_char day1, day2; 146 u_char mon1, mon2; 147 u_char year1, year2; 148 149 /* prepare values to be written to clock */ 150 sec1 = dt->dt_sec / 10; 151 sec2 = dt->dt_sec % 10; 152 min1 = dt->dt_min / 10; 153 min2 = dt->dt_min % 10; 154 hour1 = dt->dt_hour / 10; 155 hour2 = dt->dt_hour % 10; 156 157 day1 = dt->dt_day / 10; 158 day2 = dt->dt_day % 10; 159 mon1 = dt->dt_mon / 10; 160 mon2 = dt->dt_mon % 10; 161 year1 = (dt->dt_year - RTC_BASE_YEAR) / 10; 162 year2 = dt->dt_year % 10; 163 164 RTC_WRITE(RTC_MODE, RTC_HOLD_CLOCK); 165 RTC_WRITE(RTC_SEC10, sec1); 166 RTC_WRITE(RTC_SEC, sec2); 167 RTC_WRITE(RTC_MIN10, min1); 168 RTC_WRITE(RTC_MIN, min2); 169 RTC_WRITE(RTC_HOUR10, hour1); 170 RTC_WRITE(RTC_HOUR, hour2); 171 RTC_WRITE(RTC_DAY10, day1); 172 RTC_WRITE(RTC_DAY, day2); 173 RTC_WRITE(RTC_MON10, mon1); 174 RTC_WRITE(RTC_MON, mon2); 175 RTC_WRITE(RTC_YEAR10, year1); 176 RTC_WRITE(RTC_YEAR, year2); 177 RTC_WRITE(RTC_MODE, RTC_FREE_CLOCK); 178 179 return 0; 180 } 181