1 /* $NetBSD: jziic.c,v 1.10 2025/09/15 13:23:02 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2015 Michael Lorenz 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: jziic.c,v 1.10 2025/09/15 13:23:02 thorpej Exp $"); 31 32 /* 33 * a preliminary driver for JZ4780's on-chip SMBus controllers 34 * - needs more error handling and interrupt support 35 * - transfers can't be more than the chip's FIFO, supposedly 16 bytes per 36 * direction 37 * so, good enough for RTCs but not much else yet 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/device.h> 44 #include <sys/mutex.h> 45 #include <sys/bus.h> 46 #include <sys/mutex.h> 47 #include <sys/condvar.h> 48 49 #include <mips/ingenic/ingenic_var.h> 50 #include <mips/ingenic/ingenic_regs.h> 51 52 #include <dev/i2c/i2cvar.h> 53 54 #include "opt_ingenic.h" 55 56 #ifdef JZIIC_DEBUG 57 #define DPRINTF aprint_error 58 #define STATIC /* */ 59 #else 60 #define DPRINTF while (0) printf 61 #define STATIC static 62 #endif 63 64 STATIC int jziic_match(device_t, struct cfdata *, void *); 65 STATIC void jziic_attach(device_t, device_t, void *); 66 67 struct jziic_softc { 68 device_t sc_dev; 69 bus_space_tag_t sc_memt; 70 bus_space_handle_t sc_memh; 71 struct i2c_controller sc_i2c; 72 kmutex_t sc_cvlock; 73 uint32_t sc_pclk; 74 /* stuff used for interrupt-driven transfers */ 75 const uint8_t *sc_cmd; 76 uint8_t *sc_buf; 77 uint32_t sc_cmdlen, sc_buflen; 78 uint32_t sc_cmdptr, sc_bufptr, sc_rds; 79 uint32_t sc_abort; 80 kcondvar_t sc_ping; 81 uint8_t sc_txbuf[256]; 82 boolean_t sc_reading; 83 }; 84 85 CFATTACH_DECL_NEW(jziic, sizeof(struct jziic_softc), 86 jziic_match, jziic_attach, NULL, NULL); 87 88 STATIC int jziic_enable(struct jziic_softc *); 89 STATIC void jziic_disable(struct jziic_softc *); 90 STATIC int jziic_wait(struct jziic_softc *); 91 STATIC void jziic_set_speed(struct jziic_softc *); 92 STATIC int jziic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 93 void *, size_t, int); 94 STATIC int jziic_i2c_exec_poll(struct jziic_softc *, i2c_op_t, i2c_addr_t, 95 const void *, size_t, void *, size_t, int); 96 STATIC int jziic_i2c_exec_intr(struct jziic_softc *, i2c_op_t, i2c_addr_t, 97 const void *, size_t, void *, size_t, int); 98 99 STATIC int jziic_intr(void *); 100 101 102 /* ARGSUSED */ 103 STATIC int 104 jziic_match(device_t parent, struct cfdata *match, void *aux) 105 { 106 struct apbus_attach_args *aa = aux; 107 108 if (strcmp(aa->aa_name, "jziic") != 0) 109 return 0; 110 111 return 1; 112 } 113 114 /* ARGSUSED */ 115 STATIC void 116 jziic_attach(device_t parent, device_t self, void *aux) 117 { 118 struct jziic_softc *sc = device_private(self); 119 struct apbus_attach_args *aa = aux; 120 int error; 121 void *ih; 122 #ifdef JZIIC_DEBUG 123 int i; 124 uint8_t in[1] = {0}, out[16]; 125 #endif 126 127 sc->sc_dev = self; 128 sc->sc_pclk = aa->aa_pclk; 129 sc->sc_memt = aa->aa_bst; 130 131 error = bus_space_map(aa->aa_bst, aa->aa_addr, 0x100, 0, &sc->sc_memh); 132 if (error) { 133 aprint_error_dev(self, 134 "can't map registers for %s: %d\n", aa->aa_name, error); 135 return; 136 } 137 138 mutex_init(&sc->sc_cvlock, MUTEX_DEFAULT, IPL_NONE); 139 cv_init(&sc->sc_ping, device_xname(self)); 140 141 aprint_naive(": SMBus controller\n"); 142 aprint_normal(": SMBus controller\n"); 143 144 ih = evbmips_intr_establish(aa->aa_irq, jziic_intr, sc); 145 146 if (ih == NULL) { 147 aprint_error_dev(self, "failed to establish interrupt %d\n", 148 aa->aa_irq); 149 goto fail; 150 } 151 152 #ifdef JZIIC_DEBUG 153 if (jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP, 0x51, in, 1, out, 9, 0) 154 >= 0) { 155 for (i = 0; i < 9; i++) 156 printf(" %02x", out[i]); 157 printf("\n"); 158 delay(1000000); 159 jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP, 160 0x51, in, 1, out, 9, 0); 161 for (i = 0; i < 9; i++) 162 printf(" %02x", out[i]); 163 printf("\n"); 164 delay(1000000); 165 jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP, 166 0x51, in, 1, out, 9, 0); 167 for (i = 0; i < 9; i++) 168 printf(" %02x", out[i]); 169 printf("\n"); 170 } 171 #endif 172 173 /* fill in the i2c tag */ 174 iic_tag_init(&sc->sc_i2c); 175 sc->sc_i2c.ic_cookie = sc; 176 sc->sc_i2c.ic_exec = jziic_i2c_exec; 177 178 iicbus_attach(sc->sc_dev, &sc->sc_i2c); 179 180 return; 181 182 fail: 183 if (ih) { 184 evbmips_intr_disestablish(ih); 185 } 186 bus_space_unmap(sc->sc_memt, sc->sc_memh, 0x100); 187 } 188 189 STATIC int 190 jziic_enable(struct jziic_softc *sc) 191 { 192 int bail = 100000; 193 uint32_t reg; 194 195 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBENB, JZ_ENABLE); 196 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST); 197 DPRINTF("status: %02x\n", reg); 198 while ((bail > 0) && (reg == 0)) { 199 bail--; 200 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST); 201 } 202 DPRINTF("bail: %d\n", bail); 203 return (reg != 0); 204 } 205 206 STATIC void 207 jziic_disable(struct jziic_softc *sc) 208 { 209 int bail = 100000; 210 uint32_t reg; 211 212 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBENB, 0); 213 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST); 214 DPRINTF("status: %02x\n", reg); 215 while ((bail > 0) && (reg != 0)) { 216 bail--; 217 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST); 218 } 219 DPRINTF("bail: %d\n", bail); 220 } 221 222 STATIC int 223 jziic_wait(struct jziic_softc *sc) 224 { 225 uint32_t reg; 226 int bail = 10000; 227 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST); 228 while ((reg & JZ_MSTACT) && (bail > 0)) { 229 delay(100); 230 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST); 231 bail--; 232 } 233 return ((reg & JZ_MSTACT) == 0); 234 } 235 236 STATIC void 237 jziic_set_speed(struct jziic_softc *sc) 238 { 239 int ticks, hcnt, lcnt, hold, setup; 240 241 /* PCLK ticks per SMBus cycle */ 242 ticks = sc->sc_pclk / 100; /* assuming 100kHz for now */ 243 hcnt = (ticks * 40 / (40 + 47)) - 8; 244 lcnt = (ticks * 47 / (40 + 47)) - 1; 245 hold = sc->sc_pclk * 4 / 10000 - 1; /* ... * 400 / 1000000 ... */ 246 hold = uimax(1, hold); 247 hold |= JZ_HDENB; 248 setup = sc->sc_pclk * 3 / 10000 + 1; /* ... * 300 / 1000000 ... */ 249 DPRINTF("hcnt %d lcnt %d hold %d\n", hcnt, lcnt, hold); 250 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSHCNT, hcnt); 251 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSLCNT, lcnt); 252 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSDAHD, hold); 253 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSDASU, setup); 254 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON, 255 JZ_SLVDIS | JZ_STPHLD | JZ_REST | JZ_SPD_100KB | JZ_MD); 256 (void)bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT); 257 } 258 259 STATIC int 260 jziic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *vcmd, 261 size_t cmdlen, void *vbuf, size_t buflen, int flags) 262 { 263 struct jziic_softc *sc = cookie; 264 265 if (flags & I2C_F_POLL) { 266 return jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf, 267 buflen, flags); 268 } else { 269 #ifdef JZIIC_DEBUG 270 uint8_t *b = vbuf; 271 int i, ret; 272 273 memset(vbuf, 0, buflen); 274 jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf, 275 buflen, flags); 276 for (i = 0; i < buflen; i++) { 277 printf(" %02x", b[i]); 278 } 279 printf("\n"); 280 ret = jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf, 281 buflen, flags); 282 for (i = 0; i < buflen; i++) { 283 printf(" %02x", b[i]); 284 } 285 printf("\n"); 286 return ret; 287 #else 288 return jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf, 289 buflen, flags); 290 #endif 291 } 292 } 293 294 STATIC int 295 jziic_i2c_exec_poll(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr, 296 const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags) 297 { 298 int i, bail = 10000, ret = 0; 299 uint32_t abort; 300 uint8_t *rx, data; 301 const uint8_t *tx; 302 303 tx = vcmd; 304 rx = vbuf; 305 306 DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen); 307 308 jziic_disable(sc); 309 310 /* we're polling, so disable interrupts */ 311 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 312 313 jziic_set_speed(sc); 314 jziic_wait(sc); 315 /* try to talk... */ 316 317 if (!jziic_enable(sc)) { 318 ret = -1; 319 goto bork; 320 } 321 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 322 323 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTAR, addr); 324 jziic_wait(sc); 325 DPRINTF("st: %02x\n", 326 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST)); 327 DPRINTF("wr int: %02x\n", 328 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST)); 329 abort = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBABTSRC); 330 DPRINTF("abort: %02x\n", abort); 331 if ((abort != 0)) { 332 ret = -1; 333 goto bork; 334 } 335 336 do { 337 bail--; 338 delay(100); 339 } while (((bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST) & 340 JZ_TFE) == 0) && (bail > 0)); 341 342 if (cmdlen != 0) { 343 for (i = 0; i < cmdlen; i++) { 344 bus_space_write_4(sc->sc_memt, sc->sc_memh, 345 JZ_SMBDC, *tx); 346 tx++; 347 } 348 } 349 350 if (I2C_OP_READ_P(op)) { 351 /* now read */ 352 for (i = 0; i < (buflen + 1); i++) { 353 bus_space_write_4(sc->sc_memt, sc->sc_memh, 354 JZ_SMBDC, JZ_CMD); 355 } 356 wbflush(); 357 DPRINTF("rd st: %02x\n", 358 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST)); 359 DPRINTF("rd int: %02x\n", 360 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST)); 361 DPRINTF("abort: %02x\n", 362 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBABTSRC)); 363 for (i = 0; i < buflen; i++) { 364 bail = 10000; 365 while (((bus_space_read_4(sc->sc_memt, sc->sc_memh, 366 JZ_SMBST) & JZ_RFNE) == 0) && (bail > 0)) { 367 bail--; 368 delay(100); 369 } 370 if (bail == 0) { 371 ret = -1; 372 goto bork; 373 } 374 data = bus_space_read_4(sc->sc_memt, sc->sc_memh, 375 JZ_SMBDC); 376 DPRINTF("rd st: %02x %d\n", 377 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST), 378 bail); 379 DPRINTF("rd int: %02x\n", 380 bus_space_read_4(sc->sc_memt, sc->sc_memh, 381 JZ_SMBINTST)); 382 DPRINTF("abort: %02x\n", abort); 383 DPRINTF("rd data: %02x\n", data); 384 *rx = data; 385 rx++; 386 } 387 } else { 388 tx = vbuf; 389 for (i = 0; i < buflen; i++) { 390 DPRINTF("wr data: %02x\n", *tx); 391 bus_space_write_4(sc->sc_memt, sc->sc_memh, 392 JZ_SMBDC, *tx); 393 wbflush(); 394 tx++; 395 } 396 jziic_wait(sc); 397 abort = bus_space_read_4(sc->sc_memt, sc->sc_memh, 398 JZ_SMBABTSRC); 399 DPRINTF("abort: %02x\n", abort); 400 if ((abort != 0)) { 401 ret = -1; 402 goto bork; 403 } 404 405 DPRINTF("st: %02x %d\n", 406 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST), bail); 407 DPRINTF("wr int: %02x\n", 408 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST)); 409 } 410 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON, 411 JZ_SLVDIS | JZ_REST | JZ_SPD_100KB | JZ_MD); 412 bork: 413 jziic_disable(sc); 414 return ret; 415 } 416 417 STATIC int 418 jziic_i2c_exec_intr(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr, 419 const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags) 420 { 421 int i, ret = 0, bail; 422 423 DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen); 424 425 jziic_disable(sc); 426 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 427 428 mutex_enter(&sc->sc_cvlock); 429 430 sc->sc_reading = FALSE; 431 432 if (I2C_OP_READ_P(op)) { 433 sc->sc_cmd = vcmd; 434 sc->sc_cmdlen = cmdlen; 435 sc->sc_buf = vbuf; 436 sc->sc_buflen = buflen; 437 memset(vbuf, 0, buflen); 438 } else { 439 if ((cmdlen + buflen) > 256) 440 return -1; 441 memcpy(sc->sc_txbuf, vcmd, cmdlen); 442 memcpy(sc->sc_txbuf + cmdlen, vbuf, buflen); 443 sc->sc_cmd = sc->sc_txbuf; 444 sc->sc_cmdlen = cmdlen + buflen; 445 sc->sc_buf = NULL; 446 sc->sc_buflen = 0; 447 } 448 sc->sc_cmdptr = 0; 449 sc->sc_bufptr = 0; 450 sc->sc_rds = 0; 451 sc->sc_abort = 0; 452 453 jziic_set_speed(sc); 454 jziic_wait(sc); 455 456 /* set FIFO levels */ 457 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTXTL, 4); 458 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBRXTL, 0 459 /*min(7, max(0, buflen - 2 ))*/); 460 461 /* try to talk... */ 462 463 if (!jziic_enable(sc)) { 464 ret = -1; 465 goto bork; 466 } 467 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 468 469 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTAR, addr); 470 jziic_wait(sc); 471 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT, JZ_CLEARALL); 472 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 473 JZ_TXABT | JZ_TXEMP); 474 475 bail = 100 * sc->sc_cmdlen; 476 while ((sc->sc_cmdptr < sc->sc_cmdlen) && (bail > 0)) { 477 cv_timedwait(&sc->sc_ping, &sc->sc_cvlock, 1); 478 if (sc->sc_abort) { 479 /* we received an abort interrupt -> bailout */ 480 DPRINTF("abort: %x\n", sc->sc_abort); 481 ret = -1; 482 goto bork; 483 } 484 bail--; 485 } 486 487 if (sc->sc_cmdptr < sc->sc_cmdlen) { 488 /* we didn't send everything? */ 489 DPRINTF("sent %d of %d\n", sc->sc_cmdptr, sc->sc_cmdlen); 490 ret = -1; 491 goto bork; 492 } 493 494 if (I2C_OP_READ_P(op)) { 495 /* now read */ 496 sc->sc_reading = TRUE; 497 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 498 JZ_TXABT | JZ_RXFL | JZ_TXEMP); 499 500 for (i = 0; i < uimin((buflen + 1), 4); i++) { 501 bus_space_write_4(sc->sc_memt, sc->sc_memh, 502 JZ_SMBDC, JZ_CMD); 503 wbflush(); 504 } 505 sc->sc_rds = i; 506 507 bail = 10 * sc->sc_buflen; /* 10 ticks per byte should be ok */ 508 while ((sc->sc_bufptr < sc->sc_buflen) && (bail > 0)) { 509 cv_timedwait(&sc->sc_ping, &sc->sc_cvlock, 1); 510 if (sc->sc_abort) { 511 /* we received an abort interrupt -> bailout */ 512 DPRINTF("rx abort: %x\n", sc->sc_abort); 513 ret = -1; 514 goto bork; 515 } 516 bail--; 517 } 518 519 if (sc->sc_bufptr < sc->sc_buflen) { 520 /* we didn't get everything? */ 521 DPRINTF("rcvd %d of %d\n", sc->sc_bufptr, sc->sc_buflen); 522 ret = -1; 523 goto bork; 524 } 525 } 526 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON, 527 JZ_SLVDIS | JZ_REST | JZ_SPD_100KB | JZ_MD); 528 bork: 529 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 530 jziic_disable(sc); 531 mutex_exit(&sc->sc_cvlock); 532 return ret; 533 } 534 535 STATIC int 536 jziic_intr(void *cookie) 537 { 538 struct jziic_softc *sc = cookie; 539 uint32_t stat, data, rstat; 540 int i; 541 542 stat = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST); 543 if (stat & JZ_TXEMP) { 544 if (sc->sc_reading) { 545 if (sc->sc_rds < (sc->sc_buflen + 1)) { 546 for (i = 0; 547 i < uimin(4, (sc->sc_buflen + 1) - 548 sc->sc_rds); 549 i++) { 550 bus_space_write_4( sc->sc_memt, 551 sc->sc_memh, 552 JZ_SMBDC, JZ_CMD); 553 wbflush(); 554 } 555 sc->sc_rds += i; 556 } else { 557 /* we're done, so turn TX FIFO interrupt off */ 558 bus_space_write_4(sc->sc_memt, sc->sc_memh, 559 JZ_SMBINTM, 560 JZ_TXABT | JZ_RXFL); 561 } 562 } else { 563 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, 564 JZ_SMBST); 565 while ((rstat & JZ_TFNF) && 566 (sc->sc_cmdptr < sc->sc_cmdlen)) { 567 data = *sc->sc_cmd; 568 sc->sc_cmd++; 569 sc->sc_cmdptr++; 570 bus_space_write_4(sc->sc_memt, sc->sc_memh, 571 JZ_SMBDC, data & 0xff); 572 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, 573 JZ_SMBST); 574 }; 575 /* no need to clear this one */ 576 if (sc->sc_cmdptr >= sc->sc_cmdlen) { 577 cv_signal(&sc->sc_ping); 578 bus_space_write_4(sc->sc_memt, sc->sc_memh, 579 JZ_SMBINTM, JZ_TXABT); 580 } 581 } 582 } 583 if (stat & JZ_RXFL) { 584 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST); 585 while ((rstat & JZ_RFNE) && (sc->sc_bufptr < sc->sc_buflen)) { 586 data = bus_space_read_4(sc->sc_memt, sc->sc_memh, 587 JZ_SMBDC); 588 *sc->sc_buf = (uint8_t)(data & 0xff); 589 sc->sc_buf++; 590 sc->sc_bufptr++; 591 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, 592 JZ_SMBST); 593 } 594 if (sc->sc_bufptr >= sc->sc_buflen) 595 cv_signal(&sc->sc_ping); 596 } 597 if (stat & JZ_TXABT) { 598 sc->sc_abort = bus_space_read_4(sc->sc_memt, sc->sc_memh, 599 JZ_SMBABTSRC); 600 cv_signal(&sc->sc_ping); 601 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT, 602 JZ_CLEARALL); 603 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 604 } 605 return 0; 606 } 607