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