xref: /netbsd-src/sys/arch/x86/isa/rtc.c (revision 28b4250d7a034804d3ae4cd23d9a4546c63d4afe)
1*28b4250dSjakllsch /*	$NetBSD: rtc.c,v 1.3 2025/01/07 22:37:13 jakllsch Exp $	*/
23ac2dfe9Sbouyer 
33ac2dfe9Sbouyer /*-
43ac2dfe9Sbouyer  * Copyright (c) 1990 The Regents of the University of California.
53ac2dfe9Sbouyer  * All rights reserved.
63ac2dfe9Sbouyer  *
73ac2dfe9Sbouyer  * This code is derived from software contributed to Berkeley by
83ac2dfe9Sbouyer  * William Jolitz and Don Ahn.
93ac2dfe9Sbouyer  *
103ac2dfe9Sbouyer  * Redistribution and use in source and binary forms, with or without
113ac2dfe9Sbouyer  * modification, are permitted provided that the following conditions
123ac2dfe9Sbouyer  * are met:
133ac2dfe9Sbouyer  * 1. Redistributions of source code must retain the above copyright
143ac2dfe9Sbouyer  *    notice, this list of conditions and the following disclaimer.
153ac2dfe9Sbouyer  * 2. Redistributions in binary form must reproduce the above copyright
163ac2dfe9Sbouyer  *    notice, this list of conditions and the following disclaimer in the
173ac2dfe9Sbouyer  *    documentation and/or other materials provided with the distribution.
183ac2dfe9Sbouyer  * 3. Neither the name of the University nor the names of its contributors
193ac2dfe9Sbouyer  *    may be used to endorse or promote products derived from this software
203ac2dfe9Sbouyer  *    without specific prior written permission.
213ac2dfe9Sbouyer  *
223ac2dfe9Sbouyer  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
233ac2dfe9Sbouyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
243ac2dfe9Sbouyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
253ac2dfe9Sbouyer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
263ac2dfe9Sbouyer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
273ac2dfe9Sbouyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
283ac2dfe9Sbouyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
293ac2dfe9Sbouyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
303ac2dfe9Sbouyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
313ac2dfe9Sbouyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
323ac2dfe9Sbouyer  * SUCH DAMAGE.
333ac2dfe9Sbouyer  *
343ac2dfe9Sbouyer  *	@(#)clock.c	7.2 (Berkeley) 5/12/91
353ac2dfe9Sbouyer  */
363ac2dfe9Sbouyer /*-
373ac2dfe9Sbouyer  * Copyright (c) 1993, 1994 Charles M. Hannum.
383ac2dfe9Sbouyer  *
393ac2dfe9Sbouyer  * This code is derived from software contributed to Berkeley by
403ac2dfe9Sbouyer  * William Jolitz and Don Ahn.
413ac2dfe9Sbouyer  *
423ac2dfe9Sbouyer  * Redistribution and use in source and binary forms, with or without
433ac2dfe9Sbouyer  * modification, are permitted provided that the following conditions
443ac2dfe9Sbouyer  * are met:
453ac2dfe9Sbouyer  * 1. Redistributions of source code must retain the above copyright
463ac2dfe9Sbouyer  *    notice, this list of conditions and the following disclaimer.
473ac2dfe9Sbouyer  * 2. Redistributions in binary form must reproduce the above copyright
483ac2dfe9Sbouyer  *    notice, this list of conditions and the following disclaimer in the
493ac2dfe9Sbouyer  *    documentation and/or other materials provided with the distribution.
503ac2dfe9Sbouyer  * 3. All advertising materials mentioning features or use of this software
513ac2dfe9Sbouyer  *    must display the following acknowledgement:
523ac2dfe9Sbouyer  *	This product includes software developed by the University of
533ac2dfe9Sbouyer  *	California, Berkeley and its contributors.
543ac2dfe9Sbouyer  * 4. Neither the name of the University nor the names of its contributors
553ac2dfe9Sbouyer  *    may be used to endorse or promote products derived from this software
563ac2dfe9Sbouyer  *    without specific prior written permission.
573ac2dfe9Sbouyer  *
583ac2dfe9Sbouyer  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
593ac2dfe9Sbouyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
603ac2dfe9Sbouyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
613ac2dfe9Sbouyer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
623ac2dfe9Sbouyer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
633ac2dfe9Sbouyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
643ac2dfe9Sbouyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
653ac2dfe9Sbouyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
663ac2dfe9Sbouyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
673ac2dfe9Sbouyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
683ac2dfe9Sbouyer  * SUCH DAMAGE.
693ac2dfe9Sbouyer  *
703ac2dfe9Sbouyer  *	@(#)clock.c	7.2 (Berkeley) 5/12/91
713ac2dfe9Sbouyer  */
723ac2dfe9Sbouyer /*
733ac2dfe9Sbouyer  * Mach Operating System
743ac2dfe9Sbouyer  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
753ac2dfe9Sbouyer  * All Rights Reserved.
763ac2dfe9Sbouyer  *
773ac2dfe9Sbouyer  * Permission to use, copy, modify and distribute this software and its
783ac2dfe9Sbouyer  * documentation is hereby granted, provided that both the copyright
793ac2dfe9Sbouyer  * notice and this permission notice appear in all copies of the
803ac2dfe9Sbouyer  * software, derivative works or modified versions, and any portions
813ac2dfe9Sbouyer  * thereof, and that both notices appear in supporting documentation.
823ac2dfe9Sbouyer  *
833ac2dfe9Sbouyer  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
843ac2dfe9Sbouyer  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
853ac2dfe9Sbouyer  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
863ac2dfe9Sbouyer  *
873ac2dfe9Sbouyer  * Carnegie Mellon requests users of this software to return to
883ac2dfe9Sbouyer  *
893ac2dfe9Sbouyer  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
903ac2dfe9Sbouyer  *  School of Computer Science
913ac2dfe9Sbouyer  *  Carnegie Mellon University
923ac2dfe9Sbouyer  *  Pittsburgh PA 15213-3890
933ac2dfe9Sbouyer  *
943ac2dfe9Sbouyer  * any improvements or extensions that they make and grant Carnegie Mellon
953ac2dfe9Sbouyer  * the rights to redistribute these changes.
963ac2dfe9Sbouyer  */
973ac2dfe9Sbouyer /*
983ac2dfe9Sbouyer   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
993ac2dfe9Sbouyer 
1003ac2dfe9Sbouyer 		All Rights Reserved
1013ac2dfe9Sbouyer 
1023ac2dfe9Sbouyer Permission to use, copy, modify, and distribute this software and
1033ac2dfe9Sbouyer its documentation for any purpose and without fee is hereby
1043ac2dfe9Sbouyer granted, provided that the above copyright notice appears in all
1053ac2dfe9Sbouyer copies and that both the copyright notice and this permission notice
1063ac2dfe9Sbouyer appear in supporting documentation, and that the name of Intel
1073ac2dfe9Sbouyer not be used in advertising or publicity pertaining to distribution
1083ac2dfe9Sbouyer of the software without specific, written prior permission.
1093ac2dfe9Sbouyer 
1103ac2dfe9Sbouyer INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
1113ac2dfe9Sbouyer INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
1123ac2dfe9Sbouyer IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
1133ac2dfe9Sbouyer CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1143ac2dfe9Sbouyer LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
1153ac2dfe9Sbouyer NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
1163ac2dfe9Sbouyer WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1173ac2dfe9Sbouyer */
1183ac2dfe9Sbouyer 
1193ac2dfe9Sbouyer /*
1203ac2dfe9Sbouyer  * Primitive RTC chip routines.
1213ac2dfe9Sbouyer  */
1223ac2dfe9Sbouyer 
1233ac2dfe9Sbouyer #include <sys/cdefs.h>
124*28b4250dSjakllsch __KERNEL_RCSID(0, "$NetBSD: rtc.c,v 1.3 2025/01/07 22:37:13 jakllsch Exp $");
1253ac2dfe9Sbouyer 
1263ac2dfe9Sbouyer #include <sys/param.h>
1273ac2dfe9Sbouyer #include <sys/systm.h>
1283ac2dfe9Sbouyer #include <sys/time.h>
1293ac2dfe9Sbouyer #include <sys/timetc.h>
1303ac2dfe9Sbouyer #include <sys/kernel.h>
1313ac2dfe9Sbouyer 
1323ac2dfe9Sbouyer #include <dev/isa/isareg.h>
1333ac2dfe9Sbouyer #include <dev/isa/isavar.h>
1343ac2dfe9Sbouyer #include <i386/isa/nvram.h>
1353ac2dfe9Sbouyer 
1363ac2dfe9Sbouyer #include <machine/pio.h>
1373ac2dfe9Sbouyer 
1383ac2dfe9Sbouyer #include <dev/ic/mc146818reg.h>
1393ac2dfe9Sbouyer #include <x86/rtc.h>
1403ac2dfe9Sbouyer 
1413ac2dfe9Sbouyer #ifndef __x86_64__
1423ac2dfe9Sbouyer #include "mca.h"
1433ac2dfe9Sbouyer #endif
1443ac2dfe9Sbouyer #if NMCA > 0
1453ac2dfe9Sbouyer #include <machine/mca_machdep.h>	/* for MCA_system */
1463ac2dfe9Sbouyer #endif
1473ac2dfe9Sbouyer 
14863e5d1ebSjakllsch #include "acpica.h"
14963e5d1ebSjakllsch #if NACPICA > 0
15063e5d1ebSjakllsch #include <dev/acpi/acpivar.h>
15163e5d1ebSjakllsch #endif
15263e5d1ebSjakllsch 
1533ac2dfe9Sbouyer static void	rtcinit(void);
1543ac2dfe9Sbouyer static int	rtcget(mc_todregs *);
1553ac2dfe9Sbouyer static void	rtcput(mc_todregs *);
1563ac2dfe9Sbouyer static int	cmoscheck(void);
1573ac2dfe9Sbouyer static int	clock_expandyear(int);
1583ac2dfe9Sbouyer 
1593ac2dfe9Sbouyer /* XXX use sc? */
1603ac2dfe9Sbouyer u_int
1613ac2dfe9Sbouyer mc146818_read(void *sc, u_int reg)
1623ac2dfe9Sbouyer {
1633ac2dfe9Sbouyer 
1643ac2dfe9Sbouyer 	outb(IO_RTC, reg);
1653ac2dfe9Sbouyer 	return (inb(IO_RTC+1));
1663ac2dfe9Sbouyer }
1673ac2dfe9Sbouyer 
1683ac2dfe9Sbouyer void
1693ac2dfe9Sbouyer mc146818_write(void *sc, u_int reg, u_int datum)
1703ac2dfe9Sbouyer {
1713ac2dfe9Sbouyer 
1723ac2dfe9Sbouyer 	outb(IO_RTC, reg);
1733ac2dfe9Sbouyer 	outb(IO_RTC+1, datum);
1743ac2dfe9Sbouyer }
1753ac2dfe9Sbouyer 
1763ac2dfe9Sbouyer static void
1773ac2dfe9Sbouyer rtcinit(void)
1783ac2dfe9Sbouyer {
1793ac2dfe9Sbouyer 	static int first_rtcopen_ever = 1;
1803ac2dfe9Sbouyer 
1813ac2dfe9Sbouyer 	if (!first_rtcopen_ever)
1823ac2dfe9Sbouyer 		return;
1833ac2dfe9Sbouyer 	first_rtcopen_ever = 0;
1843ac2dfe9Sbouyer 
1853ac2dfe9Sbouyer 	mc146818_write(NULL, MC_REGA,			/* XXX softc */
1863ac2dfe9Sbouyer 	    MC_BASE_32_KHz | MC_RATE_1024_Hz);
1873ac2dfe9Sbouyer 	mc146818_write(NULL, MC_REGB, MC_REGB_24HR);	/* XXX softc */
1883ac2dfe9Sbouyer }
1893ac2dfe9Sbouyer 
1903ac2dfe9Sbouyer static int
1913ac2dfe9Sbouyer rtcget(mc_todregs *regs)
1923ac2dfe9Sbouyer {
1933ac2dfe9Sbouyer 
1943ac2dfe9Sbouyer 	rtcinit();
1953ac2dfe9Sbouyer 	if ((mc146818_read(NULL, MC_REGD) & MC_REGD_VRT) == 0) /* XXX softc */
1963ac2dfe9Sbouyer 		return (-1);
1973ac2dfe9Sbouyer 	MC146818_GETTOD(NULL, regs);			/* XXX softc */
1983ac2dfe9Sbouyer 	return (0);
1993ac2dfe9Sbouyer }
2003ac2dfe9Sbouyer 
2013ac2dfe9Sbouyer static void
2023ac2dfe9Sbouyer rtcput(mc_todregs *regs)
2033ac2dfe9Sbouyer {
2043ac2dfe9Sbouyer 
2053ac2dfe9Sbouyer 	rtcinit();
2063ac2dfe9Sbouyer 	MC146818_PUTTOD(NULL, regs);			/* XXX softc */
2073ac2dfe9Sbouyer }
2083ac2dfe9Sbouyer 
2093ac2dfe9Sbouyer /*
2103ac2dfe9Sbouyer  * check whether the CMOS layout is "standard"-like (ie, not PS/2-like),
2113ac2dfe9Sbouyer  * to be called at splclock()
2123ac2dfe9Sbouyer  */
2133ac2dfe9Sbouyer static int
2143ac2dfe9Sbouyer cmoscheck(void)
2153ac2dfe9Sbouyer {
2163ac2dfe9Sbouyer 	int i;
2173ac2dfe9Sbouyer 	unsigned short cksum = 0;
2183ac2dfe9Sbouyer 
2193ac2dfe9Sbouyer 	for (i = 0x10; i <= 0x2d; i++)
2203ac2dfe9Sbouyer 		cksum += mc146818_read(NULL, i); /* XXX softc */
2213ac2dfe9Sbouyer 
2223ac2dfe9Sbouyer 	return (cksum == (mc146818_read(NULL, 0x2e) << 8)
2233ac2dfe9Sbouyer 			  + mc146818_read(NULL, 0x2f));
2243ac2dfe9Sbouyer }
2253ac2dfe9Sbouyer 
2263ac2dfe9Sbouyer #if NMCA > 0
2273ac2dfe9Sbouyer /*
2283ac2dfe9Sbouyer  * Check whether the CMOS layout is PS/2 like, to be called at splclock().
2293ac2dfe9Sbouyer  */
2303ac2dfe9Sbouyer static int cmoscheckps2(void);
2313ac2dfe9Sbouyer static int
2323ac2dfe9Sbouyer cmoscheckps2(void)
2333ac2dfe9Sbouyer {
2343ac2dfe9Sbouyer #if 0
2353ac2dfe9Sbouyer 	/* Disabled until I find out the CRC checksum algorithm IBM uses */
2363ac2dfe9Sbouyer 	int i;
2373ac2dfe9Sbouyer 	unsigned short cksum = 0;
2383ac2dfe9Sbouyer 
2393ac2dfe9Sbouyer 	for (i = 0x10; i <= 0x31; i++)
2403ac2dfe9Sbouyer 		cksum += mc146818_read(NULL, i); /* XXX softc */
2413ac2dfe9Sbouyer 
2423ac2dfe9Sbouyer 	return (cksum == (mc146818_read(NULL, 0x32) << 8)
2433ac2dfe9Sbouyer 			  + mc146818_read(NULL, 0x33));
2443ac2dfe9Sbouyer #else
2453ac2dfe9Sbouyer 	/* Check 'incorrect checksum' bit of IBM PS/2 Diagnostic Status Byte */
2463ac2dfe9Sbouyer 	return ((mc146818_read(NULL, NVRAM_DIAG) & (1<<6)) == 0);
2473ac2dfe9Sbouyer #endif
2483ac2dfe9Sbouyer }
2493ac2dfe9Sbouyer #endif /* NMCA > 0 */
2503ac2dfe9Sbouyer 
2513ac2dfe9Sbouyer /*
2523ac2dfe9Sbouyer  * patchable to control century byte handling:
2533ac2dfe9Sbouyer  * 1: always update
2543ac2dfe9Sbouyer  * -1: never touch
2553ac2dfe9Sbouyer  * 0: try to figure out itself
2563ac2dfe9Sbouyer  */
2573ac2dfe9Sbouyer int rtc_update_century = 0;
2583ac2dfe9Sbouyer 
2593ac2dfe9Sbouyer /*
2603ac2dfe9Sbouyer  * Expand a two-digit year as read from the clock chip
2613ac2dfe9Sbouyer  * into full width.
2623ac2dfe9Sbouyer  * Being here, deal with the CMOS century byte.
2633ac2dfe9Sbouyer  */
2643ac2dfe9Sbouyer static int centb = NVRAM_CENTURY;
2653ac2dfe9Sbouyer static int
2663ac2dfe9Sbouyer clock_expandyear(int clockyear)
2673ac2dfe9Sbouyer {
2683ac2dfe9Sbouyer 	int s, clockcentury, cmoscentury;
2693ac2dfe9Sbouyer 
2703ac2dfe9Sbouyer 	clockcentury = (clockyear < 70) ? 20 : 19;
2713ac2dfe9Sbouyer 	clockyear += 100 * clockcentury;
2723ac2dfe9Sbouyer 
2733ac2dfe9Sbouyer 	if (rtc_update_century < 0)
2743ac2dfe9Sbouyer 		return (clockyear);
2753ac2dfe9Sbouyer 
2763ac2dfe9Sbouyer 	s = splclock();
27763e5d1ebSjakllsch #if NACPICA > 0
278*28b4250dSjakllsch 	if (acpi_active && AcpiGbl_FADT.Century >= MC_NVRAM_START &&
279*28b4250dSjakllsch 	    AcpiGbl_FADT.Century < (MC_NVRAM_START + MC_NVRAM_SIZE))
28063e5d1ebSjakllsch 		cmoscentury = mc146818_read(NULL,
28163e5d1ebSjakllsch 		    (centb = AcpiGbl_FADT.Century));
28263e5d1ebSjakllsch 	else
28363e5d1ebSjakllsch #endif
2843ac2dfe9Sbouyer 	if (cmoscheck())
2853ac2dfe9Sbouyer 		cmoscentury = mc146818_read(NULL, NVRAM_CENTURY);
2863ac2dfe9Sbouyer #if NMCA > 0
2873ac2dfe9Sbouyer 	else if (MCA_system && cmoscheckps2())
2883ac2dfe9Sbouyer 		cmoscentury = mc146818_read(NULL, (centb = 0x37));
2893ac2dfe9Sbouyer #endif
2903ac2dfe9Sbouyer 	else
2913ac2dfe9Sbouyer 		cmoscentury = 0;
2923ac2dfe9Sbouyer 	splx(s);
2933ac2dfe9Sbouyer 	if (!cmoscentury) {
2943ac2dfe9Sbouyer #ifdef DIAGNOSTIC
2953ac2dfe9Sbouyer 		printf("clock: unknown CMOS layout\n");
2963ac2dfe9Sbouyer #endif
2973ac2dfe9Sbouyer 		return (clockyear);
2983ac2dfe9Sbouyer 	}
2993ac2dfe9Sbouyer 	cmoscentury = bcdtobin(cmoscentury);
3003ac2dfe9Sbouyer 
3013ac2dfe9Sbouyer 	if (cmoscentury != clockcentury) {
3023ac2dfe9Sbouyer 		/* XXX note: saying "century is 20" might confuse the naive. */
3033ac2dfe9Sbouyer 		printf("WARNING: NVRAM century is %d but RTC year is %d\n",
3043ac2dfe9Sbouyer 		       cmoscentury, clockyear);
3053ac2dfe9Sbouyer 
3063ac2dfe9Sbouyer 		/* Kludge to roll over century. */
3073ac2dfe9Sbouyer 		if ((rtc_update_century > 0) ||
3083ac2dfe9Sbouyer 		    ((cmoscentury == 19) && (clockcentury == 20) &&
3093ac2dfe9Sbouyer 		     (clockyear == 2000))) {
3103ac2dfe9Sbouyer 			printf("WARNING: Setting NVRAM century to %d\n",
3113ac2dfe9Sbouyer 			       clockcentury);
3123ac2dfe9Sbouyer 			s = splclock();
3133ac2dfe9Sbouyer 			mc146818_write(NULL, centb, bintobcd(clockcentury));
3143ac2dfe9Sbouyer 			splx(s);
3153ac2dfe9Sbouyer 		}
3163ac2dfe9Sbouyer 	} else if (cmoscentury == 19 && rtc_update_century == 0)
3173ac2dfe9Sbouyer 		rtc_update_century = 1; /* will update later in resettodr() */
3183ac2dfe9Sbouyer 
3193ac2dfe9Sbouyer 	return (clockyear);
3203ac2dfe9Sbouyer }
3213ac2dfe9Sbouyer 
3223ac2dfe9Sbouyer int
3233ac2dfe9Sbouyer rtc_get_ymdhms(todr_chip_handle_t tch, struct clock_ymdhms *dt)
3243ac2dfe9Sbouyer {
3253ac2dfe9Sbouyer 	int s;
3263ac2dfe9Sbouyer 	mc_todregs rtclk;
3273ac2dfe9Sbouyer 
3283ac2dfe9Sbouyer 	s = splclock();
3293ac2dfe9Sbouyer 	if (rtcget(&rtclk)) {
3303ac2dfe9Sbouyer 		splx(s);
3313ac2dfe9Sbouyer 		return -1;
3323ac2dfe9Sbouyer 	}
3333ac2dfe9Sbouyer 	splx(s);
3343ac2dfe9Sbouyer 
3353ac2dfe9Sbouyer 	dt->dt_sec = bcdtobin(rtclk[MC_SEC]);
3363ac2dfe9Sbouyer 	dt->dt_min = bcdtobin(rtclk[MC_MIN]);
3373ac2dfe9Sbouyer 	dt->dt_hour = bcdtobin(rtclk[MC_HOUR]);
3383ac2dfe9Sbouyer 	dt->dt_day = bcdtobin(rtclk[MC_DOM]);
3393ac2dfe9Sbouyer 	dt->dt_mon = bcdtobin(rtclk[MC_MONTH]);
3403ac2dfe9Sbouyer 	dt->dt_year = clock_expandyear(bcdtobin(rtclk[MC_YEAR]));
3413ac2dfe9Sbouyer 
3423ac2dfe9Sbouyer 	return 0;
3433ac2dfe9Sbouyer }
3443ac2dfe9Sbouyer 
3453ac2dfe9Sbouyer int
3463ac2dfe9Sbouyer rtc_set_ymdhms(todr_chip_handle_t tch, struct clock_ymdhms *dt)
3473ac2dfe9Sbouyer {
3483ac2dfe9Sbouyer 	mc_todregs rtclk;
3493ac2dfe9Sbouyer 	int century;
3503ac2dfe9Sbouyer 	int s;
3513ac2dfe9Sbouyer 
3523ac2dfe9Sbouyer 	s = splclock();
3533ac2dfe9Sbouyer 	if (rtcget(&rtclk))
3543ac2dfe9Sbouyer 		memset(&rtclk, 0, sizeof(rtclk));
3553ac2dfe9Sbouyer 	splx(s);
3563ac2dfe9Sbouyer 
3573ac2dfe9Sbouyer 	rtclk[MC_SEC] = bintobcd(dt->dt_sec);
3583ac2dfe9Sbouyer 	rtclk[MC_MIN] = bintobcd(dt->dt_min);
3593ac2dfe9Sbouyer 	rtclk[MC_HOUR] = bintobcd(dt->dt_hour);
3603ac2dfe9Sbouyer 	rtclk[MC_DOW] = dt->dt_wday + 1;
3613ac2dfe9Sbouyer 	rtclk[MC_YEAR] = bintobcd(dt->dt_year % 100);
3623ac2dfe9Sbouyer 	rtclk[MC_MONTH] = bintobcd(dt->dt_mon);
3633ac2dfe9Sbouyer 	rtclk[MC_DOM] = bintobcd(dt->dt_day);
3643ac2dfe9Sbouyer 
3653ac2dfe9Sbouyer #ifdef DEBUG_CLOCK
3663ac2dfe9Sbouyer 	printf("setclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR], rtclk[MC_MONTH],
3673ac2dfe9Sbouyer 	   rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN], rtclk[MC_SEC]);
3683ac2dfe9Sbouyer #endif
3693ac2dfe9Sbouyer 	s = splclock();
3703ac2dfe9Sbouyer 	rtcput(&rtclk);
3713ac2dfe9Sbouyer 	if (rtc_update_century > 0) {
3723ac2dfe9Sbouyer 		century = bintobcd(dt->dt_year / 100);
3733ac2dfe9Sbouyer 		mc146818_write(NULL, centb, century); /* XXX softc */
3743ac2dfe9Sbouyer 	}
3753ac2dfe9Sbouyer 	splx(s);
3763ac2dfe9Sbouyer 	return 0;
3773ac2dfe9Sbouyer 
3783ac2dfe9Sbouyer }
3793ac2dfe9Sbouyer 
3803ac2dfe9Sbouyer void
3813ac2dfe9Sbouyer rtc_register(void)
3823ac2dfe9Sbouyer {
3833ac2dfe9Sbouyer 	static struct todr_chip_handle	tch;
3843ac2dfe9Sbouyer 	tch.todr_gettime_ymdhms = rtc_get_ymdhms;
3853ac2dfe9Sbouyer 	tch.todr_settime_ymdhms = rtc_set_ymdhms;
3863ac2dfe9Sbouyer 	tch.todr_setwen = NULL;
3873ac2dfe9Sbouyer 
3883ac2dfe9Sbouyer 	todr_attach(&tch);
3893ac2dfe9Sbouyer }
3903ac2dfe9Sbouyer 
391