1 /*- 2 * Copyright (c) 2002 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by UCHIYAMA Yasushi. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the NetBSD 19 * Foundation, Inc. and its contributors. 20 * 4. Neither the name of The NetBSD Foundation nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: rtc.c,v 1.1 2006/09/20 00:41:11 uwe Exp $"); 39 40 #include <sys/param.h> 41 #include <sys/kernel.h> 42 #include <sys/device.h> 43 #include <sys/malloc.h> 44 #include <sys/systm.h> 45 #ifdef GPROF 46 #include <sys/gmon.h> 47 #endif 48 49 #include <dev/clock_subr.h> 50 51 #include <sh3/rtcreg.h> 52 53 54 struct rtc_softc { 55 struct device sc_dev; 56 57 struct todr_chip_handle sc_todr; 58 }; 59 60 static int rtc_match(struct device *, struct cfdata *, void *); 61 static void rtc_attach(struct device *, struct device *, void *); 62 63 CFATTACH_DECL(rtc, sizeof(struct rtc_softc), 64 rtc_match, rtc_attach, NULL, NULL); 65 66 67 /* todr(9) methods */ 68 static int rtc_gettime_ymdhms(todr_chip_handle_t, struct clock_ymdhms *); 69 static int rtc_settime_ymdhms(todr_chip_handle_t, struct clock_ymdhms *); 70 71 72 73 static int 74 rtc_match(struct device *parent, struct cfdata *cfp, void *aux) 75 { 76 77 return 1; 78 } 79 80 81 static void 82 rtc_attach(struct device *parent, struct device *self, void *aux) 83 { 84 struct rtc_softc *sc = (void *)self; 85 86 printf("\n"); 87 88 /* Make sure RTC is started */ 89 _reg_write_1(SH_(RCR2), SH_RCR2_ENABLE | SH_RCR2_START); 90 91 #ifdef RTC_DEBUG 92 { 93 struct clock_ymdhms dt; 94 int error; 95 96 error = rtc_gettime_ymdhms(NULL, &dt); 97 if (error) 98 printf("%s: error %d\n", sc->sc_dev.dv_xname, error); 99 else 100 printf("%s: %04d-%02d-%02d %02d:%02d:%02d\n", 101 sc->sc_dev.dv_xname, 102 dt.dt_year, dt.dt_mon, dt.dt_day, 103 dt.dt_hour, dt.dt_min, dt.dt_sec); 104 } 105 #endif 106 sc->sc_todr.cookie = sc; 107 sc->sc_todr.todr_gettime_ymdhms = rtc_gettime_ymdhms; 108 sc->sc_todr.todr_settime_ymdhms = rtc_settime_ymdhms; 109 110 todr_attach(&sc->sc_todr); 111 } 112 113 114 static int 115 rtc_gettime_ymdhms(todr_chip_handle_t h, struct clock_ymdhms *dt) 116 { 117 unsigned int year; 118 int retry = 8; 119 120 /* disable carry interrupt */ 121 _reg_bclr_1(SH_(RCR1), SH_RCR1_CIE); 122 123 do { 124 uint8_t r = _reg_read_1(SH_(RCR1)); 125 r &= ~SH_RCR1_CF; 126 r |= SH_RCR1_AF; /* don't clear alarm flag */ 127 _reg_write_1(SH_(RCR1), r); 128 129 if (CPU_IS_SH3) 130 year = _reg_read_1(SH3_RYRCNT); 131 else 132 year = _reg_read_2(SH4_RYRCNT) & 0x00ff; 133 dt->dt_year = FROMBCD(year); 134 135 /* read counter */ 136 #define RTCGET(x, y) \ 137 dt->dt_ ## x = FROMBCD(_reg_read_1(SH_(R ## y ## CNT))) 138 139 RTCGET(mon, MON); 140 RTCGET(wday, WK); 141 RTCGET(day, DAY); 142 RTCGET(hour, HR); 143 RTCGET(min, MIN); 144 RTCGET(sec, SEC); 145 #undef RTCGET 146 } while ((_reg_read_1(SH_(RCR1)) & SH_RCR1_CF) && --retry > 0); 147 148 if (retry == 0) 149 return EIO; 150 151 dt->dt_year += 1900; 152 if (dt->dt_year < POSIX_BASE_YEAR) 153 dt->dt_year += 100; 154 155 return 0; 156 } 157 158 159 static int 160 rtc_settime_ymdhms(todr_chip_handle_t h, struct clock_ymdhms *dt) 161 { 162 unsigned int year; 163 uint8_t r; 164 165 year = TOBCD(dt->dt_year % 100); 166 167 /* stop clock */ 168 r = _reg_read_1(SH_(RCR2)); 169 r |= SH_RCR2_RESET; 170 r &= ~SH_RCR2_START; 171 _reg_write_1(SH_(RCR2), r); 172 173 /* set time */ 174 if (CPU_IS_SH3) 175 _reg_write_1(SH3_RYRCNT, year); 176 else 177 _reg_write_2(SH4_RYRCNT, year); 178 179 #define RTCSET(x, y) \ 180 _reg_write_1(SH_(R ## x ## CNT), TOBCD(dt->dt_ ## y)) 181 182 RTCSET(MON, mon); 183 RTCSET(WK, wday); 184 RTCSET(DAY, day); 185 RTCSET(HR, hour); 186 RTCSET(MIN, min); 187 RTCSET(SEC, sec); 188 189 #undef RTCSET 190 191 /* start clock */ 192 _reg_write_1(SH_(RCR2), r | SH_RCR2_START); 193 194 return 0; 195 } 196