1 /* $NetBSD: ds1743.c,v 1.1 2002/12/09 12:16:23 scw Exp $ */ 2 3 /* 4 * Copyright (c) 2001-2002 Wasabi Sysetms, Inc. 5 * Copyright (c) 1998 Mark Brinicombe. 6 * Copyright (c) 1998 Causality Limited. 7 * All rights reserved. 8 * 9 * Written by Mark Brinicombe, Causality Limited 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by Mark Brinicombe 22 * for the NetBSD Project. 23 * 4. The name of the company nor the name of the author may be used to 24 * endorse or promote products derived from this software without specific 25 * prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY CAUASLITY LIMITED ``AS IS'' AND ANY EXPRESS 28 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/device.h> 43 44 #include <machine/rtc.h> 45 #include <machine/bus.h> 46 47 #include <evbppc/walnut/dev/ds1743reg.h> 48 #include <evbppc/walnut/dev/todclockvar.h> 49 #include <evbppc/walnut/dev/pbusvar.h> 50 51 struct dsrtc_softc { 52 struct device sc_dev; 53 bus_space_tag_t sc_iot; 54 bus_space_handle_t sc_ioh; 55 }; 56 57 static void dsrtcattach(struct device *, struct device *, void *); 58 static int dsrtcmatch(struct device *, struct cfdata *, void *); 59 #if 0 /* Nothing uses these yet */ 60 static int ds1743_ram_read(struct dsrtc_softc *, int); 61 static void ds1743_ram_write(struct dsrtc_softc *, int, int); 62 #endif 63 64 static int dsrtc_read(void *, rtc_t *); 65 static int dsrtc_write(void *, rtc_t *); 66 static inline u_char ds1743_read(struct dsrtc_softc *, int); 67 static inline void ds1743_write(struct dsrtc_softc *, int, u_char); 68 static u_char ds1743_lock(struct dsrtc_softc *, u_char); 69 static void ds1743_unlock(struct dsrtc_softc *, u_char); 70 71 /* device and attach structures */ 72 CFATTACH_DECL(dsrtc, sizeof(struct dsrtc_softc), 73 dsrtcmatch, dsrtcattach, NULL, NULL); 74 75 /* 76 * dsrtcmatch() 77 * 78 * Validate the IIC address to make sure its an RTC we understand 79 */ 80 int ds1743found = 0; 81 82 #define DS_SCRATCH_ADDR 0x1FF7 83 84 static int 85 dsrtcmatch(struct device *parent, struct cfdata *cf, void *aux) 86 { 87 struct pbus_attach_args *paa = aux; 88 int retval = !ds1743found; 89 bus_space_handle_t h; 90 u_int8_t x; 91 92 /* match only RTC devices */ 93 if (strcmp(paa->pb_name, cf->cf_name) != 0) 94 return 0; 95 96 if (bus_space_map(0, paa->pb_addr, DS_SIZE, 0, &h)) { 97 printf("%s: can't map i/o space\n", paa->pb_name); 98 return 0; 99 } 100 101 /* Read one byte of what's supposed to be NVRAM */ 102 x = bus_space_read_1(0, h, DS_SCRATCH_ADDR); 103 bus_space_write_1(0, h, DS_SCRATCH_ADDR, 0xAA); 104 if (bus_space_read_1(0, h, DS_SCRATCH_ADDR) != 0xAA) { 105 retval = 0; 106 goto done; 107 } 108 109 bus_space_write_1(0, h, DS_SCRATCH_ADDR, 0x55); 110 if (bus_space_read_1(0, h, DS_SCRATCH_ADDR) != 0x55) { 111 retval = 0; 112 goto done; 113 } 114 115 /* Restore scratch byte value */ 116 bus_space_write_1(0, h, DS_SCRATCH_ADDR, x); 117 done: 118 bus_space_unmap(0, h, DS_SIZE); 119 120 return retval; 121 } 122 123 /* 124 * dsrtcattach() 125 * 126 * Attach the rtc device 127 */ 128 129 static void 130 dsrtcattach(struct device *parent, struct device *self, void *aux) 131 { 132 struct dsrtc_softc *sc = (struct dsrtc_softc *)self; 133 struct pbus_attach_args *paa = aux; 134 struct todclock_attach_args ta; 135 136 ds1743found = 1; 137 138 sc->sc_iot = 0; 139 sc->sc_ioh = paa->pb_addr; 140 if (bus_space_map(sc->sc_iot, paa->pb_addr, DS_SIZE, 0, &sc->sc_ioh)) { 141 printf(": can't map i/o space\n"); 142 return; 143 } 144 145 ds1743_unlock(sc,0); /* Make sure the clock is running */ 146 if ((ds1743_read(sc, DS_DAY) & DS_CTL_BF) == 0) 147 printf(": lithium cell is dead, RTC unreliable"); 148 printf("\n"); 149 150 #ifdef DEBUG 151 { 152 rtc_t rtc; 153 dsrtc_read(sc,&rtc); 154 printf("RTC: %d/%d/%02d%02d %d:%02d:%02d\n", 155 rtc.rtc_mon, rtc.rtc_day, rtc.rtc_cen, rtc.rtc_year, 156 rtc.rtc_hour, rtc.rtc_min, rtc.rtc_sec); 157 } 158 #endif 159 160 161 ta.ta_name = "todclock"; 162 ta.ta_rtc_arg = sc; 163 ta.ta_rtc_write = dsrtc_write; 164 ta.ta_rtc_read = dsrtc_read; 165 ta.ta_flags = 0; 166 config_found(self, &ta, NULL); 167 } 168 169 static inline u_char 170 ds1743_read(struct dsrtc_softc *sc, int addr) 171 { 172 173 return(bus_space_read_1(sc->sc_iot, sc->sc_ioh, addr)); 174 } 175 176 static inline void 177 ds1743_write(struct dsrtc_softc *sc, int addr, u_char data) 178 { 179 180 bus_space_write_1(sc->sc_iot, sc->sc_ioh, addr, data); 181 } 182 183 184 #if 0 /* Nothing uses these yet */ 185 static u_char 186 ds1743_ram_read(struct dsrtc_softc *sc, int addr) 187 { 188 189 if (addr >= DS_RAM_SIZE) 190 return(-1); 191 return(ds1743_read(sc, addr)); 192 } 193 194 static void 195 ds1743_ram_write(struct dsrtc_softc *sc, int addr, u_char val) 196 { 197 198 if (addr >= DS_RAM_SIZE) 199 return (-1); 200 ds1743_write(sc,addr,val); 201 } 202 #endif 203 204 #define BCD(x) ((((x)/10)<<4)|(x%10)) 205 #define unBCD(v,x) v=x; v = ((v>>4) & 0xf)*10+(v & 0xf) 206 207 static u_char 208 ds1743_lock(struct dsrtc_softc *sc, u_char mode) 209 { 210 u_char octl,ctl; 211 212 octl = ds1743_read(sc,DS_CENTURY); 213 ctl = octl | (mode & DS_CTL_RW); 214 ds1743_write(sc,DS_CENTURY, ctl); /* Lock RTC for both reading and writing */ 215 return octl; 216 } 217 218 static void 219 ds1743_unlock(struct dsrtc_softc *sc, u_char key) 220 { 221 int ctl; 222 223 ctl = ds1743_read(sc,DS_CENTURY); 224 ctl = (ctl & 0x3f) | (key & DS_CTL_RW); 225 ds1743_write(sc,DS_CENTURY, ctl); /* Enable updates */ 226 } 227 228 static int 229 dsrtc_write(void * arg, rtc_t * rtc) 230 { 231 struct dsrtc_softc *sc = arg; 232 u_char key; 233 234 key = ds1743_lock(sc,DS_CTL_W); 235 236 ds1743_write(sc, DS_SECONDS, BCD(rtc->rtc_sec) & 0x7f); 237 ds1743_write(sc, DS_MINUTES, BCD(rtc->rtc_min) & 0x7f); 238 ds1743_write(sc, DS_HOURS, BCD(rtc->rtc_hour) & 0x3f); 239 ds1743_write(sc, DS_DATE, BCD(rtc->rtc_day) & 0x3f); 240 ds1743_write(sc, DS_MONTH, BCD(rtc->rtc_mon) & 0x1f); 241 ds1743_write(sc, DS_YEAR, BCD(rtc->rtc_year)); 242 ds1743_write(sc, DS_CENTURY, ((ds1743_read(sc,DS_CENTURY) & DS_CTL_RW) 243 | BCD(rtc->rtc_cen))); 244 245 ds1743_unlock(sc,key); 246 dsrtc_read(arg,rtc); 247 return(1); 248 } 249 250 static int 251 dsrtc_read(void *arg, rtc_t *rtc) 252 { 253 struct dsrtc_softc *sc = arg; 254 u_char key; 255 256 key = ds1743_lock(sc,DS_CTL_R); 257 rtc->rtc_micro = 0; 258 rtc->rtc_centi = 0; 259 unBCD(rtc->rtc_sec,ds1743_read(sc, DS_SECONDS) & 0x7f); 260 unBCD(rtc->rtc_min,ds1743_read(sc, DS_MINUTES) & 0x7f); 261 unBCD(rtc->rtc_hour, ds1743_read(sc, DS_HOURS) & 0x3f); 262 unBCD(rtc->rtc_day, ds1743_read(sc, DS_DATE) & 0x3f); 263 unBCD(rtc->rtc_mon,ds1743_read(sc, DS_MONTH) & 0x1f); 264 unBCD(rtc->rtc_year, ds1743_read(sc, DS_YEAR)); 265 unBCD(rtc->rtc_cen, ds1743_read(sc, DS_CENTURY) & ~DS_CTL_RW); 266 267 ds1743_unlock(sc,key); 268 return(1); 269 } 270