1 /* $NetBSD: rtc.c,v 1.17 2009/12/14 00:46:12 matt Exp $ */ 2 3 /* 4 * Copyright 2002 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Simon Burge for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: rtc.c,v 1.17 2009/12/14 00:46:12 matt Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/device.h> 43 #include <sys/kernel.h> 44 #include <sys/systm.h> 45 #include <sys/cpu.h> 46 47 #include <dev/clock_subr.h> 48 49 #include <machine/swarm.h> 50 #include <machine/systemsw.h> 51 52 #include <mips/locore.h> 53 #include <mips/sibyte/dev/sbsmbusvar.h> 54 55 #include <dev/smbus/m41t81reg.h> 56 #include <dev/smbus/x1241reg.h> 57 58 struct rtc_softc { 59 struct device sc_dev; 60 int sc_smbus_chan; 61 int sc_smbus_addr; 62 int sc_type; 63 struct todr_chip_handle sc_ct; 64 }; 65 66 /* "types" for RTCs we support */ 67 #define SMB_1BYTE_ADDR 1 68 #define SMB_2BYTE_ADDR 2 69 70 static int xirtc_match(struct device *, struct cfdata *, void *); 71 static void xirtc_attach(struct device *, struct device *, void *); 72 static int xirtc_gettime(todr_chip_handle_t, struct clock_ymdhms *); 73 static int xirtc_settime(todr_chip_handle_t, struct clock_ymdhms *); 74 75 static int strtc_match(struct device *, struct cfdata *, void *); 76 static void strtc_attach(struct device *, struct device *, void *); 77 static int strtc_gettime(todr_chip_handle_t, struct clock_ymdhms *); 78 static int strtc_settime(todr_chip_handle_t, struct clock_ymdhms *); 79 80 static void rtc_cal_timer(void); 81 82 static void time_smbus_init(int); 83 static int time_waitready(int); 84 static int time_readrtc(int, int, int, int); 85 static int time_writertc(int, int, int, int, int); 86 87 #define WRITERTC(sc, dev, val) \ 88 time_writertc((sc)->sc_smbus_chan, (sc)->sc_smbus_addr, (dev), (sc)->sc_type, (val)) 89 #define READRTC(sc, dev) \ 90 time_readrtc((sc)->sc_smbus_chan, (sc)->sc_smbus_addr, (dev), (sc)->sc_type) 91 92 93 CFATTACH_DECL(xirtc, sizeof(struct rtc_softc), 94 xirtc_match, xirtc_attach, NULL, NULL); 95 96 CFATTACH_DECL(m41t81rtc, sizeof(struct rtc_softc), 97 strtc_match, strtc_attach, NULL, NULL); 98 99 static int rtcfound = 0; 100 struct rtc_softc *the_rtc; 101 102 /* 103 * Xicor X1241 RTC support. 104 */ 105 static int 106 xirtc_match(struct device *parent, struct cfdata *cf, void *aux) 107 { 108 struct smbus_attach_args *sa = aux; 109 int ret; 110 111 time_smbus_init(sa->sa_interface); 112 113 if ((sa->sa_interface != X1241_SMBUS_CHAN) || 114 (sa->sa_device != X1241_RTC_SLAVEADDR)) 115 return (0); 116 117 ret = time_readrtc(sa->sa_interface, sa->sa_device, SMB_2BYTE_ADDR, X1241REG_SC); 118 if (ret < 0) 119 return (0); 120 121 return (!rtcfound); 122 } 123 124 static void 125 xirtc_attach(struct device *parent, struct device *self, void *aux) 126 { 127 struct smbus_attach_args *sa = aux; 128 struct rtc_softc *sc = (void *)self; 129 130 rtcfound = 1; 131 the_rtc = sc; 132 133 sc->sc_smbus_chan = sa->sa_interface; 134 sc->sc_smbus_addr = sa->sa_device; 135 sc->sc_type = SMB_2BYTE_ADDR; /* Two-byte register addresses on the Xicor */ 136 137 138 /* Set up MI todr(9) stuff */ 139 sc->sc_ct.cookie = sc; 140 sc->sc_ct.todr_settime_ymdhms = xirtc_settime; 141 sc->sc_ct.todr_gettime_ymdhms = xirtc_gettime; 142 143 todr_attach(&sc->sc_ct); 144 145 printf("\n"); 146 rtc_cal_timer(); /* XXX */ 147 } 148 149 static int 150 xirtc_settime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) 151 { 152 struct rtc_softc *sc = handle->cookie; 153 uint8_t year, y2k; 154 155 time_smbus_init(sc->sc_smbus_chan); 156 157 /* unlock writes to the CCR */ 158 WRITERTC(sc, X1241REG_SR, X1241REG_SR_WEL); 159 WRITERTC(sc, X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); 160 161 /* set the time */ 162 WRITERTC(sc, X1241REG_HR, TOBCD(ymdhms->dt_hour) | X1241REG_HR_MIL); 163 WRITERTC(sc, X1241REG_MN, TOBCD(ymdhms->dt_min)); 164 WRITERTC(sc, X1241REG_SC, TOBCD(ymdhms->dt_sec)); 165 166 /* set the date */ 167 y2k = (ymdhms->dt_year >= 2000) ? 0x20 : 0x19; 168 year = ymdhms->dt_year % 100; 169 170 WRITERTC(sc, X1241REG_MO, TOBCD(ymdhms->dt_mon)); 171 WRITERTC(sc, X1241REG_DT, TOBCD(ymdhms->dt_day)); 172 WRITERTC(sc, X1241REG_YR, TOBCD(year)); 173 WRITERTC(sc, X1241REG_Y2K, TOBCD(y2k)); 174 175 /* lock writes again */ 176 WRITERTC(sc, X1241REG_SR, 0); 177 178 return (0); 179 } 180 181 static int 182 xirtc_gettime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) 183 { 184 struct rtc_softc *sc = handle->cookie; 185 uint8_t hour, year, y2k; 186 uint8_t status; 187 188 time_smbus_init(sc->sc_smbus_chan); 189 ymdhms->dt_day = FROMBCD(READRTC(sc, X1241REG_DT)); 190 ymdhms->dt_mon = FROMBCD(READRTC(sc, X1241REG_MO)); 191 year = READRTC(sc, X1241REG_YR); 192 y2k = READRTC(sc, X1241REG_Y2K); 193 ymdhms->dt_year = FROMBCD(y2k) * 100 + FROMBCD(year); 194 195 196 ymdhms->dt_sec = FROMBCD(READRTC(sc, X1241REG_SC)); 197 ymdhms->dt_min = FROMBCD(READRTC(sc, X1241REG_MN)); 198 hour = READRTC(sc, X1241REG_HR); 199 ymdhms->dt_hour = FROMBCD(hour & ~X1241REG_HR_MIL); 200 201 status = READRTC(sc, X1241REG_SR); 202 203 if (status & X1241REG_SR_RTCF) { 204 printf("%s: battery has failed, clock setting is not accurate\n", 205 sc->sc_dev.dv_xname); 206 return (EIO); 207 } 208 209 return (0); 210 } 211 212 /* 213 * ST M41T81 RTC support. 214 */ 215 static int 216 strtc_match(struct device *parent, struct cfdata *cf, void *aux) 217 { 218 struct smbus_attach_args *sa = aux; 219 int ret; 220 221 if ((sa->sa_interface != M41T81_SMBUS_CHAN) || 222 (sa->sa_device != M41T81_SLAVEADDR)) 223 return (0); 224 225 time_smbus_init(sa->sa_interface); 226 227 ret = time_readrtc(sa->sa_interface, sa->sa_device, SMB_1BYTE_ADDR, M41T81_SEC); 228 if (ret < 0) 229 return (0); 230 231 return (!rtcfound); 232 } 233 234 static void 235 strtc_attach(struct device *parent, struct device *self, void *aux) 236 { 237 struct smbus_attach_args *sa = aux; 238 struct rtc_softc *sc = (void *)self; 239 240 rtcfound = 1; 241 the_rtc = sc; 242 243 sc->sc_smbus_chan = sa->sa_interface; 244 sc->sc_smbus_addr = sa->sa_device; 245 sc->sc_type = SMB_1BYTE_ADDR; /* One-byte register addresses on the ST */ 246 247 /* Set up MI todr(9) stuff */ 248 sc->sc_ct.cookie = sc; 249 sc->sc_ct.todr_settime_ymdhms = strtc_settime; 250 sc->sc_ct.todr_gettime_ymdhms = strtc_gettime; 251 252 todr_attach(&sc->sc_ct); 253 254 printf("\n"); 255 rtc_cal_timer(); /* XXX */ 256 } 257 258 static int 259 strtc_settime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) 260 { 261 struct rtc_softc *sc = handle->cookie; 262 uint8_t hour; 263 264 time_smbus_init(sc->sc_smbus_chan); 265 266 hour = TOBCD(ymdhms->dt_hour); 267 if (ymdhms->dt_year >= 2000) /* Should be always true! */ 268 hour |= M41T81_HOUR_CB | M41T81_HOUR_CEB; 269 270 /* set the time */ 271 WRITERTC(sc, M41T81_SEC, TOBCD(ymdhms->dt_sec)); 272 WRITERTC(sc, M41T81_MIN, TOBCD(ymdhms->dt_min)); 273 WRITERTC(sc, M41T81_HOUR, hour); 274 275 /* set the date */ 276 WRITERTC(sc, M41T81_DATE, TOBCD(ymdhms->dt_day)); 277 WRITERTC(sc, M41T81_MON, TOBCD(ymdhms->dt_mon)); 278 WRITERTC(sc, M41T81_YEAR, TOBCD(ymdhms->dt_year % 100)); 279 280 return (0); 281 } 282 283 static int 284 strtc_gettime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) 285 { 286 struct rtc_softc *sc = handle->cookie; 287 uint8_t hour; 288 289 time_smbus_init(sc->sc_smbus_chan); 290 291 ymdhms->dt_sec = FROMBCD(READRTC(sc, M41T81_SEC)); 292 ymdhms->dt_min = FROMBCD(READRTC(sc, M41T81_MIN)); 293 hour = READRTC(sc, M41T81_HOUR & M41T81_HOUR_MASK); 294 ymdhms->dt_hour = FROMBCD(hour & M41T81_HOUR_MASK); 295 296 ymdhms->dt_day = FROMBCD(READRTC(sc, M41T81_DATE)); 297 ymdhms->dt_mon = FROMBCD(READRTC(sc, M41T81_MON)); 298 ymdhms->dt_year = 1900 + FROMBCD(READRTC(sc, M41T81_YEAR)); 299 if (hour & M41T81_HOUR_CB) 300 ymdhms->dt_year += 100; 301 302 return (0); 303 } 304 305 #define NITERS 3 306 #define RTC_SECONDS(rtc) FROMBCD(READRTC((rtc), X1241REG_SC)) 307 308 /* 309 * Since it takes so long to read the complete time/date values from 310 * the RTC over the SMBus, we only read the seconds value. 311 * Later versions of the SWARM will hopefully have the RTC interrupt 312 * attached so we can do the clock calibration much more quickly and 313 * with a higher resolution. 314 */ 315 static void 316 rtc_cal_timer(void) 317 { 318 uint32_t ctrdiff[NITERS], startctr, endctr; 319 int sec, lastsec, i; 320 321 if (rtcfound == 0) { 322 printf("rtc_cal_timer before rtc attached\n"); 323 return; 324 } 325 return; /* XXX XXX */ 326 327 printf("%s: calibrating CPU clock", the_rtc->sc_dev.dv_xname); 328 329 /* 330 * Run the loop an extra time to wait for the second to tick over 331 * and to prime the cache. 332 */ 333 time_smbus_init(the_rtc->sc_smbus_chan); 334 sec = RTC_SECONDS(the_rtc); 335 endctr = mips3_cp0_count_read(); 336 337 for (i = 0; i < NITERS; i++) { 338 int diff; 339 340 again: 341 lastsec = sec; 342 startctr = endctr; 343 344 /* Wait for the timer to tick over. */ 345 do { 346 // time_smbus_init(the_rtc->sc_smbus_chan); 347 sec = RTC_SECONDS(the_rtc); 348 } while (lastsec == sec); 349 endctr = mips3_cp0_count_read(); 350 351 diff = sec - lastsec; 352 if (diff < 0) 353 diff += 60; 354 355 /* Sometimes we appear to skip a second. Clock jitter? */ 356 if (diff > 1) 357 goto again; 358 359 if (endctr < startctr) 360 ctrdiff[i] = 0xffffffff - startctr + endctr; 361 else 362 ctrdiff[i] = endctr - startctr; 363 } 364 printf("\n"); 365 366 /* Compute the number of cycles per second. */ 367 curcpu()->ci_cpu_freq = ((ctrdiff[1] + ctrdiff[2]) / 2); 368 369 /* Compute the delay divisor. */ 370 curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / 1000000; 371 372 /* Compute clock cycles per hz */ 373 curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / hz; 374 375 printf("%s: timer calibration: %lu cycles/sec [(%u, %u)]\n", 376 the_rtc->sc_dev.dv_xname, curcpu()->ci_cpu_freq, 377 ctrdiff[1], ctrdiff[2]); 378 } 379 #undef RTC_SECONDS 380 381 /* XXX eville direct-access-to-the-device code follows... */ 382 383 /* 384 * Copyright 2000,2001 385 * Broadcom Corporation. All rights reserved. 386 * 387 * This software is furnished under license and may be used and copied only 388 * in accordance with the following terms and conditions. Subject to these 389 * conditions, you may download, copy, install, use, modify and distribute 390 * modified or unmodified copies of this software in source and/or binary 391 * form. No title or ownership is transferred hereby. 392 * 393 * 1) Any source code used, modified or distributed must reproduce and 394 * retain this copyright notice and list of conditions as they appear in 395 * the source file. 396 * 397 * 2) No right is granted to use any trade name, trademark, or logo of 398 * Broadcom Corporation. The "Broadcom Corporation" name may not be 399 * used to endorse or promote products derived from this software 400 * without the prior written permission of Broadcom Corporation. 401 * 402 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 403 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 404 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 405 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 406 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 407 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 408 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 409 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 410 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 411 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 412 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 413 */ 414 415 #include <mips/sibyte/include/sb1250_regs.h> 416 #include <mips/sibyte/include/sb1250_smbus.h> 417 418 #define READ_REG(rp) (mips3_ld((volatile uint64_t *)(MIPS_PHYS_TO_KSEG1(rp)))) 419 #define WRITE_REG(rp, val) (mips3_sd((volatile uint64_t *)(MIPS_PHYS_TO_KSEG1(rp)), (val))) 420 421 static void 422 time_smbus_init(int chan) 423 { 424 uint32_t reg; 425 426 reg = A_SMB_REGISTER(chan, R_SMB_FREQ); 427 WRITE_REG(reg, K_SMB_FREQ_100KHZ); 428 reg = A_SMB_REGISTER(chan, R_SMB_CONTROL); 429 WRITE_REG(reg, 0); /* not in direct mode, no interrupts, will poll */ 430 } 431 432 static int 433 time_waitready(int chan) 434 { 435 uint32_t reg; 436 uint64_t status; 437 438 reg = A_SMB_REGISTER(chan, R_SMB_STATUS); 439 440 for (;;) { 441 status = READ_REG(reg); 442 if (status & M_SMB_BUSY) 443 continue; 444 break; 445 } 446 447 if (status & M_SMB_ERROR) { 448 WRITE_REG(reg, (status & M_SMB_ERROR)); 449 return (-1); 450 } 451 return (0); 452 } 453 454 static int 455 time_readrtc(int chan, int slaveaddr, int devaddr, int type) 456 { 457 uint32_t reg; 458 int err; 459 460 /* 461 * Make sure the bus is idle (probably should 462 * ignore error here) 463 */ 464 465 if (time_waitready(chan) < 0) 466 return (-1); 467 468 if (type == SMB_2BYTE_ADDR) { 469 /* 470 * Write the device address to the controller. There are two 471 * parts, the high part goes in the "CMD" field, and the 472 * low part is the data field. 473 */ 474 475 reg = A_SMB_REGISTER(chan, R_SMB_CMD); 476 WRITE_REG(reg, (devaddr >> 8) & 0x7); 477 478 /* 479 * Write the data to the controller 480 */ 481 482 reg = A_SMB_REGISTER(chan, R_SMB_DATA); 483 WRITE_REG(reg, (devaddr & 0xff) & 0xff); 484 } else { /* SMB_1BYTE_ADDR */ 485 /* 486 * Write the device address to the controller. 487 */ 488 489 reg = A_SMB_REGISTER(chan, R_SMB_CMD); 490 WRITE_REG(reg, devaddr & 0xff); 491 } 492 493 /* 494 * Start the command 495 */ 496 497 reg = A_SMB_REGISTER(chan, R_SMB_START); 498 if (type == SMB_2BYTE_ADDR) 499 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR2BYTE) | V_SMB_ADDR(slaveaddr)); 500 else /* SMB_1BYTE_ADDR */ 501 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR1BYTE) | V_SMB_ADDR(slaveaddr)); 502 503 /* 504 * Wait till done 505 */ 506 507 err = time_waitready(chan); 508 if (err < 0) 509 return (err); 510 511 /* 512 * Read the data byte 513 */ 514 515 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_RD1BYTE) | V_SMB_ADDR(slaveaddr)); 516 517 err = time_waitready(chan); 518 if (err < 0) 519 return (err); 520 521 reg = A_SMB_REGISTER(chan, R_SMB_DATA); 522 err = READ_REG(reg); 523 524 return (err & 0xff); 525 } 526 527 static int 528 time_writertc(int chan, int slaveaddr, int devaddr, int type, int b) 529 { 530 uint32_t reg; 531 int err, timer; 532 533 /* 534 * Make sure the bus is idle (probably should 535 * ignore error here) 536 */ 537 538 if (time_waitready(chan) < 0) 539 return (-1); 540 541 /* 542 * Write the device address to the controller. There are two 543 * parts, the high part goes in the "CMD" field, and the 544 * low part is the data field. 545 */ 546 547 reg = A_SMB_REGISTER(chan, R_SMB_CMD); 548 if (type == SMB_2BYTE_ADDR) 549 WRITE_REG(reg, (devaddr >> 8) & 0x7); 550 else /* SMB_1BYTE_ADDR */ 551 WRITE_REG(reg, devaddr & 0xff); 552 553 /* 554 * Write the data to the controller 555 */ 556 557 reg = A_SMB_REGISTER(chan, R_SMB_DATA); 558 if (type == SMB_2BYTE_ADDR) 559 WRITE_REG(reg, (devaddr & 0xff) | ((b & 0xff) << 8)); 560 else /* SMB_1BYTE_ADDR */ 561 WRITE_REG(reg, b & 0xff); 562 563 /* 564 * Start the command. Keep pounding on the device until it 565 * submits or the timer expires, whichever comes first. The 566 * datasheet says writes can take up to 10ms, so we'll give it 500. 567 */ 568 569 reg = A_SMB_REGISTER(chan, R_SMB_START); 570 if (type == SMB_2BYTE_ADDR) 571 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR3BYTE) | V_SMB_ADDR(slaveaddr)); 572 else /* SMB_1BYTE_ADDR */ 573 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR2BYTE) | V_SMB_ADDR(slaveaddr)); 574 575 /* 576 * Wait till the SMBus interface is done 577 */ 578 579 err = time_waitready(chan); 580 if (err < 0) 581 return (err); 582 583 /* 584 * Pound on the device with a current address read 585 * to poll for the write complete 586 */ 587 588 err = -1; 589 timer = 100000000; /* XXX */ 590 591 while (timer-- > 0) { 592 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_RD1BYTE) | V_SMB_ADDR(slaveaddr)); 593 594 err = time_waitready(chan); 595 if (err == 0) 596 break; 597 } 598 599 return (err); 600 } 601