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