jziic.c revision 1.9
1/* $NetBSD: jziic.c,v 1.9 2021/08/07 16:18:59 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.9 2021/08/07 16:18:59 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 64STATIC int jziic_match(device_t, struct cfdata *, void *); 65STATIC void jziic_attach(device_t, device_t, void *); 66 67struct 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 85CFATTACH_DECL_NEW(jziic, sizeof(struct jziic_softc), 86 jziic_match, jziic_attach, NULL, NULL); 87 88STATIC int jziic_enable(struct jziic_softc *); 89STATIC void jziic_disable(struct jziic_softc *); 90STATIC int jziic_wait(struct jziic_softc *); 91STATIC void jziic_set_speed(struct jziic_softc *); 92STATIC int jziic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 93 void *, size_t, int); 94STATIC int jziic_i2c_exec_poll(struct jziic_softc *, i2c_op_t, i2c_addr_t, 95 const void *, size_t, void *, size_t, int); 96STATIC int jziic_i2c_exec_intr(struct jziic_softc *, i2c_op_t, i2c_addr_t, 97 const void *, size_t, void *, size_t, int); 98 99STATIC int jziic_intr(void *); 100 101 102/* ARGSUSED */ 103STATIC int 104jziic_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 */ 115STATIC void 116jziic_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 struct i2cbus_attach_args iba; 121 int error; 122 void *ih; 123#ifdef JZIIC_DEBUG 124 int i; 125 uint8_t in[1] = {0}, out[16]; 126#endif 127 128 sc->sc_dev = self; 129 sc->sc_pclk = aa->aa_pclk; 130 sc->sc_memt = aa->aa_bst; 131 132 error = bus_space_map(aa->aa_bst, aa->aa_addr, 0x100, 0, &sc->sc_memh); 133 if (error) { 134 aprint_error_dev(self, 135 "can't map registers for %s: %d\n", aa->aa_name, error); 136 return; 137 } 138 139 mutex_init(&sc->sc_cvlock, MUTEX_DEFAULT, IPL_NONE); 140 cv_init(&sc->sc_ping, device_xname(self)); 141 142 aprint_naive(": SMBus controller\n"); 143 aprint_normal(": SMBus controller\n"); 144 145 ih = evbmips_intr_establish(aa->aa_irq, jziic_intr, sc); 146 147 if (ih == NULL) { 148 aprint_error_dev(self, "failed to establish interrupt %d\n", 149 aa->aa_irq); 150 goto fail; 151 } 152 153#ifdef JZIIC_DEBUG 154 if (jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP, 0x51, in, 1, out, 9, 0) 155 >= 0) { 156 for (i = 0; i < 9; i++) 157 printf(" %02x", out[i]); 158 printf("\n"); 159 delay(1000000); 160 jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP, 161 0x51, in, 1, out, 9, 0); 162 for (i = 0; i < 9; i++) 163 printf(" %02x", out[i]); 164 printf("\n"); 165 delay(1000000); 166 jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP, 167 0x51, in, 1, out, 9, 0); 168 for (i = 0; i < 9; i++) 169 printf(" %02x", out[i]); 170 printf("\n"); 171 } 172#endif 173 174 /* fill in the i2c tag */ 175 iic_tag_init(&sc->sc_i2c); 176 sc->sc_i2c.ic_cookie = sc; 177 sc->sc_i2c.ic_exec = jziic_i2c_exec; 178 179 memset(&iba, 0, sizeof(iba)); 180 iba.iba_tag = &sc->sc_i2c; 181 config_found(sc->sc_dev, &iba, iicbus_print, CFARGS_NONE); 182 183 184 return; 185 186fail: 187 if (ih) { 188 evbmips_intr_disestablish(ih); 189 } 190 bus_space_unmap(sc->sc_memt, sc->sc_memh, 0x100); 191} 192 193STATIC int 194jziic_enable(struct jziic_softc *sc) 195{ 196 int bail = 100000; 197 uint32_t reg; 198 199 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBENB, JZ_ENABLE); 200 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST); 201 DPRINTF("status: %02x\n", reg); 202 while ((bail > 0) && (reg == 0)) { 203 bail--; 204 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST); 205 } 206 DPRINTF("bail: %d\n", bail); 207 return (reg != 0); 208} 209 210STATIC void 211jziic_disable(struct jziic_softc *sc) 212{ 213 int bail = 100000; 214 uint32_t reg; 215 216 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBENB, 0); 217 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST); 218 DPRINTF("status: %02x\n", reg); 219 while ((bail > 0) && (reg != 0)) { 220 bail--; 221 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST); 222 } 223 DPRINTF("bail: %d\n", bail); 224} 225 226STATIC int 227jziic_wait(struct jziic_softc *sc) 228{ 229 uint32_t reg; 230 int bail = 10000; 231 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST); 232 while ((reg & JZ_MSTACT) && (bail > 0)) { 233 delay(100); 234 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST); 235 bail--; 236 } 237 return ((reg & JZ_MSTACT) == 0); 238} 239 240STATIC void 241jziic_set_speed(struct jziic_softc *sc) 242{ 243 int ticks, hcnt, lcnt, hold, setup; 244 245 /* PCLK ticks per SMBus cycle */ 246 ticks = sc->sc_pclk / 100; /* assuming 100kHz for now */ 247 hcnt = (ticks * 40 / (40 + 47)) - 8; 248 lcnt = (ticks * 47 / (40 + 47)) - 1; 249 hold = sc->sc_pclk * 4 / 10000 - 1; /* ... * 400 / 1000000 ... */ 250 hold = uimax(1, hold); 251 hold |= JZ_HDENB; 252 setup = sc->sc_pclk * 3 / 10000 + 1; /* ... * 300 / 1000000 ... */ 253 DPRINTF("hcnt %d lcnt %d hold %d\n", hcnt, lcnt, hold); 254 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSHCNT, hcnt); 255 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSLCNT, lcnt); 256 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSDAHD, hold); 257 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSDASU, setup); 258 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON, 259 JZ_SLVDIS | JZ_STPHLD | JZ_REST | JZ_SPD_100KB | JZ_MD); 260 (void)bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT); 261} 262 263STATIC int 264jziic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *vcmd, 265 size_t cmdlen, void *vbuf, size_t buflen, int flags) 266{ 267 struct jziic_softc *sc = cookie; 268 269 if (flags & I2C_F_POLL) { 270 return jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf, 271 buflen, flags); 272 } else { 273#ifdef JZIIC_DEBUG 274 uint8_t *b = vbuf; 275 int i, ret; 276 277 memset(vbuf, 0, buflen); 278 jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf, 279 buflen, flags); 280 for (i = 0; i < buflen; i++) { 281 printf(" %02x", b[i]); 282 } 283 printf("\n"); 284 ret = jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf, 285 buflen, flags); 286 for (i = 0; i < buflen; i++) { 287 printf(" %02x", b[i]); 288 } 289 printf("\n"); 290 return ret; 291#else 292 return jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf, 293 buflen, flags); 294#endif 295 } 296} 297 298STATIC int 299jziic_i2c_exec_poll(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr, 300 const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags) 301{ 302 int i, bail = 10000, ret = 0; 303 uint32_t abort; 304 uint8_t *rx, data; 305 const uint8_t *tx; 306 307 tx = vcmd; 308 rx = vbuf; 309 310 DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen); 311 312 jziic_disable(sc); 313 314 /* we're polling, so disable interrupts */ 315 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 316 317 jziic_set_speed(sc); 318 jziic_wait(sc); 319 /* try to talk... */ 320 321 if (!jziic_enable(sc)) { 322 ret = -1; 323 goto bork; 324 } 325 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 326 327 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTAR, addr); 328 jziic_wait(sc); 329 DPRINTF("st: %02x\n", 330 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST)); 331 DPRINTF("wr int: %02x\n", 332 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST)); 333 abort = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBABTSRC); 334 DPRINTF("abort: %02x\n", abort); 335 if ((abort != 0)) { 336 ret = -1; 337 goto bork; 338 } 339 340 do { 341 bail--; 342 delay(100); 343 } while (((bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST) & 344 JZ_TFE) == 0) && (bail > 0)); 345 346 if (cmdlen != 0) { 347 for (i = 0; i < cmdlen; i++) { 348 bus_space_write_4(sc->sc_memt, sc->sc_memh, 349 JZ_SMBDC, *tx); 350 tx++; 351 } 352 } 353 354 if (I2C_OP_READ_P(op)) { 355 /* now read */ 356 for (i = 0; i < (buflen + 1); i++) { 357 bus_space_write_4(sc->sc_memt, sc->sc_memh, 358 JZ_SMBDC, JZ_CMD); 359 } 360 wbflush(); 361 DPRINTF("rd st: %02x\n", 362 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST)); 363 DPRINTF("rd int: %02x\n", 364 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST)); 365 DPRINTF("abort: %02x\n", 366 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBABTSRC)); 367 for (i = 0; i < buflen; i++) { 368 bail = 10000; 369 while (((bus_space_read_4(sc->sc_memt, sc->sc_memh, 370 JZ_SMBST) & JZ_RFNE) == 0) && (bail > 0)) { 371 bail--; 372 delay(100); 373 } 374 if (bail == 0) { 375 ret = -1; 376 goto bork; 377 } 378 data = bus_space_read_4(sc->sc_memt, sc->sc_memh, 379 JZ_SMBDC); 380 DPRINTF("rd st: %02x %d\n", 381 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST), 382 bail); 383 DPRINTF("rd int: %02x\n", 384 bus_space_read_4(sc->sc_memt, sc->sc_memh, 385 JZ_SMBINTST)); 386 DPRINTF("abort: %02x\n", abort); 387 DPRINTF("rd data: %02x\n", data); 388 *rx = data; 389 rx++; 390 } 391 } else { 392 tx = vbuf; 393 for (i = 0; i < buflen; i++) { 394 DPRINTF("wr data: %02x\n", *tx); 395 bus_space_write_4(sc->sc_memt, sc->sc_memh, 396 JZ_SMBDC, *tx); 397 wbflush(); 398 tx++; 399 } 400 jziic_wait(sc); 401 abort = bus_space_read_4(sc->sc_memt, sc->sc_memh, 402 JZ_SMBABTSRC); 403 DPRINTF("abort: %02x\n", abort); 404 if ((abort != 0)) { 405 ret = -1; 406 goto bork; 407 } 408 409 DPRINTF("st: %02x %d\n", 410 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST), bail); 411 DPRINTF("wr int: %02x\n", 412 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST)); 413 } 414 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON, 415 JZ_SLVDIS | JZ_REST | JZ_SPD_100KB | JZ_MD); 416bork: 417 jziic_disable(sc); 418 return ret; 419} 420 421STATIC int 422jziic_i2c_exec_intr(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr, 423 const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags) 424{ 425 int i, ret = 0, bail; 426 427 DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen); 428 429 jziic_disable(sc); 430 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 431 432 mutex_enter(&sc->sc_cvlock); 433 434 sc->sc_reading = FALSE; 435 436 if (I2C_OP_READ_P(op)) { 437 sc->sc_cmd = vcmd; 438 sc->sc_cmdlen = cmdlen; 439 sc->sc_buf = vbuf; 440 sc->sc_buflen = buflen; 441 memset(vbuf, 0, buflen); 442 } else { 443 if ((cmdlen + buflen) > 256) 444 return -1; 445 memcpy(sc->sc_txbuf, vcmd, cmdlen); 446 memcpy(sc->sc_txbuf + cmdlen, vbuf, buflen); 447 sc->sc_cmd = sc->sc_txbuf; 448 sc->sc_cmdlen = cmdlen + buflen; 449 sc->sc_buf = NULL; 450 sc->sc_buflen = 0; 451 } 452 sc->sc_cmdptr = 0; 453 sc->sc_bufptr = 0; 454 sc->sc_rds = 0; 455 sc->sc_abort = 0; 456 457 jziic_set_speed(sc); 458 jziic_wait(sc); 459 460 /* set FIFO levels */ 461 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTXTL, 4); 462 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBRXTL, 0 463 /*min(7, max(0, buflen - 2 ))*/); 464 465 /* try to talk... */ 466 467 if (!jziic_enable(sc)) { 468 ret = -1; 469 goto bork; 470 } 471 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 472 473 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTAR, addr); 474 jziic_wait(sc); 475 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT, JZ_CLEARALL); 476 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 477 JZ_TXABT | JZ_TXEMP); 478 479 bail = 100 * sc->sc_cmdlen; 480 while ((sc->sc_cmdptr < sc->sc_cmdlen) && (bail > 0)) { 481 cv_timedwait(&sc->sc_ping, &sc->sc_cvlock, 1); 482 if (sc->sc_abort) { 483 /* we received an abort interrupt -> bailout */ 484 DPRINTF("abort: %x\n", sc->sc_abort); 485 ret = -1; 486 goto bork; 487 } 488 bail--; 489 } 490 491 if (sc->sc_cmdptr < sc->sc_cmdlen) { 492 /* we didn't send everything? */ 493 DPRINTF("sent %d of %d\n", sc->sc_cmdptr, sc->sc_cmdlen); 494 ret = -1; 495 goto bork; 496 } 497 498 if (I2C_OP_READ_P(op)) { 499 /* now read */ 500 sc->sc_reading = TRUE; 501 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 502 JZ_TXABT | JZ_RXFL | JZ_TXEMP); 503 504 for (i = 0; i < uimin((buflen + 1), 4); i++) { 505 bus_space_write_4(sc->sc_memt, sc->sc_memh, 506 JZ_SMBDC, JZ_CMD); 507 wbflush(); 508 } 509 sc->sc_rds = i; 510 511 bail = 10 * sc->sc_buflen; /* 10 ticks per byte should be ok */ 512 while ((sc->sc_bufptr < sc->sc_buflen) && (bail > 0)) { 513 cv_timedwait(&sc->sc_ping, &sc->sc_cvlock, 1); 514 if (sc->sc_abort) { 515 /* we received an abort interrupt -> bailout */ 516 DPRINTF("rx abort: %x\n", sc->sc_abort); 517 ret = -1; 518 goto bork; 519 } 520 bail--; 521 } 522 523 if (sc->sc_bufptr < sc->sc_buflen) { 524 /* we didn't get everything? */ 525 DPRINTF("rcvd %d of %d\n", sc->sc_bufptr, sc->sc_buflen); 526 ret = -1; 527 goto bork; 528 } 529 } 530 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON, 531 JZ_SLVDIS | JZ_REST | JZ_SPD_100KB | JZ_MD); 532bork: 533 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 534 jziic_disable(sc); 535 mutex_exit(&sc->sc_cvlock); 536 return ret; 537} 538 539STATIC int 540jziic_intr(void *cookie) 541{ 542 struct jziic_softc *sc = cookie; 543 uint32_t stat, data, rstat; 544 int i; 545 546 stat = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST); 547 if (stat & JZ_TXEMP) { 548 if (sc->sc_reading) { 549 if (sc->sc_rds < (sc->sc_buflen + 1)) { 550 for (i = 0; 551 i < uimin(4, (sc->sc_buflen + 1) - 552 sc->sc_rds); 553 i++) { 554 bus_space_write_4( sc->sc_memt, 555 sc->sc_memh, 556 JZ_SMBDC, JZ_CMD); 557 wbflush(); 558 } 559 sc->sc_rds += i; 560 } else { 561 /* we're done, so turn TX FIFO interrupt off */ 562 bus_space_write_4(sc->sc_memt, sc->sc_memh, 563 JZ_SMBINTM, 564 JZ_TXABT | JZ_RXFL); 565 } 566 } else { 567 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, 568 JZ_SMBST); 569 while ((rstat & JZ_TFNF) && 570 (sc->sc_cmdptr < sc->sc_cmdlen)) { 571 data = *sc->sc_cmd; 572 sc->sc_cmd++; 573 sc->sc_cmdptr++; 574 bus_space_write_4(sc->sc_memt, sc->sc_memh, 575 JZ_SMBDC, data & 0xff); 576 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, 577 JZ_SMBST); 578 }; 579 /* no need to clear this one */ 580 if (sc->sc_cmdptr >= sc->sc_cmdlen) { 581 cv_signal(&sc->sc_ping); 582 bus_space_write_4(sc->sc_memt, sc->sc_memh, 583 JZ_SMBINTM, JZ_TXABT); 584 } 585 } 586 } 587 if (stat & JZ_RXFL) { 588 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST); 589 while ((rstat & JZ_RFNE) && (sc->sc_bufptr < sc->sc_buflen)) { 590 data = bus_space_read_4(sc->sc_memt, sc->sc_memh, 591 JZ_SMBDC); 592 *sc->sc_buf = (uint8_t)(data & 0xff); 593 sc->sc_buf++; 594 sc->sc_bufptr++; 595 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, 596 JZ_SMBST); 597 } 598 if (sc->sc_bufptr >= sc->sc_buflen) 599 cv_signal(&sc->sc_ping); 600 } 601 if (stat & JZ_TXABT) { 602 sc->sc_abort = bus_space_read_4(sc->sc_memt, sc->sc_memh, 603 JZ_SMBABTSRC); 604 cv_signal(&sc->sc_ping); 605 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT, 606 JZ_CLEARALL); 607 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0); 608 } 609 return 0; 610} 611