xref: /openbsd/sys/arch/sparc64/dev/rtc.c (revision 404b540a)
1 /*	$OpenBSD: rtc.c,v 1.7 2009/01/07 13:01:39 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  * Copyright (c) 1994 Gordon W. Ross
7  * Copyright (c) 1993 Adam Glass
8  * Copyright (c) 1996 Paul Kranenburg
9  * Copyright (c) 1996
10  * 	The President and Fellows of Harvard College. All rights reserved.
11  *
12  * This software was developed by the Computer Systems Engineering group
13  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
14  * contributed to Berkeley.
15  *
16  * All advertising materials mentioning features or use of this software
17  * must display the following acknowledgement:
18  *	This product includes software developed by Harvard University.
19  *	This product includes software developed by the University of
20  *	California, Lawrence Berkeley Laboratory.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  *
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *	This product includes software developed by the University of
34  *	California, Berkeley and its contributors.
35  *	This product includes software developed by Paul Kranenburg.
36  *	This product includes software developed by Harvard University.
37  * 4. Neither the name of the University nor the names of its contributors
38  *    may be used to endorse or promote products derived from this software
39  *    without specific prior written permission.
40  *
41  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  */
54 
55 /*
56  * Driver for rtc device on Blade 1000, Fire V210, etc.
57  */
58 
59 #include <sys/param.h>
60 #include <sys/kernel.h>
61 #include <sys/device.h>
62 #include <sys/malloc.h>
63 #include <sys/proc.h>
64 #include <sys/signalvar.h>
65 #include <sys/systm.h>
66 
67 #include <machine/bus.h>
68 #include <machine/autoconf.h>
69 
70 #include <dev/clock_subr.h>
71 #include <dev/ic/mc146818reg.h>
72 
73 #include <sparc64/dev/ebusreg.h>
74 #include <sparc64/dev/ebusvar.h>
75 
76 /*
77  * Register definitions for the Texas Instruments bq4802.
78  */
79 
80 #define BQ4802_SEC		0x00	/* Seconds. */
81 #define BQ4802_MIN		0x02	/* Minutes. */
82 #define BQ4802_HOUR		0x04	/* Hours. */
83 #define BQ4802_DAY		0x06	/* Day (01-31). */
84 #define BQ4802_DOW		0x08	/* Day of week (01-07). */
85 #define BQ4802_MONTH		0x09	/* Month (01-12). */
86 #define BQ4802_YEAR		0x0a	/* Year (00-99). */
87 #define BQ4802_CENTURY		0x0f	/* Century (00-99). */
88 
89 #define BQ4802_CTRL		0x0e	/* Control. */
90 #define   BQ4802_24HR		0x02	/* 24-hour mode. */
91 #define   BQ4802_UTI		0x08	/* Update transfer inhibit. */
92 
93 extern todr_chip_handle_t todr_handle;
94 
95 struct rtc_softc {
96 	struct device		sc_dv;
97 	bus_space_tag_t		sc_iot;
98 	bus_space_handle_t	sc_ioh;
99 	struct intrhand		*sc_ih;
100 };
101 
102 int	rtc_match(struct device *, void *, void *);
103 void	rtc_attach(struct device *, struct device *, void *);
104 
105 struct cfattach rtc_ca = {
106 	sizeof(struct rtc_softc), rtc_match, rtc_attach
107 };
108 
109 struct cfdriver rtc_cd = {
110 	NULL, "rtc", DV_DULL
111 };
112 
113 int rtc_intr(void *arg);
114 
115 u_int8_t rtc_read_reg(struct rtc_softc *, bus_size_t);
116 void rtc_write_reg(struct rtc_softc *sc, bus_size_t, u_int8_t);
117 
118 int rtc_gettime(todr_chip_handle_t, struct timeval *);
119 int rtc_settime(todr_chip_handle_t, struct timeval *);
120 int rtc_bq4802_gettime(todr_chip_handle_t, struct timeval *);
121 int rtc_bq4802_settime(todr_chip_handle_t, struct timeval *);
122 int rtc_getcal(todr_chip_handle_t, int *);
123 int rtc_setcal(todr_chip_handle_t, int);
124 
125 int
126 rtc_match(struct device *parent, void *cf, void *aux)
127 {
128 	struct ebus_attach_args *ea = aux;
129 
130 	if (strcmp("rtc", ea->ea_name) == 0)
131 		return (1);
132 	return (0);
133 }
134 
135 void
136 rtc_attach(struct device *parent, struct device *self, void *aux)
137 {
138 	struct rtc_softc *sc = (void *)self;
139 	struct ebus_attach_args *ea = aux;
140 	todr_chip_handle_t handle;
141 	char *model;
142 	u_int8_t csr;
143 
144 	if (ebus_bus_map(ea->ea_iotag, 0,
145 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
146 	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
147 		sc->sc_iot = ea->ea_iotag;
148 	} else if (ebus_bus_map(ea->ea_memtag, 0,
149 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
150 	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
151 		sc->sc_iot = ea->ea_memtag;
152 	} else {
153 		printf("%s: can't map register\n", self->dv_xname);
154 		return;
155 	}
156 
157 	model = getpropstring(ea->ea_node, "model");
158 	if (*model == '\0')
159 		model = getpropstring(ea->ea_node, "compatible");
160 	printf(": %s\n", *model != '\0' != 0 ? model : "unknown");
161 
162 	/* Setup our todr_handle */
163 	handle = malloc(sizeof(struct todr_chip_handle), M_DEVBUF, M_NOWAIT);
164 	if (handle == NULL)
165 		panic("couldn't allocate todr_handle");
166 	handle->cookie = sc;
167 	handle->todr_gettime = rtc_gettime;
168 	handle->todr_settime = rtc_settime;
169 	handle->todr_getcal = rtc_getcal;
170 	handle->todr_setcal = rtc_setcal;
171 
172 	handle->bus_cookie = NULL;
173 	handle->todr_setwen = NULL;
174 	todr_handle = handle;
175 
176 	/* The bq4802 is not compatible with the mc146818. */
177 	if (strcmp(model, "bq4802") == 0) {
178 		handle->todr_gettime = rtc_bq4802_gettime;
179 		handle->todr_settime = rtc_bq4802_settime;
180 
181 		/* Turn on 24-hour mode. */
182 		csr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, BQ4802_CTRL);
183 		csr |= BQ4802_24HR;
184 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, BQ4802_CTRL, csr);
185 		return;
186 	}
187 
188 	/*
189 	 * Turn interrupts off, just in case. (Although they shouldn't
190 	 * be wired to an interrupt controller on sparcs).
191 	 */
192 	rtc_write_reg(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
193 
194 	/*
195 	 * On ds1287 models (which really are ns87317 chips), the
196 	 * interrupt is wired to the powerbutton.
197 	 */
198 	if (strcmp(model, "ds1287") == 0 && ea->ea_nintrs > 0) {
199 		sc->sc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0],
200 		    IPL_BIO, 0, rtc_intr, sc, self->dv_xname);
201 		if (sc->sc_ih == NULL) {
202 			printf("%s: can't establish interrupt\n",
203 			    self->dv_xname);
204 		}
205 	}
206 }
207 
208 int
209 rtc_intr(void *arg)
210 {
211 	extern int kbd_reset;
212 
213 	if (kbd_reset == 1) {
214 		kbd_reset = 0;
215 		psignal(initproc, SIGUSR2);
216 	}
217 	return (1);
218 }
219 
220 /*
221  * Register access is indirect, through an address and data port.
222  */
223 
224 #define	RTC_ADDR	0
225 #define	RTC_DATA	1
226 
227 u_int8_t
228 rtc_read_reg(struct rtc_softc *sc, bus_size_t reg)
229 {
230 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR, reg);
231 	return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA));
232 }
233 
234 void
235 rtc_write_reg(struct rtc_softc *sc, bus_size_t reg, u_int8_t val)
236 {
237 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR, reg);
238 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA, val);
239 }
240 
241 /*
242  * RTC todr routines.
243  */
244 
245 /*
246  * Get time-of-day and convert to a `struct timeval'
247  * Return 0 on success; an error number otherwise.
248  */
249 int
250 rtc_gettime(todr_chip_handle_t handle, struct timeval *tv)
251 {
252 	struct rtc_softc *sc = handle->cookie;
253 	struct clock_ymdhms dt;
254 	int year;
255 	u_int8_t csr;
256 
257 	/* Stop updates. */
258 	csr = rtc_read_reg(sc, MC_REGB);
259 	csr |= MC_REGB_SET;
260 	rtc_write_reg(sc, MC_REGB, csr);
261 
262 	/* Read time */
263 	dt.dt_sec = rtc_read_reg(sc, MC_SEC);
264 	dt.dt_min = rtc_read_reg(sc, MC_MIN);
265 	dt.dt_hour = rtc_read_reg(sc, MC_HOUR);
266 	dt.dt_day = rtc_read_reg(sc, MC_DOM);
267 	dt.dt_wday = rtc_read_reg(sc, MC_DOW);
268 	dt.dt_mon = rtc_read_reg(sc, MC_MONTH);
269 	year = rtc_read_reg(sc, MC_YEAR);
270 
271 	if ((year += 1900) < POSIX_BASE_YEAR)
272 		year += 100;
273 
274 	dt.dt_year = year;
275 
276 	/* time wears on */
277 	csr = rtc_read_reg(sc, MC_REGB);
278 	csr &= ~MC_REGB_SET;
279 	rtc_write_reg(sc, MC_REGB, csr);
280 
281 	/* simple sanity checks */
282 	if (dt.dt_mon > 12 || dt.dt_day > 31 ||
283 	    dt.dt_hour >= 24 || dt.dt_min >= 60 || dt.dt_sec >= 60)
284 		return (1);
285 
286 	tv->tv_sec = clock_ymdhms_to_secs(&dt);
287 	tv->tv_usec = 0;
288 	return (0);
289 }
290 
291 /*
292  * Set the time-of-day clock based on the value of the `struct timeval' arg.
293  * Return 0 on success; an error number otherwise.
294  */
295 int
296 rtc_settime(todr_chip_handle_t handle, struct timeval *tv)
297 {
298 	struct rtc_softc *sc = handle->cookie;
299 	struct clock_ymdhms dt;
300 	u_int8_t csr;
301 	int year;
302 
303 	/* Note: we ignore `tv_usec' */
304 	clock_secs_to_ymdhms(tv->tv_sec, &dt);
305 
306 	year = dt.dt_year % 100;
307 
308 	/* enable write */
309 	csr = rtc_read_reg(sc, MC_REGB);
310 	csr |= MC_REGB_SET;
311 	rtc_write_reg(sc, MC_REGB, csr);
312 
313 	rtc_write_reg(sc, MC_SEC, dt.dt_sec);
314 	rtc_write_reg(sc, MC_MIN, dt.dt_min);
315 	rtc_write_reg(sc, MC_HOUR, dt.dt_hour);
316 	rtc_write_reg(sc, MC_DOW, dt.dt_wday);
317 	rtc_write_reg(sc, MC_DOM, dt.dt_day);
318 	rtc_write_reg(sc, MC_MONTH, dt.dt_mon);
319 	rtc_write_reg(sc, MC_YEAR, year);
320 
321 	/* load them up */
322 	csr = rtc_read_reg(sc, MC_REGB);
323 	csr &= ~MC_REGB_SET;
324 	rtc_write_reg(sc, MC_REGB, csr);
325 	return (0);
326 }
327 
328 /*
329  * Get time-of-day and convert to a `struct timeval'
330  * Return 0 on success; an error number otherwise.
331  */
332 int
333 rtc_bq4802_gettime(todr_chip_handle_t handle, struct timeval *tv)
334 {
335 	struct rtc_softc *sc = handle->cookie;
336 	struct clock_ymdhms dt;
337 	bus_space_tag_t iot = sc->sc_iot;
338 	bus_space_handle_t ioh = sc->sc_ioh;
339 	u_int8_t csr;
340 
341 	/* Stop updates. */
342 	csr = bus_space_read_1(iot, ioh, BQ4802_CTRL);
343 	csr |= BQ4802_UTI;
344 	bus_space_write_1(iot, ioh, BQ4802_CTRL, csr);
345 
346 	/* Read time */
347 	dt.dt_sec = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_SEC));
348 	dt.dt_min = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_MIN));
349 	dt.dt_hour = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_HOUR));
350 	dt.dt_day = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_DAY));
351 	dt.dt_wday = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_DOW));
352 	dt.dt_mon = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_MONTH));
353 	dt.dt_year = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_YEAR)) +
354 	    FROMBCD(bus_space_read_1(iot, ioh, BQ4802_CENTURY)) * 100;
355 
356 	/* time wears on */
357 	csr = bus_space_read_1(iot, ioh, BQ4802_CTRL);
358 	csr &= ~BQ4802_UTI;
359 	bus_space_write_1(iot, ioh, BQ4802_CTRL, csr);
360 
361 	/* simple sanity checks */
362 	if (dt.dt_mon > 12 || dt.dt_day > 31 ||
363 	    dt.dt_hour >= 24 || dt.dt_min >= 60 || dt.dt_sec >= 60)
364 		return (1);
365 
366 	tv->tv_sec = clock_ymdhms_to_secs(&dt);
367 	tv->tv_usec = 0;
368 	return (0);
369 }
370 
371 /*
372  * Set the time-of-day clock based on the value of the `struct timeval' arg.
373  * Return 0 on success; an error number otherwise.
374  */
375 int
376 rtc_bq4802_settime(todr_chip_handle_t handle, struct timeval *tv)
377 {
378 	struct rtc_softc *sc = handle->cookie;
379 	struct clock_ymdhms dt;
380 	bus_space_tag_t iot = sc->sc_iot;
381 	bus_space_handle_t ioh = sc->sc_ioh;
382 	u_int8_t csr;
383 
384 	/* Note: we ignore `tv_usec' */
385 	clock_secs_to_ymdhms(tv->tv_sec, &dt);
386 
387 	/* enable write */
388 	csr = bus_space_read_1(iot, ioh, BQ4802_CTRL);
389 	csr |= BQ4802_UTI;
390 	bus_space_write_1(iot, ioh, BQ4802_CTRL, csr);
391 
392 	bus_space_write_1(iot, ioh, BQ4802_SEC, TOBCD(dt.dt_sec));
393 	bus_space_write_1(iot, ioh, BQ4802_MIN, TOBCD(dt.dt_min));
394 	bus_space_write_1(iot, ioh, BQ4802_HOUR, TOBCD(dt.dt_hour));
395 	bus_space_write_1(iot, ioh, BQ4802_DOW, TOBCD(dt.dt_wday));
396 	bus_space_write_1(iot, ioh, BQ4802_DAY, TOBCD(dt.dt_day));
397 	bus_space_write_1(iot, ioh, BQ4802_MONTH, TOBCD(dt.dt_mon));
398 	bus_space_write_1(iot, ioh, BQ4802_YEAR, TOBCD(dt.dt_year % 100));
399 	bus_space_write_1(iot, ioh, BQ4802_CENTURY, TOBCD(dt.dt_year / 100));
400 
401 	/* load them up */
402 	csr = bus_space_read_1(iot, ioh, BQ4802_CTRL);
403 	csr &= ~BQ4802_UTI;
404 	bus_space_write_1(iot, ioh, BQ4802_CTRL, csr);
405 	return (0);
406 }
407 
408 int
409 rtc_getcal(todr_chip_handle_t handle, int *vp)
410 {
411 	return (EOPNOTSUPP);
412 }
413 
414 int
415 rtc_setcal(todr_chip_handle_t handle, int v)
416 {
417 	return (EOPNOTSUPP);
418 }
419