1 /* $NetBSD: rtclock.c,v 1.22 2008/06/25 08:14:59 isaki Exp $ */ 2 3 /* 4 * Copyright 1993, 1994 Masaru Oki 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Masaru Oki. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * X680x0 internal real time clock interface 35 * alarm is not supported. 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: rtclock.c,v 1.22 2008/06/25 08:14:59 isaki Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/buf.h> 44 #include <sys/malloc.h> 45 #include <sys/proc.h> 46 #include <sys/reboot.h> 47 #include <sys/file.h> 48 #include <sys/kernel.h> 49 #include <sys/device.h> 50 51 #include <machine/bus.h> 52 53 #include <dev/clock_subr.h> 54 55 #include <arch/x68k/dev/rtclock_var.h> 56 #include <arch/x68k/dev/intiovar.h> 57 58 static int rtgettod(todr_chip_handle_t, struct clock_ymdhms *); 59 static int rtsettod(todr_chip_handle_t, struct clock_ymdhms *); 60 61 static int rtc_match(device_t, cfdata_t, void *); 62 static void rtc_attach(device_t, device_t, void *); 63 64 int rtclockinit(void); 65 66 CFATTACH_DECL_NEW(rtc, sizeof(struct rtc_softc), 67 rtc_match, rtc_attach, NULL, NULL); 68 69 static int rtc_attached; 70 71 static int 72 rtc_match(device_t parent, cfdata_t cf, void *aux) 73 { 74 struct intio_attach_args *ia = aux; 75 76 if (strcmp(ia->ia_name, "rtc") != 0) 77 return (0); 78 if (rtc_attached) 79 return (0); 80 81 /* fixed address */ 82 if (ia->ia_addr != RTC_ADDR) 83 return (0); 84 if (ia->ia_intr != -1) 85 return (0); 86 87 return (1); 88 } 89 90 static void 91 rtc_attach(device_t parent, device_t self, void *aux) 92 { 93 struct rtc_softc *sc = device_private(self); 94 struct intio_attach_args *ia = aux; 95 int r; 96 97 rtc_attached = 1; 98 99 ia->ia_size = 0x20; 100 r = intio_map_allocate_region(parent, ia, INTIO_MAP_ALLOCATE); 101 #ifdef DIAGNOSTIC 102 if (r) 103 panic("IO map for RTC corruption??"); 104 #endif 105 106 107 sc->sc_bst = ia->ia_bst; 108 bus_space_map(sc->sc_bst, ia->ia_addr, 0x2000, 0, &sc->sc_bht); 109 110 sc->sc_todr.cookie = sc; 111 sc->sc_todr.todr_gettime_ymdhms = rtgettod; 112 sc->sc_todr.todr_settime_ymdhms = rtsettod; 113 todr_attach(&sc->sc_todr); 114 115 aprint_normal(": RP5C15\n"); 116 } 117 118 static int 119 rtgettod(todr_chip_handle_t tch, struct clock_ymdhms *dt) 120 { 121 struct rtc_softc *rtc = tch->cookie; 122 123 /* hold clock */ 124 RTC_WRITE(RTC_MODE, RTC_HOLD_CLOCK); 125 126 /* read it */ 127 dt->dt_sec = RTC_REG(RTC_SEC10) * 10 + RTC_REG(RTC_SEC); 128 dt->dt_min = RTC_REG(RTC_MIN10) * 10 + RTC_REG(RTC_MIN); 129 dt->dt_hour = RTC_REG(RTC_HOUR10) * 10 + RTC_REG(RTC_HOUR); 130 dt->dt_day = RTC_REG(RTC_DAY10) * 10 + RTC_REG(RTC_DAY); 131 dt->dt_mon = RTC_REG(RTC_MON10) * 10 + RTC_REG(RTC_MON); 132 dt->dt_year = RTC_REG(RTC_YEAR10) * 10 + RTC_REG(RTC_YEAR) 133 +RTC_BASE_YEAR; 134 135 /* let it run again.. */ 136 RTC_WRITE(RTC_MODE, RTC_FREE_CLOCK); 137 138 return 0; 139 } 140 141 static int 142 rtsettod(todr_chip_handle_t tch, struct clock_ymdhms *dt) 143 { 144 struct rtc_softc *rtc = tch->cookie; 145 u_char sec1, sec2; 146 u_char min1, min2; 147 u_char hour1, hour2; 148 u_char day1, day2; 149 u_char mon1, mon2; 150 u_char year1, year2; 151 152 /* prepare values to be written to clock */ 153 sec1 = dt->dt_sec / 10; 154 sec2 = dt->dt_sec % 10; 155 min1 = dt->dt_min / 10; 156 min2 = dt->dt_min % 10; 157 hour1 = dt->dt_hour / 10; 158 hour2 = dt->dt_hour % 10; 159 160 day1 = dt->dt_day / 10; 161 day2 = dt->dt_day % 10; 162 mon1 = dt->dt_mon / 10; 163 mon2 = dt->dt_mon % 10; 164 year1 = (dt->dt_year - RTC_BASE_YEAR) / 10; 165 year2 = dt->dt_year % 10; 166 167 RTC_WRITE(RTC_MODE, RTC_HOLD_CLOCK); 168 RTC_WRITE(RTC_SEC10, sec1); 169 RTC_WRITE(RTC_SEC, sec2); 170 RTC_WRITE(RTC_MIN10, min1); 171 RTC_WRITE(RTC_MIN, min2); 172 RTC_WRITE(RTC_HOUR10, hour1); 173 RTC_WRITE(RTC_HOUR, hour2); 174 RTC_WRITE(RTC_DAY10, day1); 175 RTC_WRITE(RTC_DAY, day2); 176 RTC_WRITE(RTC_MON10, mon1); 177 RTC_WRITE(RTC_MON, mon2); 178 RTC_WRITE(RTC_YEAR10, year1); 179 RTC_WRITE(RTC_YEAR, year2); 180 RTC_WRITE(RTC_MODE, RTC_FREE_CLOCK); 181 182 return 0; 183 } 184