1 /* $OpenBSD: rtc.c,v 1.7 2009/01/07 13:01:39 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Copyright (c) 1994 Gordon W. Ross 7 * Copyright (c) 1993 Adam Glass 8 * Copyright (c) 1996 Paul Kranenburg 9 * Copyright (c) 1996 10 * The President and Fellows of Harvard College. All rights reserved. 11 * 12 * This software was developed by the Computer Systems Engineering group 13 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 14 * contributed to Berkeley. 15 * 16 * All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Harvard University. 19 * This product includes software developed by the University of 20 * California, Lawrence Berkeley Laboratory. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * This product includes software developed by the University of 34 * California, Berkeley and its contributors. 35 * This product includes software developed by Paul Kranenburg. 36 * This product includes software developed by Harvard University. 37 * 4. Neither the name of the University nor the names of its contributors 38 * may be used to endorse or promote products derived from this software 39 * without specific prior written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 */ 54 55 /* 56 * Driver for rtc device on Blade 1000, Fire V210, etc. 57 */ 58 59 #include <sys/param.h> 60 #include <sys/kernel.h> 61 #include <sys/device.h> 62 #include <sys/malloc.h> 63 #include <sys/proc.h> 64 #include <sys/signalvar.h> 65 #include <sys/systm.h> 66 67 #include <machine/bus.h> 68 #include <machine/autoconf.h> 69 70 #include <dev/clock_subr.h> 71 #include <dev/ic/mc146818reg.h> 72 73 #include <sparc64/dev/ebusreg.h> 74 #include <sparc64/dev/ebusvar.h> 75 76 /* 77 * Register definitions for the Texas Instruments bq4802. 78 */ 79 80 #define BQ4802_SEC 0x00 /* Seconds. */ 81 #define BQ4802_MIN 0x02 /* Minutes. */ 82 #define BQ4802_HOUR 0x04 /* Hours. */ 83 #define BQ4802_DAY 0x06 /* Day (01-31). */ 84 #define BQ4802_DOW 0x08 /* Day of week (01-07). */ 85 #define BQ4802_MONTH 0x09 /* Month (01-12). */ 86 #define BQ4802_YEAR 0x0a /* Year (00-99). */ 87 #define BQ4802_CENTURY 0x0f /* Century (00-99). */ 88 89 #define BQ4802_CTRL 0x0e /* Control. */ 90 #define BQ4802_24HR 0x02 /* 24-hour mode. */ 91 #define BQ4802_UTI 0x08 /* Update transfer inhibit. */ 92 93 extern todr_chip_handle_t todr_handle; 94 95 struct rtc_softc { 96 struct device sc_dv; 97 bus_space_tag_t sc_iot; 98 bus_space_handle_t sc_ioh; 99 struct intrhand *sc_ih; 100 }; 101 102 int rtc_match(struct device *, void *, void *); 103 void rtc_attach(struct device *, struct device *, void *); 104 105 struct cfattach rtc_ca = { 106 sizeof(struct rtc_softc), rtc_match, rtc_attach 107 }; 108 109 struct cfdriver rtc_cd = { 110 NULL, "rtc", DV_DULL 111 }; 112 113 int rtc_intr(void *arg); 114 115 u_int8_t rtc_read_reg(struct rtc_softc *, bus_size_t); 116 void rtc_write_reg(struct rtc_softc *sc, bus_size_t, u_int8_t); 117 118 int rtc_gettime(todr_chip_handle_t, struct timeval *); 119 int rtc_settime(todr_chip_handle_t, struct timeval *); 120 int rtc_bq4802_gettime(todr_chip_handle_t, struct timeval *); 121 int rtc_bq4802_settime(todr_chip_handle_t, struct timeval *); 122 int rtc_getcal(todr_chip_handle_t, int *); 123 int rtc_setcal(todr_chip_handle_t, int); 124 125 int 126 rtc_match(struct device *parent, void *cf, void *aux) 127 { 128 struct ebus_attach_args *ea = aux; 129 130 if (strcmp("rtc", ea->ea_name) == 0) 131 return (1); 132 return (0); 133 } 134 135 void 136 rtc_attach(struct device *parent, struct device *self, void *aux) 137 { 138 struct rtc_softc *sc = (void *)self; 139 struct ebus_attach_args *ea = aux; 140 todr_chip_handle_t handle; 141 char *model; 142 u_int8_t csr; 143 144 if (ebus_bus_map(ea->ea_iotag, 0, 145 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), 146 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { 147 sc->sc_iot = ea->ea_iotag; 148 } else if (ebus_bus_map(ea->ea_memtag, 0, 149 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), 150 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { 151 sc->sc_iot = ea->ea_memtag; 152 } else { 153 printf("%s: can't map register\n", self->dv_xname); 154 return; 155 } 156 157 model = getpropstring(ea->ea_node, "model"); 158 if (*model == '\0') 159 model = getpropstring(ea->ea_node, "compatible"); 160 printf(": %s\n", *model != '\0' != 0 ? model : "unknown"); 161 162 /* Setup our todr_handle */ 163 handle = malloc(sizeof(struct todr_chip_handle), M_DEVBUF, M_NOWAIT); 164 if (handle == NULL) 165 panic("couldn't allocate todr_handle"); 166 handle->cookie = sc; 167 handle->todr_gettime = rtc_gettime; 168 handle->todr_settime = rtc_settime; 169 handle->todr_getcal = rtc_getcal; 170 handle->todr_setcal = rtc_setcal; 171 172 handle->bus_cookie = NULL; 173 handle->todr_setwen = NULL; 174 todr_handle = handle; 175 176 /* The bq4802 is not compatible with the mc146818. */ 177 if (strcmp(model, "bq4802") == 0) { 178 handle->todr_gettime = rtc_bq4802_gettime; 179 handle->todr_settime = rtc_bq4802_settime; 180 181 /* Turn on 24-hour mode. */ 182 csr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, BQ4802_CTRL); 183 csr |= BQ4802_24HR; 184 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BQ4802_CTRL, csr); 185 return; 186 } 187 188 /* 189 * Turn interrupts off, just in case. (Although they shouldn't 190 * be wired to an interrupt controller on sparcs). 191 */ 192 rtc_write_reg(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR); 193 194 /* 195 * On ds1287 models (which really are ns87317 chips), the 196 * interrupt is wired to the powerbutton. 197 */ 198 if (strcmp(model, "ds1287") == 0 && ea->ea_nintrs > 0) { 199 sc->sc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0], 200 IPL_BIO, 0, rtc_intr, sc, self->dv_xname); 201 if (sc->sc_ih == NULL) { 202 printf("%s: can't establish interrupt\n", 203 self->dv_xname); 204 } 205 } 206 } 207 208 int 209 rtc_intr(void *arg) 210 { 211 extern int kbd_reset; 212 213 if (kbd_reset == 1) { 214 kbd_reset = 0; 215 psignal(initproc, SIGUSR2); 216 } 217 return (1); 218 } 219 220 /* 221 * Register access is indirect, through an address and data port. 222 */ 223 224 #define RTC_ADDR 0 225 #define RTC_DATA 1 226 227 u_int8_t 228 rtc_read_reg(struct rtc_softc *sc, bus_size_t reg) 229 { 230 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR, reg); 231 return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA)); 232 } 233 234 void 235 rtc_write_reg(struct rtc_softc *sc, bus_size_t reg, u_int8_t val) 236 { 237 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR, reg); 238 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA, val); 239 } 240 241 /* 242 * RTC todr routines. 243 */ 244 245 /* 246 * Get time-of-day and convert to a `struct timeval' 247 * Return 0 on success; an error number otherwise. 248 */ 249 int 250 rtc_gettime(todr_chip_handle_t handle, struct timeval *tv) 251 { 252 struct rtc_softc *sc = handle->cookie; 253 struct clock_ymdhms dt; 254 int year; 255 u_int8_t csr; 256 257 /* Stop updates. */ 258 csr = rtc_read_reg(sc, MC_REGB); 259 csr |= MC_REGB_SET; 260 rtc_write_reg(sc, MC_REGB, csr); 261 262 /* Read time */ 263 dt.dt_sec = rtc_read_reg(sc, MC_SEC); 264 dt.dt_min = rtc_read_reg(sc, MC_MIN); 265 dt.dt_hour = rtc_read_reg(sc, MC_HOUR); 266 dt.dt_day = rtc_read_reg(sc, MC_DOM); 267 dt.dt_wday = rtc_read_reg(sc, MC_DOW); 268 dt.dt_mon = rtc_read_reg(sc, MC_MONTH); 269 year = rtc_read_reg(sc, MC_YEAR); 270 271 if ((year += 1900) < POSIX_BASE_YEAR) 272 year += 100; 273 274 dt.dt_year = year; 275 276 /* time wears on */ 277 csr = rtc_read_reg(sc, MC_REGB); 278 csr &= ~MC_REGB_SET; 279 rtc_write_reg(sc, MC_REGB, csr); 280 281 /* simple sanity checks */ 282 if (dt.dt_mon > 12 || dt.dt_day > 31 || 283 dt.dt_hour >= 24 || dt.dt_min >= 60 || dt.dt_sec >= 60) 284 return (1); 285 286 tv->tv_sec = clock_ymdhms_to_secs(&dt); 287 tv->tv_usec = 0; 288 return (0); 289 } 290 291 /* 292 * Set the time-of-day clock based on the value of the `struct timeval' arg. 293 * Return 0 on success; an error number otherwise. 294 */ 295 int 296 rtc_settime(todr_chip_handle_t handle, struct timeval *tv) 297 { 298 struct rtc_softc *sc = handle->cookie; 299 struct clock_ymdhms dt; 300 u_int8_t csr; 301 int year; 302 303 /* Note: we ignore `tv_usec' */ 304 clock_secs_to_ymdhms(tv->tv_sec, &dt); 305 306 year = dt.dt_year % 100; 307 308 /* enable write */ 309 csr = rtc_read_reg(sc, MC_REGB); 310 csr |= MC_REGB_SET; 311 rtc_write_reg(sc, MC_REGB, csr); 312 313 rtc_write_reg(sc, MC_SEC, dt.dt_sec); 314 rtc_write_reg(sc, MC_MIN, dt.dt_min); 315 rtc_write_reg(sc, MC_HOUR, dt.dt_hour); 316 rtc_write_reg(sc, MC_DOW, dt.dt_wday); 317 rtc_write_reg(sc, MC_DOM, dt.dt_day); 318 rtc_write_reg(sc, MC_MONTH, dt.dt_mon); 319 rtc_write_reg(sc, MC_YEAR, year); 320 321 /* load them up */ 322 csr = rtc_read_reg(sc, MC_REGB); 323 csr &= ~MC_REGB_SET; 324 rtc_write_reg(sc, MC_REGB, csr); 325 return (0); 326 } 327 328 /* 329 * Get time-of-day and convert to a `struct timeval' 330 * Return 0 on success; an error number otherwise. 331 */ 332 int 333 rtc_bq4802_gettime(todr_chip_handle_t handle, struct timeval *tv) 334 { 335 struct rtc_softc *sc = handle->cookie; 336 struct clock_ymdhms dt; 337 bus_space_tag_t iot = sc->sc_iot; 338 bus_space_handle_t ioh = sc->sc_ioh; 339 u_int8_t csr; 340 341 /* Stop updates. */ 342 csr = bus_space_read_1(iot, ioh, BQ4802_CTRL); 343 csr |= BQ4802_UTI; 344 bus_space_write_1(iot, ioh, BQ4802_CTRL, csr); 345 346 /* Read time */ 347 dt.dt_sec = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_SEC)); 348 dt.dt_min = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_MIN)); 349 dt.dt_hour = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_HOUR)); 350 dt.dt_day = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_DAY)); 351 dt.dt_wday = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_DOW)); 352 dt.dt_mon = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_MONTH)); 353 dt.dt_year = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_YEAR)) + 354 FROMBCD(bus_space_read_1(iot, ioh, BQ4802_CENTURY)) * 100; 355 356 /* time wears on */ 357 csr = bus_space_read_1(iot, ioh, BQ4802_CTRL); 358 csr &= ~BQ4802_UTI; 359 bus_space_write_1(iot, ioh, BQ4802_CTRL, csr); 360 361 /* simple sanity checks */ 362 if (dt.dt_mon > 12 || dt.dt_day > 31 || 363 dt.dt_hour >= 24 || dt.dt_min >= 60 || dt.dt_sec >= 60) 364 return (1); 365 366 tv->tv_sec = clock_ymdhms_to_secs(&dt); 367 tv->tv_usec = 0; 368 return (0); 369 } 370 371 /* 372 * Set the time-of-day clock based on the value of the `struct timeval' arg. 373 * Return 0 on success; an error number otherwise. 374 */ 375 int 376 rtc_bq4802_settime(todr_chip_handle_t handle, struct timeval *tv) 377 { 378 struct rtc_softc *sc = handle->cookie; 379 struct clock_ymdhms dt; 380 bus_space_tag_t iot = sc->sc_iot; 381 bus_space_handle_t ioh = sc->sc_ioh; 382 u_int8_t csr; 383 384 /* Note: we ignore `tv_usec' */ 385 clock_secs_to_ymdhms(tv->tv_sec, &dt); 386 387 /* enable write */ 388 csr = bus_space_read_1(iot, ioh, BQ4802_CTRL); 389 csr |= BQ4802_UTI; 390 bus_space_write_1(iot, ioh, BQ4802_CTRL, csr); 391 392 bus_space_write_1(iot, ioh, BQ4802_SEC, TOBCD(dt.dt_sec)); 393 bus_space_write_1(iot, ioh, BQ4802_MIN, TOBCD(dt.dt_min)); 394 bus_space_write_1(iot, ioh, BQ4802_HOUR, TOBCD(dt.dt_hour)); 395 bus_space_write_1(iot, ioh, BQ4802_DOW, TOBCD(dt.dt_wday)); 396 bus_space_write_1(iot, ioh, BQ4802_DAY, TOBCD(dt.dt_day)); 397 bus_space_write_1(iot, ioh, BQ4802_MONTH, TOBCD(dt.dt_mon)); 398 bus_space_write_1(iot, ioh, BQ4802_YEAR, TOBCD(dt.dt_year % 100)); 399 bus_space_write_1(iot, ioh, BQ4802_CENTURY, TOBCD(dt.dt_year / 100)); 400 401 /* load them up */ 402 csr = bus_space_read_1(iot, ioh, BQ4802_CTRL); 403 csr &= ~BQ4802_UTI; 404 bus_space_write_1(iot, ioh, BQ4802_CTRL, csr); 405 return (0); 406 } 407 408 int 409 rtc_getcal(todr_chip_handle_t handle, int *vp) 410 { 411 return (EOPNOTSUPP); 412 } 413 414 int 415 rtc_setcal(todr_chip_handle_t handle, int v) 416 { 417 return (EOPNOTSUPP); 418 } 419