xref: /netbsd-src/sys/arch/amiga/dev/a34kbbc.c (revision cbab9cadce21ae72fac13910001079fff214cc29)
1*cbab9cadSchs /*	$NetBSD: a34kbbc.c,v 1.23 2012/10/27 17:17:26 chs Exp $ */
2aad01611Sagc 
3aad01611Sagc /*
49b6bd2d9Srmind  * Copyright (c) 1988 University of Utah.
5aad01611Sagc  * Copyright (c) 1982, 1990 The Regents of the University of California.
6aad01611Sagc  * All rights reserved.
7aad01611Sagc  *
8aad01611Sagc  * This code is derived from software contributed to Berkeley by
9aad01611Sagc  * the Systems Programming Group of the University of Utah Computer
10aad01611Sagc  * Science Department.
11aad01611Sagc  *
12aad01611Sagc  * Redistribution and use in source and binary forms, with or without
13aad01611Sagc  * modification, are permitted provided that the following conditions
14aad01611Sagc  * are met:
15aad01611Sagc  * 1. Redistributions of source code must retain the above copyright
16aad01611Sagc  *    notice, this list of conditions and the following disclaimer.
17aad01611Sagc  * 2. Redistributions in binary form must reproduce the above copyright
18aad01611Sagc  *    notice, this list of conditions and the following disclaimer in the
19aad01611Sagc  *    documentation and/or other materials provided with the distribution.
20aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
21aad01611Sagc  *    may be used to endorse or promote products derived from this software
22aad01611Sagc  *    without specific prior written permission.
23aad01611Sagc  *
24aad01611Sagc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25aad01611Sagc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26aad01611Sagc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27aad01611Sagc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28aad01611Sagc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29aad01611Sagc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30aad01611Sagc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31aad01611Sagc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32aad01611Sagc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33aad01611Sagc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34aad01611Sagc  * SUCH DAMAGE.
35aad01611Sagc  *
36aad01611Sagc  * from: Utah $Hdr: clock.c 1.18 91/01/21$
37aad01611Sagc  *
38aad01611Sagc  *	@(#)clock.c	7.6 (Berkeley) 5/7/91
39aad01611Sagc  */
404d8c2c35Sis 
411ea4df81Saymeric #include <sys/cdefs.h>
42*cbab9cadSchs __KERNEL_RCSID(0, "$NetBSD: a34kbbc.c,v 1.23 2012/10/27 17:17:26 chs Exp $");
431ea4df81Saymeric 
444d8c2c35Sis #include <sys/param.h>
454d8c2c35Sis #include <sys/kernel.h>
464d8c2c35Sis #include <sys/device.h>
474d8c2c35Sis #include <sys/systm.h>
484d8c2c35Sis #include <machine/psl.h>
494d8c2c35Sis #include <machine/cpu.h>
504d8c2c35Sis #include <amiga/amiga/device.h>
514d8c2c35Sis #include <amiga/amiga/custom.h>
524d8c2c35Sis #include <amiga/amiga/cia.h>
534d8c2c35Sis #include <amiga/dev/rtc.h>
544d8c2c35Sis #include <amiga/dev/zbusvar.h>
554d8c2c35Sis 
564d8c2c35Sis #include <dev/clock_subr.h>
574d8c2c35Sis 
580d242d5fSmatt int a34kbbc_match(device_t, cfdata_t, void *);
590d242d5fSmatt void a34kbbc_attach(device_t, device_t, void *);
604d8c2c35Sis 
610d242d5fSmatt CFATTACH_DECL_NEW(a34kbbc, 0,
62c5e91d44Sthorpej     a34kbbc_match, a34kbbc_attach, NULL, NULL);
634d8c2c35Sis 
644d8c2c35Sis void *a34kclockaddr;
65dcc5a663Sgdamore int a34kugettod(todr_chip_handle_t, struct clock_ymdhms *);
66dcc5a663Sgdamore int a34kusettod(todr_chip_handle_t, struct clock_ymdhms *);
6714c9ea00Smhitch static struct todr_chip_handle a34ktodr;
684d8c2c35Sis 
694d8c2c35Sis int
a34kbbc_match(device_t parent,cfdata_t cf,void * aux)70*cbab9cadSchs a34kbbc_match(device_t parent, cfdata_t cf, void *aux)
714d8c2c35Sis {
72031f3db0Smhitch 	struct clock_ymdhms dt;
7316343055Skleink 	static int a34kbbc_matched = 0;
7416343055Skleink 
75*cbab9cadSchs 	if (!matchname("a34kbbc", aux))
764d8c2c35Sis 		return(0);
774d8c2c35Sis 
78c8ee9999Sis 	/* Allow only one instance. */
7916343055Skleink 	if (a34kbbc_matched)
8016343055Skleink 		return(0);
814d8c2c35Sis 
824d8c2c35Sis 	if (!(is_a3000() || is_a4000()))
834d8c2c35Sis 		return(0);
844d8c2c35Sis 
85803a5ae1Sjmc 	a34kclockaddr = (void *)__UNVOLATILE(ztwomap(0xdc0000));
86031f3db0Smhitch 	if (a34kugettod(&a34ktodr, &dt) != 0)
874d8c2c35Sis 		return(0);
884d8c2c35Sis 
8916343055Skleink 	a34kbbc_matched = 1;
904d8c2c35Sis 	return(1);
914d8c2c35Sis }
924d8c2c35Sis 
934d8c2c35Sis /*
944d8c2c35Sis  * Attach us to the rtc function pointers.
954d8c2c35Sis  */
964d8c2c35Sis void
a34kbbc_attach(device_t parent,device_t self,void * aux)97*cbab9cadSchs a34kbbc_attach(device_t parent, device_t self, void *aux)
984d8c2c35Sis {
994d8c2c35Sis 	printf("\n");
100803a5ae1Sjmc 	a34kclockaddr = (void *)__UNVOLATILE(ztwomap(0xdc0000));
1014d8c2c35Sis 
10214c9ea00Smhitch 	a34ktodr.cookie = a34kclockaddr;
103dcc5a663Sgdamore 	a34ktodr.todr_gettime_ymdhms = a34kugettod;
104dcc5a663Sgdamore 	a34ktodr.todr_settime_ymdhms = a34kusettod;
10514c9ea00Smhitch 	todr_attach(&a34ktodr);
1064d8c2c35Sis }
1074d8c2c35Sis 
108ba07737bSis int
a34kugettod(todr_chip_handle_t h,struct clock_ymdhms * dt)109dcc5a663Sgdamore a34kugettod(todr_chip_handle_t h, struct clock_ymdhms *dt)
1104d8c2c35Sis {
1114d8c2c35Sis 	struct rtclock3000 *rt;
1124d8c2c35Sis 
1134d8c2c35Sis 	rt = a34kclockaddr;
1144d8c2c35Sis 
1154d8c2c35Sis 	/* hold clock */
1164d8c2c35Sis 	rt->control1 = A3CONTROL1_HOLD_CLOCK;
1174d8c2c35Sis 
1184d8c2c35Sis 	/* Copy the info.  Careful about the order! */
119dcc5a663Sgdamore 	dt->dt_sec   = rt->second1 * 10 + rt->second2;
120dcc5a663Sgdamore 	dt->dt_min   = rt->minute1 * 10 + rt->minute2;
121dcc5a663Sgdamore 	dt->dt_hour  = rt->hour1   * 10 + rt->hour2;
122dcc5a663Sgdamore 	dt->dt_wday  = rt->weekday;
123dcc5a663Sgdamore 	dt->dt_day   = rt->day1    * 10 + rt->day2;
124dcc5a663Sgdamore 	dt->dt_mon   = rt->month1  * 10 + rt->month2;
125dcc5a663Sgdamore 	dt->dt_year  = rt->year1   * 10 + rt->year2;
1264d8c2c35Sis 
127dcc5a663Sgdamore 	dt->dt_year += CLOCK_BASE_YEAR;
128d1496807Sis 	/* let it run again.. */
129d1496807Sis 	rt->control1 = A3CONTROL1_FREE_CLOCK;
130d1496807Sis 
131dcc5a663Sgdamore 	if (dt->dt_year < STARTOFTIME)
132dcc5a663Sgdamore 		dt->dt_year += 100;
1334d8c2c35Sis 
1344d8c2c35Sis 
135dcc5a663Sgdamore 	/*
136dcc5a663Sgdamore 	 * These checks are mostly redundant against those already in the
137dcc5a663Sgdamore 	 * generic todr, but apparently the attach code checks against the
138dcc5a663Sgdamore 	 * return value of this function, so we have to include a check here,
139dcc5a663Sgdamore 	 * too.
140dcc5a663Sgdamore 	 */
141dcc5a663Sgdamore 	if ((dt->dt_hour > 23) ||
142dcc5a663Sgdamore 	    (dt->dt_wday > 6) ||
143dcc5a663Sgdamore 	    (dt->dt_day  > 31) ||
144dcc5a663Sgdamore 	    (dt->dt_mon  > 12) ||
145dcc5a663Sgdamore 	    /* (dt.dt_year < STARTOFTIME) || */ (dt->dt_year > 2036))
1467b2d0951Smhitch 		return (EINVAL);
1474d8c2c35Sis 
14814c9ea00Smhitch 	return (0);
1494d8c2c35Sis }
1504d8c2c35Sis 
1514d8c2c35Sis int
a34kusettod(todr_chip_handle_t h,struct clock_ymdhms * dt)152dcc5a663Sgdamore a34kusettod(todr_chip_handle_t h, struct clock_ymdhms *dt)
1534d8c2c35Sis {
1544d8c2c35Sis 	struct rtclock3000 *rt;
1554d8c2c35Sis 
1564d8c2c35Sis 	rt = a34kclockaddr;
1574d8c2c35Sis 	/*
1584d8c2c35Sis 	 * there seem to be problems with the bitfield addressing
1594d8c2c35Sis 	 * currently used..
1604d8c2c35Sis 	 */
1614d8c2c35Sis 
1624d8c2c35Sis 	if (! rt)
1637b2d0951Smhitch 		return (ENXIO);
1644d8c2c35Sis 
165fc0b743eSis 	rt->control1 = A3CONTROL1_HOLD_CLOCK;		/* implies mode 0 */
166dcc5a663Sgdamore 	rt->second1 = dt->dt_sec / 10;
167dcc5a663Sgdamore 	rt->second2 = dt->dt_sec % 10;
168dcc5a663Sgdamore 	rt->minute1 = dt->dt_min / 10;
169dcc5a663Sgdamore 	rt->minute2 = dt->dt_min % 10;
170dcc5a663Sgdamore 	rt->hour1   = dt->dt_hour / 10;
171dcc5a663Sgdamore 	rt->hour2   = dt->dt_hour % 10;
172dcc5a663Sgdamore 	rt->weekday = dt->dt_wday;
173dcc5a663Sgdamore 	rt->day1    = dt->dt_day / 10;
174dcc5a663Sgdamore 	rt->day2    = dt->dt_day % 10;
175dcc5a663Sgdamore 	rt->month1  = dt->dt_mon / 10;
176dcc5a663Sgdamore 	rt->month2  = dt->dt_mon % 10;
177dcc5a663Sgdamore 	rt->year1   = (dt->dt_year / 10) % 10;
178dcc5a663Sgdamore 	rt->year2   = dt->dt_year % 10;
1792e3d1cc0Sis 	rt->control1 = A3CONTROL1_HOLD_CLOCK | 1;	/* mode 1 registers */
180dcc5a663Sgdamore 	rt->leapyear = dt->dt_year; 		/* XXX implicit % 4 */
181fc0b743eSis 	rt->control1 = A3CONTROL1_FREE_CLOCK;		/* implies mode 1 */
1824d8c2c35Sis 
18314c9ea00Smhitch 	return (0);
1844d8c2c35Sis }
185