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