a2kbbc.c revision 1.18
11.18Smhitch/* $NetBSD: a2kbbc.c,v 1.18 2006/09/05 05:32:30 mhitch Exp $ */ 21.1Sis 31.1Sis/* 41.1Sis * Copyright (c) 1982, 1990 The Regents of the University of California. 51.1Sis * All rights reserved. 61.1Sis * 71.1Sis * This code is derived from software contributed to Berkeley by 81.1Sis * the Systems Programming Group of the University of Utah Computer 91.1Sis * Science Department. 101.1Sis * 111.1Sis * Redistribution and use in source and binary forms, with or without 121.1Sis * modification, are permitted provided that the following conditions 131.1Sis * are met: 141.1Sis * 1. Redistributions of source code must retain the above copyright 151.1Sis * notice, this list of conditions and the following disclaimer. 161.1Sis * 2. Redistributions in binary form must reproduce the above copyright 171.1Sis * notice, this list of conditions and the following disclaimer in the 181.1Sis * documentation and/or other materials provided with the distribution. 191.15Sagc * 3. Neither the name of the University nor the names of its contributors 201.15Sagc * may be used to endorse or promote products derived from this software 211.15Sagc * without specific prior written permission. 221.15Sagc * 231.15Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 241.15Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 251.15Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 261.15Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 271.15Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 281.15Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 291.15Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 301.15Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 311.15Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 321.15Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 331.15Sagc * SUCH DAMAGE. 341.15Sagc * 351.15Sagc * from: Utah $Hdr: clock.c 1.18 91/01/21$ 361.15Sagc * 371.15Sagc * @(#)clock.c 7.6 (Berkeley) 5/7/91 381.15Sagc */ 391.15Sagc 401.15Sagc/* 411.15Sagc * Copyright (c) 1988 University of Utah. 421.15Sagc * 431.15Sagc * This code is derived from software contributed to Berkeley by 441.15Sagc * the Systems Programming Group of the University of Utah Computer 451.15Sagc * Science Department. 461.15Sagc * 471.15Sagc * Redistribution and use in source and binary forms, with or without 481.15Sagc * modification, are permitted provided that the following conditions 491.15Sagc * are met: 501.15Sagc * 1. Redistributions of source code must retain the above copyright 511.15Sagc * notice, this list of conditions and the following disclaimer. 521.15Sagc * 2. Redistributions in binary form must reproduce the above copyright 531.15Sagc * notice, this list of conditions and the following disclaimer in the 541.15Sagc * documentation and/or other materials provided with the distribution. 551.1Sis * 3. All advertising materials mentioning features or use of this software 561.1Sis * must display the following acknowledgement: 571.1Sis * This product includes software developed by the University of 581.1Sis * California, Berkeley and its contributors. 591.1Sis * 4. Neither the name of the University nor the names of its contributors 601.1Sis * may be used to endorse or promote products derived from this software 611.1Sis * without specific prior written permission. 621.1Sis * 631.1Sis * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 641.1Sis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 651.1Sis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 661.1Sis * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 671.1Sis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 681.1Sis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 691.1Sis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 701.1Sis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 711.1Sis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 721.1Sis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 731.1Sis * SUCH DAMAGE. 741.1Sis * 751.1Sis * from: Utah $Hdr: clock.c 1.18 91/01/21$ 761.1Sis * 771.1Sis * @(#)clock.c 7.6 (Berkeley) 5/7/91 781.1Sis */ 791.12Saymeric 801.12Saymeric#include <sys/cdefs.h> 811.18Smhitch__KERNEL_RCSID(0, "$NetBSD: a2kbbc.c,v 1.18 2006/09/05 05:32:30 mhitch Exp $"); 821.1Sis 831.1Sis#include <sys/param.h> 841.1Sis#include <sys/kernel.h> 851.1Sis#include <sys/device.h> 861.1Sis#include <sys/systm.h> 871.1Sis#include <machine/psl.h> 881.1Sis#include <machine/cpu.h> 891.1Sis#include <amiga/amiga/device.h> 901.1Sis#include <amiga/amiga/custom.h> 911.1Sis#include <amiga/amiga/cia.h> 921.1Sis#include <amiga/dev/rtc.h> 931.1Sis#include <amiga/dev/zbusvar.h> 941.1Sis 951.1Sis#include <dev/clock_subr.h> 961.1Sis 971.11Saymericint a2kbbc_match(struct device *, struct cfdata *, void *); 981.11Saymericvoid a2kbbc_attach(struct device *, struct device *, void *); 991.1Sis 1001.14SthorpejCFATTACH_DECL(a2kbbc, sizeof(struct device), 1011.14Sthorpej a2kbbc_match, a2kbbc_attach, NULL, NULL); 1021.1Sis 1031.1Sisvoid *a2kclockaddr; 1041.18Smhitchint a2kugettod(todr_chip_handle_t, volatile struct timeval *); 1051.18Smhitchint a2kusettod(todr_chip_handle_t, volatile struct timeval *); 1061.18Smhitchstatic struct todr_chip_handle a2ktodr; 1071.1Sis 1081.1Sisint 1091.11Saymerica2kbbc_match(struct device *pdp, struct cfdata *cfp, void *auxp) 1101.1Sis{ 1111.10Skleink static int a2kbbc_matched = 0; 1121.10Skleink 1131.1Sis if (!matchname("a2kbbc", auxp)) 1141.2Skleink return (0); 1151.1Sis 1161.10Skleink /* Allow only one instance. */ 1171.10Skleink if (a2kbbc_matched) 1181.10Skleink return (0); 1191.1Sis 1201.11Saymeric if (/* is_a1200() || */ is_a3000() || is_a4000() 1211.3Sis#ifdef DRACO 1221.3Sis || is_draco() 1231.3Sis#endif 1241.3Sis ) 1251.2Skleink return (0); 1261.1Sis 1271.16Sjmc a2kclockaddr = (void *)__UNVOLATILE(ztwomap(0xdc0000)); 1281.18Smhitch if (a2kugettod(&a2ktodr, 0) != 0) 1291.2Skleink return (0); 1301.1Sis 1311.10Skleink a2kbbc_matched = 1; 1321.2Skleink return (1); 1331.1Sis} 1341.1Sis 1351.1Sis/* 1361.1Sis * Attach us to the rtc function pointers. 1371.1Sis */ 1381.1Sisvoid 1391.11Saymerica2kbbc_attach(struct device *pdp, struct device *dp, void *auxp) 1401.1Sis{ 1411.1Sis printf("\n"); 1421.16Sjmc a2kclockaddr = (void *)__UNVOLATILE(ztwomap(0xdc0000)); 1431.1Sis 1441.18Smhitch a2ktodr.cookie = a2kclockaddr; 1451.18Smhitch a2ktodr.todr_gettime = a2kugettod; 1461.18Smhitch a2ktodr.todr_settime = a2kusettod; 1471.18Smhitch todr_attach(&a2ktodr); 1481.1Sis} 1491.1Sis 1501.6Sisint 1511.18Smhitcha2kugettod(todr_chip_handle_t h, volatile struct timeval *tvp) 1521.1Sis{ 1531.1Sis struct rtclock2000 *rt; 1541.1Sis struct clock_ymdhms dt; 1551.1Sis time_t secs; 1561.1Sis int i; 1571.1Sis 1581.1Sis rt = a2kclockaddr; 1591.1Sis 1601.1Sis /* 1611.1Sis * hold clock 1621.1Sis */ 1631.1Sis rt->control1 |= A2CONTROL1_HOLD; 1641.1Sis i = 0x1000; 1651.1Sis while (rt->control1 & A2CONTROL1_BUSY && i--) 1661.1Sis ; 1671.1Sis if (rt->control1 & A2CONTROL1_BUSY) 1681.1Sis return (0); /* Give up and say it's not there */ 1691.1Sis 1701.1Sis /* Copy the info. Careful about the order! */ 1711.1Sis dt.dt_sec = rt->second1 * 10 + rt->second2; 1721.1Sis dt.dt_min = rt->minute1 * 10 + rt->minute2; 1731.1Sis dt.dt_hour = (rt->hour1 & 3) * 10 + rt->hour2; 1741.1Sis dt.dt_day = rt->day1 * 10 + rt->day2; 1751.1Sis dt.dt_mon = rt->month1 * 10 + rt->month2; 1761.1Sis dt.dt_year = rt->year1 * 10 + rt->year2; 1771.1Sis dt.dt_wday = rt->weekday; 1781.1Sis 1791.1Sis /* 1801.1Sis * The oki clock chip has a register to put the clock into 1811.1Sis * 12/24h mode. 1821.1Sis * 1831.1Sis * clockmode | A2HOUR1_PM 1841.1Sis * 24h 12h | am = 0, pm = 1 1851.1Sis * --------------------------------- 1861.1Sis * 0 12 | 0 1871.1Sis * 1 1 | 0 1881.1Sis * .. .. | 0 1891.1Sis * 11 11 | 0 1901.1Sis * 12 12 | 1 1911.1Sis * 13 1 | 1 1921.1Sis * .. .. | 1 1931.1Sis * 23 11 | 1 1941.1Sis * 1951.1Sis */ 1961.1Sis 1971.1Sis if ((rt->control3 & A2CONTROL3_24HMODE) == 0) { 1981.1Sis if ((rt->hour1 & A2HOUR1_PM) == 0 && dt.dt_hour == 12) 1991.1Sis dt.dt_hour = 0; 2001.1Sis else if ((rt->hour1 & A2HOUR1_PM) && dt.dt_hour != 12) 2011.1Sis dt.dt_hour += 12; 2021.1Sis } 2031.1Sis 2041.11Saymeric /* 2051.11Saymeric * release the clock 2061.1Sis */ 2071.1Sis rt->control1 &= ~A2CONTROL1_HOLD; 2081.1Sis 2091.1Sis dt.dt_year += CLOCK_BASE_YEAR; 2101.8Sis if (dt.dt_year < STARTOFTIME) 2111.8Sis dt.dt_year += 100; 2121.1Sis 2131.1Sis if ((dt.dt_hour > 23) || 2141.11Saymeric (dt.dt_day > 31) || 2151.1Sis (dt.dt_mon > 12) || 2161.8Sis /* (dt.dt_year < STARTOFTIME) || */ (dt.dt_year > 2036)) 2171.1Sis return (0); 2181.11Saymeric 2191.1Sis secs = clock_ymdhms_to_secs(&dt); 2201.7Sis if (tvp) { 2211.7Sis tvp->tv_sec = secs; 2221.7Sis tvp->tv_usec = 0; 2231.7Sis } 2241.18Smhitch return (0); 2251.1Sis} 2261.1Sis 2271.1Sisint 2281.18Smhitcha2kusettod(todr_chip_handle_t h, volatile struct timeval *tvp) 2291.1Sis{ 2301.1Sis struct rtclock2000 *rt; 2311.1Sis struct clock_ymdhms dt; 2321.1Sis int ampm, i; 2331.6Sis time_t secs; 2341.1Sis 2351.6Sis secs = tvp->tv_sec; 2361.1Sis rt = a2kclockaddr; 2371.11Saymeric /* 2381.1Sis * there seem to be problems with the bitfield addressing 2391.1Sis * currently used.. 2401.1Sis */ 2411.1Sis if (! rt) 2421.18Smhitch return (1); 2431.1Sis 2441.1Sis clock_secs_to_ymdhms(secs, &dt); 2451.1Sis 2461.1Sis /* 2471.1Sis * hold clock 2481.1Sis */ 2491.1Sis rt->control1 |= A2CONTROL1_HOLD; 2501.1Sis i = 0x1000; 2511.1Sis while (rt->control1 & A2CONTROL1_BUSY && i--) 2521.1Sis ; 2531.1Sis if (rt->control1 & A2CONTROL1_BUSY) 2541.1Sis return (0); /* Give up and say it's not there */ 2551.1Sis 2561.1Sis ampm = 0; 2571.1Sis if ((rt->control3 & A2CONTROL3_24HMODE) == 0) { 2581.1Sis if (dt.dt_hour >= 12) { 2591.1Sis ampm = A2HOUR1_PM; 2601.1Sis if (dt.dt_hour != 12) 2611.1Sis dt.dt_hour -= 12; 2621.1Sis } else if (dt.dt_hour == 0) { 2631.1Sis dt.dt_hour = 12; 2641.1Sis } 2651.1Sis } 2661.1Sis rt->hour1 = (dt.dt_hour / 10) | ampm; 2671.1Sis rt->hour2 = dt.dt_hour % 10; 2681.1Sis rt->second1 = dt.dt_sec / 10; 2691.1Sis rt->second2 = dt.dt_sec % 10; 2701.1Sis rt->minute1 = dt.dt_min / 10; 2711.1Sis rt->minute2 = dt.dt_min % 10; 2721.1Sis rt->day1 = dt.dt_day / 10; 2731.1Sis rt->day2 = dt.dt_day % 10; 2741.1Sis rt->month1 = dt.dt_mon / 10; 2751.1Sis rt->month2 = dt.dt_mon % 10; 2761.9Sis rt->year1 = (dt.dt_year / 10) % 10; 2771.1Sis rt->year2 = dt.dt_year % 10; 2781.1Sis rt->weekday = dt.dt_wday; 2791.1Sis 2801.11Saymeric /* 2811.11Saymeric * release the clock 2821.1Sis */ 2831.1Sis rt->control2 &= ~A2CONTROL1_HOLD; 2841.1Sis 2851.18Smhitch return (0); 2861.1Sis} 287