1 /* $NetBSD: dsrtc.c,v 1.8 2005/12/11 12:16:46 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1998 Mark Brinicombe. 5 * Copyright (c) 1998 Causality Limited. 6 * All rights reserved. 7 * 8 * Written by Mark Brinicombe, Causality Limited 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Mark Brinicombe 21 * for the NetBSD Project. 22 * 4. The name of the company nor the name of the author may be used to 23 * endorse or promote products derived from this software without specific 24 * prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY CAUASLITY LIMITED ``AS IS'' AND ANY EXPRESS 27 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: dsrtc.c,v 1.8 2005/12/11 12:16:46 christos Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/conf.h> 46 #include <sys/device.h> 47 48 #include <machine/rtc.h> 49 50 #include <arm/footbridge/todclockvar.h> 51 #include <arm/footbridge/isa/ds1687reg.h> 52 53 #include <dev/isa/isavar.h> 54 55 #define NRTC_PORTS 2 56 57 struct dsrtc_softc { 58 struct device sc_dev; 59 bus_space_tag_t sc_iot; 60 bus_space_handle_t sc_ioh; 61 }; 62 63 void dsrtcattach __P((struct device *parent, struct device *self, void *aux)); 64 int dsrtcmatch __P((struct device *parent, struct cfdata *cf, void *aux)); 65 int ds1687_read __P((struct dsrtc_softc *sc, int addr)); 66 void ds1687_write __P((struct dsrtc_softc *sc, int addr, int data)); 67 int ds1687_ram_read __P((struct dsrtc_softc *sc, int addr)); 68 void ds1687_ram_write __P((struct dsrtc_softc *sc, int addr, int data)); 69 static void ds1687_bank_select __P((struct dsrtc_softc *, int)); 70 static int dsrtc_write __P((void *, rtc_t *)); 71 static int dsrtc_read __P((void *, rtc_t *)); 72 73 int 74 ds1687_read(sc, addr) 75 struct dsrtc_softc *sc; 76 int addr; 77 { 78 79 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr); 80 return(bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG)); 81 } 82 83 void 84 ds1687_write(sc, addr, data) 85 struct dsrtc_softc *sc; 86 int addr; 87 int data; 88 { 89 90 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr); 91 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG, data); 92 } 93 94 static void 95 ds1687_bank_select(sc, bank) 96 struct dsrtc_softc *sc; 97 int bank; 98 { 99 int data; 100 101 data = ds1687_read(sc, RTC_REG_A); 102 data &= ~RTC_REG_A_BANK_MASK; 103 if (bank) 104 data |= RTC_REG_A_BANK1; 105 ds1687_write(sc, RTC_REG_A, data); 106 } 107 108 #if 0 109 /* Nothing uses these yet */ 110 int 111 ds1687_ram_read(sc, addr) 112 struct dsrtc_softc *sc; 113 int addr; 114 { 115 if (addr < RTC_PC_RAM_SIZE) 116 return(ds1687_read(sc, RTC_PC_RAM_START + addr)); 117 118 addr -= RTC_PC_RAM_SIZE; 119 if (addr < RTC_BANK0_RAM_SIZE) 120 return(ds1687_read(sc, RTC_BANK0_RAM_START + addr)); 121 122 addr -= RTC_BANK0_RAM_SIZE; 123 if (addr < RTC_EXT_RAM_SIZE) { 124 int data; 125 126 ds1687_bank_select(sc, 1); 127 ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr); 128 data = ds1687_read(sc, RTC_EXT_RAM_DATA); 129 ds1687_bank_select(sc, 0); 130 return(data); 131 } 132 return(-1); 133 } 134 135 void 136 ds1687_ram_write(sc, addr, val) 137 struct dsrtc_softc *sc; 138 int addr; 139 int val; 140 { 141 if (addr < RTC_PC_RAM_SIZE) 142 return(ds1687_write(sc, RTC_PC_RAM_START + addr, val)); 143 144 addr -= RTC_PC_RAM_SIZE; 145 if (addr < RTC_BANK0_RAM_SIZE) 146 return(ds1687_write(sc, RTC_BANK0_RAM_START + addr, val)); 147 148 addr -= RTC_BANK0_RAM_SIZE; 149 if (addr < RTC_EXT_RAM_SIZE) { 150 ds1687_bank_select(sc, 1); 151 ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr); 152 ds1687_write(sc, RTC_EXT_RAM_DATA, val); 153 ds1687_bank_select(sc, 0); 154 } 155 } 156 #endif 157 158 static int 159 dsrtc_write(arg, rtc) 160 void *arg; 161 rtc_t *rtc; 162 { 163 struct dsrtc_softc *sc = arg; 164 165 ds1687_write(sc, RTC_SECONDS, rtc->rtc_sec); 166 ds1687_write(sc, RTC_MINUTES, rtc->rtc_min); 167 ds1687_write(sc, RTC_HOURS, rtc->rtc_hour); 168 ds1687_write(sc, RTC_DAYOFMONTH, rtc->rtc_day); 169 ds1687_write(sc, RTC_MONTH, rtc->rtc_mon); 170 ds1687_write(sc, RTC_YEAR, rtc->rtc_year); 171 ds1687_bank_select(sc, 1); 172 ds1687_write(sc, RTC_CENTURY, rtc->rtc_cen); 173 ds1687_bank_select(sc, 0); 174 return(1); 175 } 176 177 static int 178 dsrtc_read(arg, rtc) 179 void *arg; 180 rtc_t *rtc; 181 { 182 struct dsrtc_softc *sc = arg; 183 184 rtc->rtc_micro = 0; 185 rtc->rtc_centi = 0; 186 rtc->rtc_sec = ds1687_read(sc, RTC_SECONDS); 187 rtc->rtc_min = ds1687_read(sc, RTC_MINUTES); 188 rtc->rtc_hour = ds1687_read(sc, RTC_HOURS); 189 rtc->rtc_day = ds1687_read(sc, RTC_DAYOFMONTH); 190 rtc->rtc_mon = ds1687_read(sc, RTC_MONTH); 191 rtc->rtc_year = ds1687_read(sc, RTC_YEAR); 192 ds1687_bank_select(sc, 1); 193 rtc->rtc_cen = ds1687_read(sc, RTC_CENTURY); 194 ds1687_bank_select(sc, 0); 195 196 return(1); 197 } 198 199 /* device and attach structures */ 200 CFATTACH_DECL(ds1687rtc, sizeof(struct dsrtc_softc), 201 dsrtcmatch, dsrtcattach, NULL, NULL); 202 203 /* 204 * dsrtcmatch() 205 * 206 * Validate the IIC address to make sure its an RTC we understand 207 */ 208 209 int 210 dsrtcmatch(parent, cf, aux) 211 struct device *parent; 212 struct cfdata *cf; 213 void *aux; 214 { 215 struct isa_attach_args *ia = aux; 216 217 if (ia->ia_nio < 1 || 218 ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 219 return (0); 220 221 ia->ia_nio = 1; 222 ia->ia_io[0].ir_size = NRTC_PORTS; 223 224 ia->ia_niomem = 0; 225 ia->ia_nirq = 0; 226 ia->ia_ndrq = 0; 227 228 return(1); 229 } 230 231 /* 232 * dsrtcattach() 233 * 234 * Attach the rtc device 235 */ 236 237 void 238 dsrtcattach(parent, self, aux) 239 struct device *parent; 240 struct device *self; 241 void *aux; 242 { 243 struct dsrtc_softc *sc = (struct dsrtc_softc *)self; 244 struct isa_attach_args *ia = aux; 245 struct todclock_attach_args ta; 246 247 sc->sc_iot = ia->ia_iot; 248 if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 249 ia->ia_io[0].ir_size, 0, &sc->sc_ioh)) { 250 printf(": cannot map I/O space\n"); 251 return; 252 } 253 254 ds1687_write(sc, RTC_REG_A, RTC_REG_A_DV1); 255 ds1687_write(sc, RTC_REG_B, RTC_REG_B_BINARY | RTC_REG_B_24_HOUR); 256 257 if (!(ds1687_read(sc, RTC_REG_D) & RTC_REG_D_VRT)) 258 printf(": lithium cell is dead, RTC unreliable"); 259 printf("\n"); 260 261 ta.ta_name = "todclock"; 262 ta.ta_rtc_arg = sc; 263 ta.ta_rtc_write = dsrtc_write; 264 ta.ta_rtc_read = dsrtc_read; 265 ta.ta_flags = 0; 266 config_found(self, &ta, NULL); 267 } 268 269 /* End of dsrtc.c */ 270