1 /* $NetBSD: rtclock.c,v 1.23 2009/01/03 09:32:13 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.23 2009/01/03 09:32:13 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 CFATTACH_DECL_NEW(rtc, sizeof(struct rtc_softc), 65 rtc_match, rtc_attach, NULL, NULL); 66 67 static int rtc_attached; 68 69 static int 70 rtc_match(device_t parent, cfdata_t cf, void *aux) 71 { 72 struct intio_attach_args *ia = aux; 73 74 if (strcmp(ia->ia_name, "rtc") != 0) 75 return (0); 76 if (rtc_attached) 77 return (0); 78 79 /* fixed address */ 80 if (ia->ia_addr != RTC_ADDR) 81 return (0); 82 if (ia->ia_intr != -1) 83 return (0); 84 85 return (1); 86 } 87 88 static void 89 rtc_attach(device_t parent, device_t self, void *aux) 90 { 91 struct rtc_softc *sc = device_private(self); 92 struct intio_attach_args *ia = aux; 93 int r; 94 95 rtc_attached = 1; 96 97 ia->ia_size = 0x20; 98 r = intio_map_allocate_region(parent, ia, INTIO_MAP_ALLOCATE); 99 #ifdef DIAGNOSTIC 100 if (r) 101 panic("IO map for RTC corruption??"); 102 #endif 103 104 105 sc->sc_bst = ia->ia_bst; 106 bus_space_map(sc->sc_bst, ia->ia_addr, 0x2000, 0, &sc->sc_bht); 107 108 sc->sc_todr.cookie = sc; 109 sc->sc_todr.todr_gettime_ymdhms = rtgettod; 110 sc->sc_todr.todr_settime_ymdhms = rtsettod; 111 todr_attach(&sc->sc_todr); 112 113 aprint_normal(": RP5C15\n"); 114 } 115 116 static int 117 rtgettod(todr_chip_handle_t tch, struct clock_ymdhms *dt) 118 { 119 struct rtc_softc *rtc = tch->cookie; 120 121 /* hold clock */ 122 RTC_WRITE(RTC_MODE, RTC_HOLD_CLOCK); 123 124 /* read it */ 125 dt->dt_sec = RTC_REG(RTC_SEC10) * 10 + RTC_REG(RTC_SEC); 126 dt->dt_min = RTC_REG(RTC_MIN10) * 10 + RTC_REG(RTC_MIN); 127 dt->dt_hour = RTC_REG(RTC_HOUR10) * 10 + RTC_REG(RTC_HOUR); 128 dt->dt_day = RTC_REG(RTC_DAY10) * 10 + RTC_REG(RTC_DAY); 129 dt->dt_mon = RTC_REG(RTC_MON10) * 10 + RTC_REG(RTC_MON); 130 dt->dt_year = RTC_REG(RTC_YEAR10) * 10 + RTC_REG(RTC_YEAR) 131 +RTC_BASE_YEAR; 132 133 /* let it run again.. */ 134 RTC_WRITE(RTC_MODE, RTC_FREE_CLOCK); 135 136 return 0; 137 } 138 139 static int 140 rtsettod(todr_chip_handle_t tch, struct clock_ymdhms *dt) 141 { 142 struct rtc_softc *rtc = tch->cookie; 143 u_char sec1, sec2; 144 u_char min1, min2; 145 u_char hour1, hour2; 146 u_char day1, day2; 147 u_char mon1, mon2; 148 u_char year1, year2; 149 150 /* prepare values to be written to clock */ 151 sec1 = dt->dt_sec / 10; 152 sec2 = dt->dt_sec % 10; 153 min1 = dt->dt_min / 10; 154 min2 = dt->dt_min % 10; 155 hour1 = dt->dt_hour / 10; 156 hour2 = dt->dt_hour % 10; 157 158 day1 = dt->dt_day / 10; 159 day2 = dt->dt_day % 10; 160 mon1 = dt->dt_mon / 10; 161 mon2 = dt->dt_mon % 10; 162 year1 = (dt->dt_year - RTC_BASE_YEAR) / 10; 163 year2 = dt->dt_year % 10; 164 165 RTC_WRITE(RTC_MODE, RTC_HOLD_CLOCK); 166 RTC_WRITE(RTC_SEC10, sec1); 167 RTC_WRITE(RTC_SEC, sec2); 168 RTC_WRITE(RTC_MIN10, min1); 169 RTC_WRITE(RTC_MIN, min2); 170 RTC_WRITE(RTC_HOUR10, hour1); 171 RTC_WRITE(RTC_HOUR, hour2); 172 RTC_WRITE(RTC_DAY10, day1); 173 RTC_WRITE(RTC_DAY, day2); 174 RTC_WRITE(RTC_MON10, mon1); 175 RTC_WRITE(RTC_MON, mon2); 176 RTC_WRITE(RTC_YEAR10, year1); 177 RTC_WRITE(RTC_YEAR, year2); 178 RTC_WRITE(RTC_MODE, RTC_FREE_CLOCK); 179 180 return 0; 181 } 182