1 /* $NetBSD: dsrtc.c,v 1.4 2002/10/02 15:45:10 thorpej 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/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/conf.h> 43 #include <sys/device.h> 44 45 #include <machine/rtc.h> 46 47 #include <arm/footbridge/todclockvar.h> 48 #include <arm/footbridge/isa/ds1687reg.h> 49 50 #include <dev/isa/isavar.h> 51 52 #define NRTC_PORTS 2 53 54 struct dsrtc_softc { 55 struct device sc_dev; 56 bus_space_tag_t sc_iot; 57 bus_space_handle_t sc_ioh; 58 }; 59 60 void dsrtcattach __P((struct device *parent, struct device *self, void *aux)); 61 int dsrtcmatch __P((struct device *parent, struct cfdata *cf, void *aux)); 62 int ds1687_read __P((struct dsrtc_softc *sc, int addr)); 63 void ds1687_write __P((struct dsrtc_softc *sc, int addr, int data)); 64 int ds1687_ram_read __P((struct dsrtc_softc *sc, int addr)); 65 void ds1687_ram_write __P((struct dsrtc_softc *sc, int addr, int data)); 66 static void ds1687_bank_select __P((struct dsrtc_softc *, int)); 67 static int dsrtc_write __P((void *, rtc_t *)); 68 static int dsrtc_read __P((void *, rtc_t *)); 69 70 int 71 ds1687_read(sc, addr) 72 struct dsrtc_softc *sc; 73 int addr; 74 { 75 76 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr); 77 return(bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG)); 78 } 79 80 void 81 ds1687_write(sc, addr, data) 82 struct dsrtc_softc *sc; 83 int addr; 84 int data; 85 { 86 87 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR_REG, addr); 88 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA_REG, data); 89 } 90 91 static void 92 ds1687_bank_select(sc, bank) 93 struct dsrtc_softc *sc; 94 int bank; 95 { 96 int data; 97 98 data = ds1687_read(sc, RTC_REG_A); 99 data &= ~RTC_REG_A_BANK_MASK; 100 if (bank) 101 data |= RTC_REG_A_BANK1; 102 ds1687_write(sc, RTC_REG_A, data); 103 } 104 105 #if 0 106 /* Nothing uses these yet */ 107 int 108 ds1687_ram_read(sc, addr) 109 struct dsrtc_softc *sc; 110 int addr; 111 { 112 if (addr < RTC_PC_RAM_SIZE) 113 return(ds1687_read(sc, RTC_PC_RAM_START + addr)); 114 115 addr -= RTC_PC_RAM_SIZE; 116 if (addr < RTC_BANK0_RAM_SIZE) 117 return(ds1687_read(sc, RTC_BANK0_RAM_START + addr)); 118 119 addr -= RTC_BANK0_RAM_SIZE; 120 if (addr < RTC_EXT_RAM_SIZE) { 121 int data; 122 123 ds1687_bank_select(sc, 1); 124 ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr); 125 data = ds1687_read(sc, RTC_EXT_RAM_DATA); 126 ds1687_bank_select(sc, 0); 127 return(data); 128 } 129 return(-1); 130 } 131 132 void 133 ds1687_ram_write(sc, addr, val) 134 struct dsrtc_softc *sc; 135 int addr; 136 int val; 137 { 138 if (addr < RTC_PC_RAM_SIZE) 139 return(ds1687_write(sc, RTC_PC_RAM_START + addr, val)); 140 141 addr -= RTC_PC_RAM_SIZE; 142 if (addr < RTC_BANK0_RAM_SIZE) 143 return(ds1687_write(sc, RTC_BANK0_RAM_START + addr, val)); 144 145 addr -= RTC_BANK0_RAM_SIZE; 146 if (addr < RTC_EXT_RAM_SIZE) { 147 ds1687_bank_select(sc, 1); 148 ds1687_write(sc, RTC_EXT_RAM_ADDRESS, addr); 149 ds1687_write(sc, RTC_EXT_RAM_DATA, val); 150 ds1687_bank_select(sc, 0); 151 } 152 } 153 #endif 154 155 static int 156 dsrtc_write(arg, rtc) 157 void *arg; 158 rtc_t *rtc; 159 { 160 struct dsrtc_softc *sc = arg; 161 162 ds1687_write(sc, RTC_SECONDS, rtc->rtc_sec); 163 ds1687_write(sc, RTC_MINUTES, rtc->rtc_min); 164 ds1687_write(sc, RTC_HOURS, rtc->rtc_hour); 165 ds1687_write(sc, RTC_DAYOFMONTH, rtc->rtc_day); 166 ds1687_write(sc, RTC_MONTH, rtc->rtc_mon); 167 ds1687_write(sc, RTC_YEAR, rtc->rtc_year); 168 ds1687_bank_select(sc, 1); 169 ds1687_write(sc, RTC_CENTURY, rtc->rtc_cen); 170 ds1687_bank_select(sc, 0); 171 return(1); 172 } 173 174 static int 175 dsrtc_read(arg, rtc) 176 void *arg; 177 rtc_t *rtc; 178 { 179 struct dsrtc_softc *sc = arg; 180 181 rtc->rtc_micro = 0; 182 rtc->rtc_centi = 0; 183 rtc->rtc_sec = ds1687_read(sc, RTC_SECONDS); 184 rtc->rtc_min = ds1687_read(sc, RTC_MINUTES); 185 rtc->rtc_hour = ds1687_read(sc, RTC_HOURS); 186 rtc->rtc_day = ds1687_read(sc, RTC_DAYOFMONTH); 187 rtc->rtc_mon = ds1687_read(sc, RTC_MONTH); 188 rtc->rtc_year = ds1687_read(sc, RTC_YEAR); 189 ds1687_bank_select(sc, 1); 190 rtc->rtc_cen = ds1687_read(sc, RTC_CENTURY); 191 ds1687_bank_select(sc, 0); 192 193 return(1); 194 } 195 196 /* device and attach structures */ 197 CFATTACH_DECL(dsrtc, sizeof(struct dsrtc_softc), 198 dsrtcmatch, dsrtcattach, NULL, NULL); 199 200 /* 201 * dsrtcmatch() 202 * 203 * Validate the IIC address to make sure its an RTC we understand 204 */ 205 206 int 207 dsrtcmatch(parent, cf, aux) 208 struct device *parent; 209 struct cfdata *cf; 210 void *aux; 211 { 212 struct isa_attach_args *ia = aux; 213 214 if (ia->ia_nio < 1 || 215 ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT) 216 return (0); 217 218 ia->ia_nio = 1; 219 ia->ia_io[0].ir_size = NRTC_PORTS; 220 221 ia->ia_niomem = 0; 222 ia->ia_nirq = 0; 223 ia->ia_ndrq = 0; 224 225 return(1); 226 } 227 228 /* 229 * dsrtcattach() 230 * 231 * Attach the rtc device 232 */ 233 234 void 235 dsrtcattach(parent, self, aux) 236 struct device *parent; 237 struct device *self; 238 void *aux; 239 { 240 struct dsrtc_softc *sc = (struct dsrtc_softc *)self; 241 struct isa_attach_args *ia = aux; 242 struct todclock_attach_args ta; 243 244 sc->sc_iot = ia->ia_iot; 245 if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 246 ia->ia_io[0].ir_size, 0, &sc->sc_ioh)) { 247 printf(": cannot map I/O space\n"); 248 return; 249 } 250 251 ds1687_write(sc, RTC_REG_A, RTC_REG_A_DV1); 252 ds1687_write(sc, RTC_REG_B, RTC_REG_B_BINARY | RTC_REG_B_24_HOUR); 253 254 if (!(ds1687_read(sc, RTC_REG_D) & RTC_REG_D_VRT)) 255 printf(": lithium cell is dead, RTC unreliable"); 256 printf("\n"); 257 258 ta.ta_name = "todclock"; 259 ta.ta_rtc_arg = sc; 260 ta.ta_rtc_write = dsrtc_write; 261 ta.ta_rtc_read = dsrtc_read; 262 ta.ta_flags = 0; 263 config_found(self, &ta, NULL); 264 } 265 266 /* End of dsrtc.c */ 267