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