1 /* $NetBSD: rtc.c,v 1.5 2002/11/12 01:22:27 simonb 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/param.h> 39 #include <sys/device.h> 40 #include <sys/kernel.h> 41 #include <sys/systm.h> 42 43 #include <dev/clock_subr.h> 44 45 #include <machine/swarm.h> 46 #include <machine/systemsw.h> 47 48 #include <mips/locore.h> 49 #include <mips/sibyte/dev/sbsmbusvar.h> 50 51 #include <dev/smbus/m41t81reg.h> 52 #include <dev/smbus/x1241reg.h> 53 54 struct rtc_softc { 55 struct device sc_dev; 56 int sc_smbus_chan; 57 int sc_smbus_addr; 58 int sc_type; 59 struct todr_chip_handle sc_ct; 60 }; 61 62 /* "types" for RTCs we support */ 63 #define SMB_1BYTE_ADDR 1 64 #define SMB_2BYTE_ADDR 2 65 66 static int xirtc_match(struct device *, struct cfdata *, void *); 67 static void xirtc_attach(struct device *, struct device *, void *); 68 static int xirtc_gettime(todr_chip_handle_t, struct timeval *); 69 static int xirtc_settime(todr_chip_handle_t, struct timeval *); 70 71 static int strtc_match(struct device *, struct cfdata *, void *); 72 static void strtc_attach(struct device *, struct device *, void *); 73 static int strtc_gettime(todr_chip_handle_t, struct timeval *); 74 static int strtc_settime(todr_chip_handle_t, struct timeval *); 75 76 static int rtc_getcal(todr_chip_handle_t, int *); 77 static int rtc_setcal(todr_chip_handle_t, int); 78 static void rtc_inittodr(void *, time_t base); 79 static void rtc_resettodr(void *); 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(strtc, 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 = xirtc_settime; 141 sc->sc_ct.todr_gettime = xirtc_gettime; 142 sc->sc_ct.todr_getcal = rtc_getcal; 143 sc->sc_ct.todr_setcal = rtc_setcal; 144 145 system_set_todrfns(sc, rtc_inittodr, rtc_resettodr); 146 147 printf("\n"); 148 rtc_cal_timer(); /* XXX */ 149 } 150 151 static int 152 xirtc_settime(todr_chip_handle_t handle, struct timeval *tv) 153 { 154 struct rtc_softc *sc = handle->cookie; 155 struct clock_ymdhms ymdhms; 156 uint8_t year, y2k; 157 158 clock_secs_to_ymdhms(tv->tv_sec, &ymdhms); 159 160 time_smbus_init(sc->sc_smbus_chan); 161 162 /* unlock writes to the CCR */ 163 WRITERTC(sc, X1241REG_SR, X1241REG_SR_WEL); 164 WRITERTC(sc, X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); 165 166 /* set the time */ 167 WRITERTC(sc, X1241REG_HR, TOBCD(ymdhms.dt_hour) | X1241REG_HR_MIL); 168 WRITERTC(sc, X1241REG_MN, TOBCD(ymdhms.dt_min)); 169 WRITERTC(sc, X1241REG_SC, TOBCD(ymdhms.dt_sec)); 170 171 /* set the date */ 172 y2k = (ymdhms.dt_year >= 2000) ? 0x20 : 0x19; 173 year = ymdhms.dt_year % 100; 174 175 WRITERTC(sc, X1241REG_MO, TOBCD(ymdhms.dt_mon)); 176 WRITERTC(sc, X1241REG_DT, TOBCD(ymdhms.dt_day)); 177 WRITERTC(sc, X1241REG_YR, TOBCD(year)); 178 WRITERTC(sc, X1241REG_Y2K, TOBCD(y2k)); 179 180 /* lock writes again */ 181 WRITERTC(sc, X1241REG_SR, 0); 182 183 return (0); 184 } 185 186 static int 187 xirtc_gettime(todr_chip_handle_t handle, struct timeval *tv) 188 { 189 struct rtc_softc *sc = handle->cookie; 190 struct clock_ymdhms ymdhms; 191 uint8_t hour, year, y2k; 192 uint8_t status; 193 194 time_smbus_init(sc->sc_smbus_chan); 195 ymdhms.dt_day = FROMBCD(READRTC(sc, X1241REG_DT)); 196 ymdhms.dt_mon = FROMBCD(READRTC(sc, X1241REG_MO)); 197 year = READRTC(sc, X1241REG_YR); 198 y2k = READRTC(sc, X1241REG_Y2K); 199 ymdhms.dt_year = FROMBCD(y2k) * 100 + FROMBCD(year); 200 201 202 ymdhms.dt_sec = FROMBCD(READRTC(sc, X1241REG_SC)); 203 ymdhms.dt_min = FROMBCD(READRTC(sc, X1241REG_MN)); 204 hour = READRTC(sc, X1241REG_HR); 205 ymdhms.dt_hour = FROMBCD(hour & ~X1241REG_HR_MIL); 206 207 status = READRTC(sc, X1241REG_SR); 208 209 if (status & X1241REG_SR_RTCF) { 210 printf("%s: battery has failed, clock setting is not accurate\n", 211 sc->sc_dev.dv_xname); 212 return (-1); 213 } 214 215 tv->tv_sec = clock_ymdhms_to_secs(&ymdhms); 216 tv->tv_usec = 0; 217 218 return (0); 219 } 220 221 /* 222 * ST M41T81 RTC support. 223 */ 224 static int 225 strtc_match(struct device *parent, struct cfdata *cf, void *aux) 226 { 227 struct smbus_attach_args *sa = aux; 228 int ret; 229 230 if ((sa->sa_interface != M41T81_SMBUS_CHAN) || 231 (sa->sa_device != M41T81_SLAVEADDR)) 232 return (0); 233 234 time_smbus_init(sa->sa_interface); 235 236 ret = time_readrtc(sa->sa_interface, sa->sa_device, SMB_1BYTE_ADDR, M41T81_SEC); 237 if (ret < 0) 238 return (0); 239 240 return (!rtcfound); 241 } 242 243 static void 244 strtc_attach(struct device *parent, struct device *self, void *aux) 245 { 246 struct smbus_attach_args *sa = aux; 247 struct rtc_softc *sc = (void *)self; 248 249 rtcfound = 1; 250 the_rtc = sc; 251 252 sc->sc_smbus_chan = sa->sa_interface; 253 sc->sc_smbus_addr = sa->sa_device; 254 sc->sc_type = SMB_1BYTE_ADDR; /* One-byte register addresses on the ST */ 255 256 /* Set up MI todr(9) stuff */ 257 sc->sc_ct.cookie = sc; 258 sc->sc_ct.todr_settime = strtc_settime; 259 sc->sc_ct.todr_gettime = strtc_gettime; 260 sc->sc_ct.todr_getcal = rtc_getcal; 261 sc->sc_ct.todr_setcal = rtc_setcal; 262 263 system_set_todrfns(sc, rtc_inittodr, rtc_resettodr); 264 265 printf("\n"); 266 rtc_cal_timer(); /* XXX */ 267 } 268 269 static int 270 strtc_settime(todr_chip_handle_t handle, struct timeval *tv) 271 { 272 struct rtc_softc *sc = handle->cookie; 273 struct clock_ymdhms ymdhms; 274 uint8_t hour; 275 276 clock_secs_to_ymdhms(tv->tv_sec, &ymdhms); 277 278 time_smbus_init(sc->sc_smbus_chan); 279 280 hour = TOBCD(ymdhms.dt_hour); 281 if (ymdhms.dt_year >= 2000) /* Should be always true! */ 282 hour |= M41T81_HOUR_CB | M41T81_HOUR_CEB; 283 284 /* set the time */ 285 WRITERTC(sc, M41T81_SEC, TOBCD(ymdhms.dt_sec)); 286 WRITERTC(sc, M41T81_MIN, TOBCD(ymdhms.dt_min)); 287 WRITERTC(sc, M41T81_HOUR, hour); 288 289 /* set the date */ 290 WRITERTC(sc, M41T81_DATE, TOBCD(ymdhms.dt_day)); 291 WRITERTC(sc, M41T81_MON, TOBCD(ymdhms.dt_mon)); 292 WRITERTC(sc, M41T81_YEAR, TOBCD(ymdhms.dt_year % 100)); 293 294 return (0); 295 } 296 297 static int 298 strtc_gettime(todr_chip_handle_t handle, struct timeval *tv) 299 { 300 struct rtc_softc *sc = handle->cookie; 301 struct clock_ymdhms ymdhms; 302 uint8_t hour; 303 304 time_smbus_init(sc->sc_smbus_chan); 305 306 ymdhms.dt_sec = FROMBCD(READRTC(sc, M41T81_SEC)); 307 ymdhms.dt_min = FROMBCD(READRTC(sc, M41T81_MIN)); 308 hour = READRTC(sc, M41T81_HOUR & M41T81_HOUR_MASK); 309 ymdhms.dt_hour = FROMBCD(hour & M41T81_HOUR_MASK); 310 311 ymdhms.dt_day = FROMBCD(READRTC(sc, M41T81_DATE)); 312 ymdhms.dt_mon = FROMBCD(READRTC(sc, M41T81_MON)); 313 ymdhms.dt_year = 1900 + FROMBCD(READRTC(sc, M41T81_YEAR)); 314 if (hour & M41T81_HOUR_CB) 315 ymdhms.dt_year += 100; 316 317 tv->tv_sec = clock_ymdhms_to_secs(&ymdhms); 318 tv->tv_usec = 0; 319 320 return (0); 321 } 322 323 static int 324 rtc_getcal(todr_chip_handle_t handle, int *vp) 325 { 326 327 return (EOPNOTSUPP); 328 } 329 330 static int 331 rtc_setcal(todr_chip_handle_t handle, int v) 332 { 333 334 return (EOPNOTSUPP); 335 } 336 337 338 static void 339 rtc_inittodr(void *cookie, time_t base) 340 { 341 struct timeval todrtime; 342 todr_chip_handle_t chip; 343 struct rtc_softc *sc = cookie; 344 int check; 345 346 check = 0; 347 if (sc == NULL) { 348 printf("inittodr: rtc0 not present"); 349 time.tv_sec = base; 350 time.tv_usec = 0; 351 check = 1; 352 } else { 353 chip = &sc->sc_ct; 354 if (todr_gettime(chip, &todrtime) != 0) { 355 printf("inittodr: Error reading clock"); 356 time.tv_sec = base; 357 time.tv_usec = 0; 358 check = 1; 359 } else { 360 time = todrtime; 361 if (time.tv_sec > base + 3 * SECDAY) { 362 printf("inittodr: Clock has gained %ld days", 363 (time.tv_sec - base) / SECDAY); 364 check = 1; 365 } else if (time.tv_sec + SECDAY < base) { 366 printf("inittodr: Clock has lost %ld day(s)", 367 (base - time.tv_sec) / SECDAY); 368 check = 1; 369 } 370 } 371 } 372 if (check) 373 printf(" - CHECK AND RESET THE DATE.\n"); 374 375 } 376 377 static void 378 rtc_resettodr(void *cookie) 379 { 380 struct rtc_softc *sc = cookie; 381 382 if (time.tv_sec == 0) 383 return; 384 385 if (todr_settime(&sc->sc_ct, (struct timeval *)&time) != 0) 386 printf("resettodr: cannot set time in time-of-day clock\n"); 387 } 388 389 #define NITERS 3 390 #define RTC_SECONDS(rtc) FROMBCD(READRTC((rtc), X1241REG_SC)) 391 392 /* 393 * Since it takes so long to read the complete time/date values from 394 * the RTC over the SMBus, we only read the seconds value. 395 * Later versions of the SWARM will hopefully have the RTC interrupt 396 * attached so we can do the clock calibration much more quickly and 397 * with a higher resolution. 398 */ 399 static void 400 rtc_cal_timer(void) 401 { 402 uint32_t ctrdiff[NITERS], startctr, endctr; 403 int sec, lastsec, i; 404 405 if (rtcfound == 0) { 406 printf("rtc_cal_timer before rtc attached\n"); 407 return; 408 } 409 return; /* XXX XXX */ 410 411 printf("%s: calibrating CPU clock", the_rtc->sc_dev.dv_xname); 412 413 /* 414 * Run the loop an extra time to wait for the second to tick over 415 * and to prime the cache. 416 */ 417 time_smbus_init(the_rtc->sc_smbus_chan); 418 sec = RTC_SECONDS(the_rtc); 419 endctr = mips3_cp0_count_read(); 420 421 for (i = 0; i < NITERS; i++) { 422 int diff; 423 424 again: 425 lastsec = sec; 426 startctr = endctr; 427 428 /* Wait for the timer to tick over. */ 429 do { 430 // time_smbus_init(the_rtc->sc_smbus_chan); 431 sec = RTC_SECONDS(the_rtc); 432 } while (lastsec == sec); 433 endctr = mips3_cp0_count_read(); 434 435 diff = sec - lastsec; 436 if (diff < 0) 437 diff += 60; 438 439 /* Sometimes we appear to skip a second. Clock jitter? */ 440 if (diff > 1) 441 goto again; 442 443 if (endctr < startctr) 444 ctrdiff[i] = 0xffffffff - startctr + endctr; 445 else 446 ctrdiff[i] = endctr - startctr; 447 } 448 printf("\n"); 449 450 /* Compute the number of cycles per second. */ 451 curcpu()->ci_cpu_freq = ((ctrdiff[1] + ctrdiff[2]) / 2); 452 453 /* Compute the delay divisor. */ 454 curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / 1000000; 455 456 /* Compute clock cycles per hz */ 457 curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / hz; 458 459 printf("%s: timer calibration: %lu cycles/sec [(%u, %u)]\n", 460 the_rtc->sc_dev.dv_xname, curcpu()->ci_cpu_freq, 461 ctrdiff[1], ctrdiff[2]); 462 } 463 #undef RTC_SECONDS 464 465 /* XXX eville direct-access-to-the-device code follows... */ 466 467 /* ********************************************************************* 468 * 469 * Copyright 2000,2001 470 * Broadcom Corporation. All rights reserved. 471 * 472 * This software is furnished under license and may be used and 473 * copied only in accordance with the following terms and 474 * conditions. Subject to these conditions, you may download, 475 * copy, install, use, modify and distribute modified or unmodified 476 * copies of this software in source and/or binary form. No title 477 * or ownership is transferred hereby. 478 * 479 * 1) Any source code used, modified or distributed must reproduce 480 * and retain this copyright notice and list of conditions as 481 * they appear in the source file. 482 * 483 * 2) No right is granted to use any trade name, trademark, or 484 * logo of Broadcom Corporation. Neither the "Broadcom 485 * Corporation" name nor any trademark or logo of Broadcom 486 * Corporation may be used to endorse or promote products 487 * derived from this software without the prior written 488 * permission of Broadcom Corporation. 489 * 490 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 491 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 492 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 493 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 494 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 495 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 496 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 497 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 498 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 499 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 500 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 501 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 502 * THE POSSIBILITY OF SUCH DAMAGE. 503 ********************************************************************* */ 504 505 #include <mips/sibyte/include/sb1250_regs.h> 506 #include <mips/sibyte/include/sb1250_smbus.h> 507 508 #define READ_REG(rp) (mips3_ld((uint64_t *)(MIPS_PHYS_TO_KSEG1(rp)))) 509 #define WRITE_REG(rp, val) (mips3_sd((uint64_t *)(MIPS_PHYS_TO_KSEG1(rp)), (val))) 510 511 static void 512 time_smbus_init(int chan) 513 { 514 uint32_t reg; 515 516 reg = A_SMB_REGISTER(chan, R_SMB_FREQ); 517 WRITE_REG(reg, K_SMB_FREQ_100KHZ); 518 reg = A_SMB_REGISTER(chan, R_SMB_CONTROL); 519 WRITE_REG(reg, 0); /* not in direct mode, no interrupts, will poll */ 520 } 521 522 static int 523 time_waitready(int chan) 524 { 525 uint32_t reg; 526 uint64_t status; 527 528 reg = A_SMB_REGISTER(chan, R_SMB_STATUS); 529 530 for (;;) { 531 status = READ_REG(reg); 532 if (status & M_SMB_BUSY) 533 continue; 534 break; 535 } 536 537 if (status & M_SMB_ERROR) { 538 WRITE_REG(reg, (status & M_SMB_ERROR)); 539 return (-1); 540 } 541 return (0); 542 } 543 544 static int 545 time_readrtc(int chan, int slaveaddr, int devaddr, int type) 546 { 547 uint32_t reg; 548 int err; 549 550 /* 551 * Make sure the bus is idle (probably should 552 * ignore error here) 553 */ 554 555 if (time_waitready(chan) < 0) 556 return (-1); 557 558 if (type == SMB_2BYTE_ADDR) { 559 /* 560 * Write the device address to the controller. There are two 561 * parts, the high part goes in the "CMD" field, and the 562 * low part is the data field. 563 */ 564 565 reg = A_SMB_REGISTER(chan, R_SMB_CMD); 566 WRITE_REG(reg, (devaddr >> 8) & 0x7); 567 568 /* 569 * Write the data to the controller 570 */ 571 572 reg = A_SMB_REGISTER(chan, R_SMB_DATA); 573 WRITE_REG(reg, (devaddr & 0xff) & 0xff); 574 } else { /* SMB_1BYTE_ADDR */ 575 /* 576 * Write the device address to the controller. 577 */ 578 579 reg = A_SMB_REGISTER(chan, R_SMB_CMD); 580 WRITE_REG(reg, devaddr & 0xff); 581 } 582 583 /* 584 * Start the command 585 */ 586 587 reg = A_SMB_REGISTER(chan, R_SMB_START); 588 if (type == SMB_2BYTE_ADDR) 589 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR2BYTE) | V_SMB_ADDR(slaveaddr)); 590 else /* SMB_1BYTE_ADDR */ 591 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR1BYTE) | V_SMB_ADDR(slaveaddr)); 592 593 /* 594 * Wait till done 595 */ 596 597 err = time_waitready(chan); 598 if (err < 0) 599 return (err); 600 601 /* 602 * Read the data byte 603 */ 604 605 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_RD1BYTE) | V_SMB_ADDR(slaveaddr)); 606 607 err = time_waitready(chan); 608 if (err < 0) 609 return (err); 610 611 reg = A_SMB_REGISTER(chan, R_SMB_DATA); 612 err = READ_REG(reg); 613 614 return (err & 0xff); 615 } 616 617 static int 618 time_writertc(int chan, int slaveaddr, int devaddr, int type, int b) 619 { 620 uint32_t reg; 621 int err, timer; 622 623 /* 624 * Make sure the bus is idle (probably should 625 * ignore error here) 626 */ 627 628 if (time_waitready(chan) < 0) 629 return (-1); 630 631 /* 632 * Write the device address to the controller. There are two 633 * parts, the high part goes in the "CMD" field, and the 634 * low part is the data field. 635 */ 636 637 reg = A_SMB_REGISTER(chan, R_SMB_CMD); 638 if (type == SMB_2BYTE_ADDR) 639 WRITE_REG(reg, (devaddr >> 8) & 0x7); 640 else /* SMB_1BYTE_ADDR */ 641 WRITE_REG(reg, devaddr & 0xff); 642 643 /* 644 * Write the data to the controller 645 */ 646 647 reg = A_SMB_REGISTER(chan, R_SMB_DATA); 648 if (type == SMB_2BYTE_ADDR) 649 WRITE_REG(reg, (devaddr & 0xff) | ((b & 0xff) << 8)); 650 else /* SMB_1BYTE_ADDR */ 651 WRITE_REG(reg, b & 0xff); 652 653 /* 654 * Start the command. Keep pounding on the device until it 655 * submits or the timer expires, whichever comes first. The 656 * datasheet says writes can take up to 10ms, so we'll give it 500. 657 */ 658 659 reg = A_SMB_REGISTER(chan, R_SMB_START); 660 if (type == SMB_2BYTE_ADDR) 661 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR3BYTE) | V_SMB_ADDR(slaveaddr)); 662 else /* SMB_1BYTE_ADDR */ 663 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_WR2BYTE) | V_SMB_ADDR(slaveaddr)); 664 665 /* 666 * Wait till the SMBus interface is done 667 */ 668 669 err = time_waitready(chan); 670 if (err < 0) 671 return (err); 672 673 /* 674 * Pound on the device with a current address read 675 * to poll for the write complete 676 */ 677 678 err = -1; 679 timer = 100000000; /* XXX */ 680 681 while (timer-- > 0) { 682 WRITE_REG(reg, V_SMB_TT(K_SMB_TT_RD1BYTE) | V_SMB_ADDR(slaveaddr)); 683 684 err = time_waitready(chan); 685 if (err == 0) 686 break; 687 } 688 689 return (err); 690 } 691