1/* $OpenBSD: rtc.c,v 1.13 2022/10/12 13:39:50 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 93extern todr_chip_handle_t todr_handle; 94 95struct 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 102int rtc_match(struct device *, void *, void *); 103void rtc_attach(struct device *, struct device *, void *); 104 105const struct cfattach rtc_ca = { 106 sizeof(struct rtc_softc), rtc_match, rtc_attach 107}; 108 109struct cfdriver rtc_cd = { 110 NULL, "rtc", DV_DULL 111}; 112 113int rtc_intr(void *arg); 114 115u_int8_t rtc_read_reg(struct rtc_softc *, bus_size_t); 116void rtc_write_reg(struct rtc_softc *sc, bus_size_t, u_int8_t); 117 118int rtc_gettime(todr_chip_handle_t, struct timeval *); 119int rtc_settime(todr_chip_handle_t, struct timeval *); 120int rtc_bq4802_gettime(todr_chip_handle_t, struct timeval *); 121int rtc_bq4802_settime(todr_chip_handle_t, struct timeval *); 122 123int 124rtc_match(struct device *parent, void *cf, void *aux) 125{ 126 struct ebus_attach_args *ea = aux; 127 128 if (strcmp("rtc", ea->ea_name) == 0) 129 return (1); 130 return (0); 131} 132 133void 134rtc_attach(struct device *parent, struct device *self, void *aux) 135{ 136 struct rtc_softc *sc = (void *)self; 137 struct ebus_attach_args *ea = aux; 138 todr_chip_handle_t handle; 139 char *model; 140 u_int8_t csr; 141 142 if (ebus_bus_map(ea->ea_iotag, 0, 143 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), 144 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { 145 sc->sc_iot = ea->ea_iotag; 146 } else if (ebus_bus_map(ea->ea_memtag, 0, 147 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), 148 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { 149 sc->sc_iot = ea->ea_memtag; 150 } else { 151 printf("%s: can't map register\n", self->dv_xname); 152 return; 153 } 154 155 model = getpropstring(ea->ea_node, "model"); 156 if (*model == '\0') 157 model = getpropstring(ea->ea_node, "compatible"); 158 printf(": %s\n", *model != '\0' ? model : "unknown"); 159 160 /* Setup our todr_handle */ 161 handle = malloc(sizeof(struct todr_chip_handle), M_DEVBUF, M_NOWAIT); 162 if (handle == NULL) 163 panic("couldn't allocate todr_handle"); 164 handle->cookie = sc; 165 handle->todr_gettime = rtc_gettime; 166 handle->todr_settime = rtc_settime; 167 handle->bus_cookie = NULL; 168 handle->todr_setwen = NULL; 169 handle->todr_quality = 0; 170 todr_handle = handle; 171 172 /* The bq4802 is not compatible with the mc146818. */ 173 if (strcmp(model, "bq4802") == 0) { 174 handle->todr_gettime = rtc_bq4802_gettime; 175 handle->todr_settime = rtc_bq4802_settime; 176 177 /* Turn on 24-hour mode. */ 178 csr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, BQ4802_CTRL); 179 csr |= BQ4802_24HR; 180 bus_space_write_1(sc->sc_iot, sc->sc_ioh, BQ4802_CTRL, csr); 181 return; 182 } 183 184 /* 185 * Turn interrupts off, just in case. (Although they shouldn't 186 * be wired to an interrupt controller on sparcs). 187 */ 188 rtc_write_reg(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR); 189 190 /* 191 * On ds1287 models (which really are ns87317 chips), the 192 * interrupt is wired to the powerbutton. 193 */ 194 if (strcmp(model, "ds1287") == 0 && ea->ea_nintrs > 0) { 195 sc->sc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0], 196 IPL_BIO, 0, rtc_intr, sc, self->dv_xname); 197 if (sc->sc_ih == NULL) { 198 printf("%s: can't establish interrupt\n", 199 self->dv_xname); 200 } 201 } 202} 203 204int 205rtc_intr(void *arg) 206{ 207 extern int allowpowerdown; 208 209 if (allowpowerdown == 1) { 210 allowpowerdown = 0; 211 prsignal(initprocess, SIGUSR2); 212 } 213 return (1); 214} 215 216/* 217 * Register access is indirect, through an address and data port. 218 */ 219 220#define RTC_ADDR 0 221#define RTC_DATA 1 222 223u_int8_t 224rtc_read_reg(struct rtc_softc *sc, bus_size_t reg) 225{ 226 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR, reg); 227 return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA)); 228} 229 230void 231rtc_write_reg(struct rtc_softc *sc, bus_size_t reg, u_int8_t val) 232{ 233 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR, reg); 234 bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA, val); 235} 236 237/* 238 * RTC todr routines. 239 */ 240 241/* 242 * Get time-of-day and convert to a `struct timeval' 243 * Return 0 on success; an error number otherwise. 244 */ 245int 246rtc_gettime(todr_chip_handle_t handle, struct timeval *tv) 247{ 248 struct rtc_softc *sc = handle->cookie; 249 struct clock_ymdhms dt; 250 int year; 251 u_int8_t csr; 252 253 /* Stop updates. */ 254 csr = rtc_read_reg(sc, MC_REGB); 255 csr |= MC_REGB_SET; 256 rtc_write_reg(sc, MC_REGB, csr); 257 258 /* Read time */ 259 dt.dt_sec = rtc_read_reg(sc, MC_SEC); 260 dt.dt_min = rtc_read_reg(sc, MC_MIN); 261 dt.dt_hour = rtc_read_reg(sc, MC_HOUR); 262 dt.dt_day = rtc_read_reg(sc, MC_DOM); 263 dt.dt_wday = rtc_read_reg(sc, MC_DOW); 264 dt.dt_mon = rtc_read_reg(sc, MC_MONTH); 265 year = rtc_read_reg(sc, MC_YEAR); 266 267 if ((year += 1900) < POSIX_BASE_YEAR) 268 year += 100; 269 270 dt.dt_year = year; 271 272 /* time wears on */ 273 csr = rtc_read_reg(sc, MC_REGB); 274 csr &= ~MC_REGB_SET; 275 rtc_write_reg(sc, MC_REGB, csr); 276 277 /* simple sanity checks */ 278 if (dt.dt_mon > 12 || dt.dt_day > 31 || 279 dt.dt_hour >= 24 || dt.dt_min >= 60 || dt.dt_sec >= 60) 280 return (1); 281 282 tv->tv_sec = clock_ymdhms_to_secs(&dt); 283 tv->tv_usec = 0; 284 return (0); 285} 286 287/* 288 * Set the time-of-day clock based on the value of the `struct timeval' arg. 289 * Return 0 on success; an error number otherwise. 290 */ 291int 292rtc_settime(todr_chip_handle_t handle, struct timeval *tv) 293{ 294 struct rtc_softc *sc = handle->cookie; 295 struct clock_ymdhms dt; 296 u_int8_t csr; 297 int year; 298 299 /* Note: we ignore `tv_usec' */ 300 clock_secs_to_ymdhms(tv->tv_sec, &dt); 301 302 year = dt.dt_year % 100; 303 304 /* enable write */ 305 csr = rtc_read_reg(sc, MC_REGB); 306 csr |= MC_REGB_SET; 307 rtc_write_reg(sc, MC_REGB, csr); 308 309 rtc_write_reg(sc, MC_SEC, dt.dt_sec); 310 rtc_write_reg(sc, MC_MIN, dt.dt_min); 311 rtc_write_reg(sc, MC_HOUR, dt.dt_hour); 312 rtc_write_reg(sc, MC_DOW, dt.dt_wday); 313 rtc_write_reg(sc, MC_DOM, dt.dt_day); 314 rtc_write_reg(sc, MC_MONTH, dt.dt_mon); 315 rtc_write_reg(sc, MC_YEAR, year); 316 317 /* load them up */ 318 csr = rtc_read_reg(sc, MC_REGB); 319 csr &= ~MC_REGB_SET; 320 rtc_write_reg(sc, MC_REGB, csr); 321 return (0); 322} 323 324/* 325 * Get time-of-day and convert to a `struct timeval' 326 * Return 0 on success; an error number otherwise. 327 */ 328int 329rtc_bq4802_gettime(todr_chip_handle_t handle, struct timeval *tv) 330{ 331 struct rtc_softc *sc = handle->cookie; 332 struct clock_ymdhms dt; 333 bus_space_tag_t iot = sc->sc_iot; 334 bus_space_handle_t ioh = sc->sc_ioh; 335 u_int8_t csr; 336 337 /* Stop updates. */ 338 csr = bus_space_read_1(iot, ioh, BQ4802_CTRL); 339 csr |= BQ4802_UTI; 340 bus_space_write_1(iot, ioh, BQ4802_CTRL, csr); 341 342 /* Read time */ 343 dt.dt_sec = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_SEC)); 344 dt.dt_min = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_MIN)); 345 dt.dt_hour = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_HOUR)); 346 dt.dt_day = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_DAY)); 347 dt.dt_wday = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_DOW)); 348 dt.dt_mon = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_MONTH)); 349 dt.dt_year = FROMBCD(bus_space_read_1(iot, ioh, BQ4802_YEAR)) + 350 FROMBCD(bus_space_read_1(iot, ioh, BQ4802_CENTURY)) * 100; 351 352 /* time wears on */ 353 csr = bus_space_read_1(iot, ioh, BQ4802_CTRL); 354 csr &= ~BQ4802_UTI; 355 bus_space_write_1(iot, ioh, BQ4802_CTRL, csr); 356 357 /* simple sanity checks */ 358 if (dt.dt_mon > 12 || dt.dt_day > 31 || 359 dt.dt_hour >= 24 || dt.dt_min >= 60 || dt.dt_sec >= 60) 360 return (1); 361 362 tv->tv_sec = clock_ymdhms_to_secs(&dt); 363 tv->tv_usec = 0; 364 return (0); 365} 366 367/* 368 * Set the time-of-day clock based on the value of the `struct timeval' arg. 369 * Return 0 on success; an error number otherwise. 370 */ 371int 372rtc_bq4802_settime(todr_chip_handle_t handle, struct timeval *tv) 373{ 374 struct rtc_softc *sc = handle->cookie; 375 struct clock_ymdhms dt; 376 bus_space_tag_t iot = sc->sc_iot; 377 bus_space_handle_t ioh = sc->sc_ioh; 378 u_int8_t csr; 379 380 /* Note: we ignore `tv_usec' */ 381 clock_secs_to_ymdhms(tv->tv_sec, &dt); 382 383 /* enable write */ 384 csr = bus_space_read_1(iot, ioh, BQ4802_CTRL); 385 csr |= BQ4802_UTI; 386 bus_space_write_1(iot, ioh, BQ4802_CTRL, csr); 387 388 bus_space_write_1(iot, ioh, BQ4802_SEC, TOBCD(dt.dt_sec)); 389 bus_space_write_1(iot, ioh, BQ4802_MIN, TOBCD(dt.dt_min)); 390 bus_space_write_1(iot, ioh, BQ4802_HOUR, TOBCD(dt.dt_hour)); 391 bus_space_write_1(iot, ioh, BQ4802_DOW, TOBCD(dt.dt_wday)); 392 bus_space_write_1(iot, ioh, BQ4802_DAY, TOBCD(dt.dt_day)); 393 bus_space_write_1(iot, ioh, BQ4802_MONTH, TOBCD(dt.dt_mon)); 394 bus_space_write_1(iot, ioh, BQ4802_YEAR, TOBCD(dt.dt_year % 100)); 395 bus_space_write_1(iot, ioh, BQ4802_CENTURY, TOBCD(dt.dt_year / 100)); 396 397 /* load them up */ 398 csr = bus_space_read_1(iot, ioh, BQ4802_CTRL); 399 csr &= ~BQ4802_UTI; 400 bus_space_write_1(iot, ioh, BQ4802_CTRL, csr); 401 return (0); 402} 403