a2kbbc.c revision 1.22
11.22Srmind/* $NetBSD: a2kbbc.c,v 1.22 2011/02/08 20:20:08 rmind Exp $ */ 21.1Sis 31.1Sis/* 41.22Srmind * Copyright (c) 1988 University of Utah. 51.1Sis * Copyright (c) 1982, 1990 The Regents of the University of California. 61.1Sis * All rights reserved. 71.1Sis * 81.1Sis * This code is derived from software contributed to Berkeley by 91.1Sis * the Systems Programming Group of the University of Utah Computer 101.1Sis * Science Department. 111.1Sis * 121.1Sis * Redistribution and use in source and binary forms, with or without 131.1Sis * modification, are permitted provided that the following conditions 141.1Sis * are met: 151.1Sis * 1. Redistributions of source code must retain the above copyright 161.1Sis * notice, this list of conditions and the following disclaimer. 171.1Sis * 2. Redistributions in binary form must reproduce the above copyright 181.1Sis * notice, this list of conditions and the following disclaimer in the 191.1Sis * documentation and/or other materials provided with the distribution. 201.15Sagc * 3. Neither the name of the University nor the names of its contributors 211.15Sagc * may be used to endorse or promote products derived from this software 221.15Sagc * without specific prior written permission. 231.15Sagc * 241.15Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251.15Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261.15Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271.15Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281.15Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291.15Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301.15Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311.15Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321.15Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331.15Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341.15Sagc * SUCH DAMAGE. 351.15Sagc * 361.15Sagc * from: Utah $Hdr: clock.c 1.18 91/01/21$ 371.15Sagc * 381.15Sagc * @(#)clock.c 7.6 (Berkeley) 5/7/91 391.15Sagc */ 401.15Sagc 411.12Saymeric#include <sys/cdefs.h> 421.22Srmind__KERNEL_RCSID(0, "$NetBSD: a2kbbc.c,v 1.22 2011/02/08 20:20:08 rmind Exp $"); 431.1Sis 441.1Sis#include <sys/param.h> 451.1Sis#include <sys/kernel.h> 461.1Sis#include <sys/device.h> 471.1Sis#include <sys/systm.h> 481.1Sis#include <machine/psl.h> 491.1Sis#include <machine/cpu.h> 501.1Sis#include <amiga/amiga/device.h> 511.1Sis#include <amiga/amiga/custom.h> 521.1Sis#include <amiga/amiga/cia.h> 531.1Sis#include <amiga/dev/rtc.h> 541.1Sis#include <amiga/dev/zbusvar.h> 551.1Sis 561.1Sis#include <dev/clock_subr.h> 571.1Sis 581.11Saymericint a2kbbc_match(struct device *, struct cfdata *, void *); 591.11Saymericvoid a2kbbc_attach(struct device *, struct device *, void *); 601.1Sis 611.14SthorpejCFATTACH_DECL(a2kbbc, sizeof(struct device), 621.14Sthorpej a2kbbc_match, a2kbbc_attach, NULL, NULL); 631.1Sis 641.1Sisvoid *a2kclockaddr; 651.20Sgdamoreint a2kugettod(todr_chip_handle_t, struct clock_ymdhms *); 661.20Sgdamoreint a2kusettod(todr_chip_handle_t, struct clock_ymdhms *); 671.18Smhitchstatic struct todr_chip_handle a2ktodr; 681.1Sis 691.1Sisint 701.11Saymerica2kbbc_match(struct device *pdp, struct cfdata *cfp, void *auxp) 711.1Sis{ 721.21Smhitch struct clock_ymdhms dt; 731.10Skleink static int a2kbbc_matched = 0; 741.10Skleink 751.1Sis if (!matchname("a2kbbc", auxp)) 761.2Skleink return (0); 771.1Sis 781.10Skleink /* Allow only one instance. */ 791.10Skleink if (a2kbbc_matched) 801.10Skleink return (0); 811.1Sis 821.11Saymeric if (/* is_a1200() || */ is_a3000() || is_a4000() 831.3Sis#ifdef DRACO 841.3Sis || is_draco() 851.3Sis#endif 861.3Sis ) 871.2Skleink return (0); 881.1Sis 891.16Sjmc a2kclockaddr = (void *)__UNVOLATILE(ztwomap(0xdc0000)); 901.21Smhitch if (a2kugettod(&a2ktodr, &dt) != 0) 911.2Skleink return (0); 921.1Sis 931.10Skleink a2kbbc_matched = 1; 941.2Skleink return (1); 951.1Sis} 961.1Sis 971.1Sis/* 981.1Sis * Attach us to the rtc function pointers. 991.1Sis */ 1001.1Sisvoid 1011.11Saymerica2kbbc_attach(struct device *pdp, struct device *dp, void *auxp) 1021.1Sis{ 1031.1Sis printf("\n"); 1041.16Sjmc a2kclockaddr = (void *)__UNVOLATILE(ztwomap(0xdc0000)); 1051.1Sis 1061.18Smhitch a2ktodr.cookie = a2kclockaddr; 1071.20Sgdamore a2ktodr.todr_gettime_ymdhms = a2kugettod; 1081.20Sgdamore a2ktodr.todr_settime_ymdhms = a2kusettod; 1091.18Smhitch todr_attach(&a2ktodr); 1101.1Sis} 1111.1Sis 1121.6Sisint 1131.20Sgdamorea2kugettod(todr_chip_handle_t h, struct clock_ymdhms *dt) 1141.1Sis{ 1151.1Sis struct rtclock2000 *rt; 1161.1Sis int i; 1171.1Sis 1181.1Sis rt = a2kclockaddr; 1191.1Sis 1201.1Sis /* 1211.1Sis * hold clock 1221.1Sis */ 1231.1Sis rt->control1 |= A2CONTROL1_HOLD; 1241.1Sis i = 0x1000; 1251.1Sis while (rt->control1 & A2CONTROL1_BUSY && i--) 1261.1Sis ; 1271.1Sis if (rt->control1 & A2CONTROL1_BUSY) 1281.19Smhitch return (ENXIO); /* Give up and say it's not there */ 1291.1Sis 1301.1Sis /* Copy the info. Careful about the order! */ 1311.20Sgdamore dt->dt_sec = rt->second1 * 10 + rt->second2; 1321.20Sgdamore dt->dt_min = rt->minute1 * 10 + rt->minute2; 1331.20Sgdamore dt->dt_hour = (rt->hour1 & 3) * 10 + rt->hour2; 1341.20Sgdamore dt->dt_day = rt->day1 * 10 + rt->day2; 1351.20Sgdamore dt->dt_mon = rt->month1 * 10 + rt->month2; 1361.20Sgdamore dt->dt_year = rt->year1 * 10 + rt->year2; 1371.20Sgdamore dt->dt_wday = rt->weekday; 1381.1Sis 1391.1Sis /* 1401.1Sis * The oki clock chip has a register to put the clock into 1411.1Sis * 12/24h mode. 1421.1Sis * 1431.1Sis * clockmode | A2HOUR1_PM 1441.1Sis * 24h 12h | am = 0, pm = 1 1451.1Sis * --------------------------------- 1461.1Sis * 0 12 | 0 1471.1Sis * 1 1 | 0 1481.1Sis * .. .. | 0 1491.1Sis * 11 11 | 0 1501.1Sis * 12 12 | 1 1511.1Sis * 13 1 | 1 1521.1Sis * .. .. | 1 1531.1Sis * 23 11 | 1 1541.1Sis * 1551.1Sis */ 1561.1Sis 1571.1Sis if ((rt->control3 & A2CONTROL3_24HMODE) == 0) { 1581.20Sgdamore if ((rt->hour1 & A2HOUR1_PM) == 0 && dt->dt_hour == 12) 1591.20Sgdamore dt->dt_hour = 0; 1601.20Sgdamore else if ((rt->hour1 & A2HOUR1_PM) && dt->dt_hour != 12) 1611.20Sgdamore dt->dt_hour += 12; 1621.1Sis } 1631.1Sis 1641.11Saymeric /* 1651.11Saymeric * release the clock 1661.1Sis */ 1671.1Sis rt->control1 &= ~A2CONTROL1_HOLD; 1681.1Sis 1691.20Sgdamore dt->dt_year += CLOCK_BASE_YEAR; 1701.20Sgdamore if (dt->dt_year < STARTOFTIME) 1711.20Sgdamore dt->dt_year += 100; 1721.20Sgdamore 1731.20Sgdamore /* 1741.20Sgdamore * Note that this check is redundant with one in kern_todr.c, but 1751.20Sgdamore * attach relies on it being here. 1761.20Sgdamore */ 1771.20Sgdamore if ((dt->dt_hour > 23) || 1781.20Sgdamore (dt->dt_day > 31) || 1791.20Sgdamore (dt->dt_mon > 12) || 1801.20Sgdamore /* (dt->dt_year < STARTOFTIME) || */ (dt->dt_year > 2036)) 1811.19Smhitch return (EINVAL); 1821.11Saymeric 1831.18Smhitch return (0); 1841.1Sis} 1851.1Sis 1861.1Sisint 1871.20Sgdamorea2kusettod(todr_chip_handle_t h, struct clock_ymdhms *dt) 1881.1Sis{ 1891.1Sis struct rtclock2000 *rt; 1901.1Sis int ampm, i; 1911.1Sis 1921.1Sis rt = a2kclockaddr; 1931.11Saymeric /* 1941.1Sis * there seem to be problems with the bitfield addressing 1951.1Sis * currently used.. 1961.1Sis */ 1971.1Sis if (! rt) 1981.19Smhitch return (ENXIO); 1991.1Sis 2001.1Sis /* 2011.1Sis * hold clock 2021.1Sis */ 2031.1Sis rt->control1 |= A2CONTROL1_HOLD; 2041.1Sis i = 0x1000; 2051.1Sis while (rt->control1 & A2CONTROL1_BUSY && i--) 2061.1Sis ; 2071.1Sis if (rt->control1 & A2CONTROL1_BUSY) 2081.19Smhitch return (ENXIO); /* Give up and say it's not there */ 2091.1Sis 2101.1Sis ampm = 0; 2111.1Sis if ((rt->control3 & A2CONTROL3_24HMODE) == 0) { 2121.20Sgdamore if (dt->dt_hour >= 12) { 2131.1Sis ampm = A2HOUR1_PM; 2141.20Sgdamore if (dt->dt_hour != 12) 2151.20Sgdamore dt->dt_hour -= 12; 2161.20Sgdamore } else if (dt->dt_hour == 0) { 2171.20Sgdamore dt->dt_hour = 12; 2181.1Sis } 2191.1Sis } 2201.20Sgdamore rt->hour1 = (dt->dt_hour / 10) | ampm; 2211.20Sgdamore rt->hour2 = dt->dt_hour % 10; 2221.20Sgdamore rt->second1 = dt->dt_sec / 10; 2231.20Sgdamore rt->second2 = dt->dt_sec % 10; 2241.20Sgdamore rt->minute1 = dt->dt_min / 10; 2251.20Sgdamore rt->minute2 = dt->dt_min % 10; 2261.20Sgdamore rt->day1 = dt->dt_day / 10; 2271.20Sgdamore rt->day2 = dt->dt_day % 10; 2281.20Sgdamore rt->month1 = dt->dt_mon / 10; 2291.20Sgdamore rt->month2 = dt->dt_mon % 10; 2301.20Sgdamore rt->year1 = (dt->dt_year / 10) % 10; 2311.20Sgdamore rt->year2 = dt->dt_year % 10; 2321.20Sgdamore rt->weekday = dt->dt_wday; 2331.1Sis 2341.11Saymeric /* 2351.11Saymeric * release the clock 2361.1Sis */ 2371.1Sis rt->control2 &= ~A2CONTROL1_HOLD; 2381.1Sis 2391.18Smhitch return (0); 2401.1Sis} 241