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