1 /* $NetBSD: rtclock.c,v 1.11 2002/05/14 02:03:03 matt 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/param.h> 39 #include <sys/systm.h> 40 #include <sys/buf.h> 41 #include <sys/malloc.h> 42 #include <sys/proc.h> 43 #include <sys/reboot.h> 44 #include <sys/file.h> 45 #include <sys/kernel.h> 46 #include <sys/device.h> 47 48 #include <machine/bus.h> 49 50 #include <dev/clock_subr.h> 51 52 #include <arch/x68k/dev/rtclock_var.h> 53 #include <arch/x68k/dev/intiovar.h> 54 55 static time_t rtgettod __P((void)); 56 static int rtsettod __P((long)); 57 58 static int rtc_match __P((struct device *, struct cfdata *, void *)); 59 static void rtc_attach __P((struct device *, struct device *, void *)); 60 61 int rtclockinit __P((void)); 62 63 struct cfattach rtc_ca = { 64 sizeof(struct rtc_softc), rtc_match, rtc_attach 65 }; 66 67 static int 68 rtc_match(parent, cf, aux) 69 struct device *parent; 70 struct cfdata *cf; 71 void *aux; 72 { 73 struct intio_attach_args *ia = aux; 74 75 if (strcmp (ia->ia_name, "rtc") != 0) 76 return (0); 77 if (cf->cf_unit != 0) 78 return (0); 79 80 /* fixed address */ 81 if (ia->ia_addr != RTC_ADDR) 82 return (0); 83 if (ia->ia_intr != -1) 84 return (0); 85 86 return (1); 87 } 88 89 90 static struct rtc_softc *rtc; /* XXX: softc cache */ 91 92 static void 93 rtc_attach(parent, self, aux) 94 struct device *parent, *self; 95 void *aux; 96 { 97 struct rtc_softc *sc = (struct rtc_softc *)self; 98 struct intio_attach_args *ia = aux; 99 int r; 100 101 ia->ia_size = 0x20; 102 r = intio_map_allocate_region (parent, ia, INTIO_MAP_ALLOCATE); 103 #ifdef DIAGNOSTIC 104 if (r) 105 panic ("IO map for RTC corruption??"); 106 #endif 107 108 109 sc->sc_bst = ia->ia_bst; 110 bus_space_map(sc->sc_bst, ia->ia_addr, 0x2000, 0, &sc->sc_bht); 111 rtc = sc; 112 113 rtclockinit(); 114 printf (": RP5C15\n"); 115 } 116 117 118 119 /* 120 * x68k/clock.c calls thru the get/set tod vector, if it is set, to read 121 * the realtime clock. 122 */ 123 124 int 125 rtclockinit() 126 { 127 if (rtgettod()) { 128 gettod = rtgettod; 129 settod = rtsettod; 130 } else { 131 return 0; 132 } 133 return 1; 134 } 135 136 static time_t 137 rtgettod() 138 { 139 struct clock_ymdhms dt; 140 141 /* hold clock */ 142 RTC_WRITE(RTC_MODE, RTC_HOLD_CLOCK); 143 144 /* read it */ 145 dt.dt_sec = RTC_REG(RTC_SEC10) * 10 + RTC_REG(RTC_SEC); 146 dt.dt_min = RTC_REG(RTC_MIN10) * 10 + RTC_REG(RTC_MIN); 147 dt.dt_hour = RTC_REG(RTC_HOUR10) * 10 + RTC_REG(RTC_HOUR); 148 dt.dt_day = RTC_REG(RTC_DAY10) * 10 + RTC_REG(RTC_DAY); 149 dt.dt_mon = RTC_REG(RTC_MON10) * 10 + RTC_REG(RTC_MON); 150 dt.dt_year = RTC_REG(RTC_YEAR10) * 10 + RTC_REG(RTC_YEAR) 151 +RTC_BASE_YEAR; 152 153 /* let it run again.. */ 154 RTC_WRITE(RTC_MODE, RTC_FREE_CLOCK); 155 156 #ifdef DIAGNOSTIC 157 range_test0(dt.dt_hour, 23); 158 range_test(dt.dt_day, 1, 31); 159 range_test(dt.dt_mon, 1, 12); 160 range_test(dt.dt_year, RTC_BASE_YEAR, RTC_BASE_YEAR+100-1); 161 #endif 162 163 return clock_ymdhms_to_secs (&dt) + rtc_offset * 60; 164 } 165 166 static int 167 rtsettod (tim) 168 time_t tim; 169 { 170 struct clock_ymdhms dt; 171 u_char sec1, sec2; 172 u_char min1, min2; 173 u_char hour1, hour2; 174 u_char day1, day2; 175 u_char mon1, mon2; 176 u_char year1, year2; 177 178 clock_secs_to_ymdhms (tim - rtc_offset * 60, &dt); 179 180 /* prepare values to be written to clock */ 181 sec1 = dt.dt_sec / 10; 182 sec2 = dt.dt_sec % 10; 183 min1 = dt.dt_min / 10; 184 min2 = dt.dt_min % 10; 185 hour1 = dt.dt_hour / 10; 186 hour2 = dt.dt_hour % 10; 187 188 day1 = dt.dt_day / 10; 189 day2 = dt.dt_day % 10; 190 mon1 = dt.dt_mon / 10; 191 mon2 = dt.dt_mon % 10; 192 year1 = (dt.dt_year - RTC_BASE_YEAR) / 10; 193 year2 = dt.dt_year % 10; 194 195 RTC_WRITE(RTC_MODE, RTC_HOLD_CLOCK); 196 RTC_WRITE(RTC_SEC10, sec1); 197 RTC_WRITE(RTC_SEC, sec2); 198 RTC_WRITE(RTC_MIN10, min1); 199 RTC_WRITE(RTC_MIN, min2); 200 RTC_WRITE(RTC_HOUR10, hour1); 201 RTC_WRITE(RTC_HOUR, hour2); 202 RTC_WRITE(RTC_DAY10, day1); 203 RTC_WRITE(RTC_DAY, day2); 204 RTC_WRITE(RTC_MON10, mon1); 205 RTC_WRITE(RTC_MON, mon2); 206 RTC_WRITE(RTC_YEAR10, year1); 207 RTC_WRITE(RTC_YEAR, year2); 208 RTC_WRITE(RTC_MODE, RTC_FREE_CLOCK); 209 210 return 1; 211 } 212