1 /* $NetBSD: dwiic.c,v 1.1 2017/12/10 17:12:54 bouyer Exp $ */ 2 3 /* $OpenBSD dwiic.c,v 1.24 2017/08/17 20:41:16 kettenis Exp $ */ 4 5 /*- 6 * Copyright (c) 2017 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Manuel Bouyer. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /* 34 * Synopsys DesignWare I2C controller 35 * 36 * Copyright (c) 2015, 2016 joshua stein <jcs@openbsd.org> 37 * 38 * Permission to use, copy, modify, and/or distribute this software for any 39 * purpose with or without fee is hereby granted, provided that the above 40 * copyright notice and this permission notice appear in all copies. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 48 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 49 */ 50 51 #include <sys/cdefs.h> 52 __KERNEL_RCSID(0, "$NetBSD: dwiic.c,v 1.1 2017/12/10 17:12:54 bouyer Exp $"); 53 54 #include <sys/param.h> 55 #include <sys/bus.h> 56 #include <sys/device.h> 57 #include <sys/kernel.h> 58 #include <sys/systm.h> 59 60 #include <dev/ic/dwiic_var.h> 61 62 //#define DWIIC_DEBUG 63 64 #ifdef DWIIC_DEBUG 65 #define DPRINTF(x) printf x 66 #else 67 #define DPRINTF(x) 68 #endif 69 70 /* register offsets */ 71 #define DW_IC_CON 0x0 72 #define DW_IC_TAR 0x4 73 #define DW_IC_DATA_CMD 0x10 74 #define DW_IC_SS_SCL_HCNT 0x14 75 #define DW_IC_SS_SCL_LCNT 0x18 76 #define DW_IC_FS_SCL_HCNT 0x1c 77 #define DW_IC_FS_SCL_LCNT 0x20 78 #define DW_IC_INTR_STAT 0x2c 79 #define DW_IC_INTR_MASK 0x30 80 #define DW_IC_RAW_INTR_STAT 0x34 81 #define DW_IC_RX_TL 0x38 82 #define DW_IC_TX_TL 0x3c 83 #define DW_IC_CLR_INTR 0x40 84 #define DW_IC_CLR_RX_UNDER 0x44 85 #define DW_IC_CLR_RX_OVER 0x48 86 #define DW_IC_CLR_TX_OVER 0x4c 87 #define DW_IC_CLR_RD_REQ 0x50 88 #define DW_IC_CLR_TX_ABRT 0x54 89 #define DW_IC_CLR_RX_DONE 0x58 90 #define DW_IC_CLR_ACTIVITY 0x5c 91 #define DW_IC_CLR_STOP_DET 0x60 92 #define DW_IC_CLR_START_DET 0x64 93 #define DW_IC_CLR_GEN_CALL 0x68 94 #define DW_IC_ENABLE 0x6c 95 #define DW_IC_STATUS 0x70 96 #define DW_IC_TXFLR 0x74 97 #define DW_IC_RXFLR 0x78 98 #define DW_IC_SDA_HOLD 0x7c 99 #define DW_IC_TX_ABRT_SOURCE 0x80 100 #define DW_IC_ENABLE_STATUS 0x9c 101 #define DW_IC_COMP_PARAM_1 0xf4 102 #define DW_IC_COMP_VERSION 0xf8 103 #define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A 104 #define DW_IC_COMP_TYPE 0xfc 105 #define DW_IC_COMP_TYPE_VALUE 0x44570140 106 107 #define DW_IC_CON_MASTER 0x1 108 #define DW_IC_CON_SPEED_STD 0x2 109 #define DW_IC_CON_SPEED_FAST 0x4 110 #define DW_IC_CON_10BITADDR_MASTER 0x10 111 #define DW_IC_CON_RESTART_EN 0x20 112 #define DW_IC_CON_SLAVE_DISABLE 0x40 113 114 #define DW_IC_DATA_CMD_READ 0x100 115 #define DW_IC_DATA_CMD_STOP 0x200 116 #define DW_IC_DATA_CMD_RESTART 0x400 117 118 #define DW_IC_INTR_RX_UNDER 0x001 119 #define DW_IC_INTR_RX_OVER 0x002 120 #define DW_IC_INTR_RX_FULL 0x004 121 #define DW_IC_INTR_TX_OVER 0x008 122 #define DW_IC_INTR_TX_EMPTY 0x010 123 #define DW_IC_INTR_RD_REQ 0x020 124 #define DW_IC_INTR_TX_ABRT 0x040 125 #define DW_IC_INTR_RX_DONE 0x080 126 #define DW_IC_INTR_ACTIVITY 0x100 127 #define DW_IC_INTR_STOP_DET 0x200 128 #define DW_IC_INTR_START_DET 0x400 129 #define DW_IC_INTR_GEN_CALL 0x800 130 131 #define DW_IC_STATUS_ACTIVITY 0x1 132 133 /* hardware abort codes from the DW_IC_TX_ABRT_SOURCE register */ 134 #define ABRT_7B_ADDR_NOACK 0 135 #define ABRT_10ADDR1_NOACK 1 136 #define ABRT_10ADDR2_NOACK 2 137 #define ABRT_TXDATA_NOACK 3 138 #define ABRT_GCALL_NOACK 4 139 #define ABRT_GCALL_READ 5 140 #define ABRT_SBYTE_ACKDET 7 141 #define ABRT_SBYTE_NORSTRT 9 142 #define ABRT_10B_RD_NORSTRT 10 143 #define ABRT_MASTER_DIS 11 144 #define ARB_LOST 12 145 146 static int dwiic_init(struct dwiic_softc *); 147 static void dwiic_enable(struct dwiic_softc *, bool); 148 static int dwiic_i2c_acquire_bus(void *, int); 149 static void dwiic_i2c_release_bus(void *, int); 150 static uint32_t dwiic_read(struct dwiic_softc *, int); 151 static void dwiic_write(struct dwiic_softc *, int, uint32_t); 152 static int dwiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, 153 size_t, void *, size_t, int); 154 155 bool 156 dwiic_attach(struct dwiic_softc *sc) 157 { 158 if (sc->sc_power != NULL) { 159 if (!sc->sc_power(sc, 1)) { 160 aprint_error_dev(sc->sc_dev, "failed to power up\n"); 161 return 0; 162 } 163 } 164 165 /* fetch timing parameters */ 166 if (sc->ss_hcnt == 0) 167 sc->ss_hcnt = dwiic_read(sc, DW_IC_SS_SCL_HCNT); 168 if (sc->ss_lcnt == 0) 169 sc->ss_lcnt = dwiic_read(sc, DW_IC_SS_SCL_LCNT); 170 if (sc->fs_hcnt == 0) 171 sc->fs_hcnt = dwiic_read(sc, DW_IC_FS_SCL_HCNT); 172 if (sc->fs_lcnt == 0) 173 sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT); 174 if (sc->sda_hold_time == 0) 175 sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD); 176 177 if (dwiic_init(sc)) { 178 aprint_error_dev(sc->sc_dev, "failed initializing\n"); 179 return 0; 180 } 181 182 /* leave the controller disabled */ 183 dwiic_write(sc, DW_IC_INTR_MASK, 0); 184 dwiic_enable(sc, 0); 185 dwiic_read(sc, DW_IC_CLR_INTR); 186 187 mutex_init(&sc->sc_i2c_lock, MUTEX_DEFAULT, IPL_NONE); 188 mutex_init(&sc->sc_int_lock, MUTEX_DEFAULT, IPL_VM); 189 cv_init(&sc->sc_int_readwait, "dwiicr"); 190 cv_init(&sc->sc_int_writewait, "dwiicw"); 191 192 /* setup and attach iic bus */ 193 sc->sc_i2c_tag.ic_cookie = sc; 194 sc->sc_i2c_tag.ic_acquire_bus = dwiic_i2c_acquire_bus; 195 sc->sc_i2c_tag.ic_release_bus = dwiic_i2c_release_bus; 196 sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec; 197 198 sc->sc_iba.iba_tag = &sc->sc_i2c_tag; 199 200 config_found_ia(sc->sc_dev, "i2cbus", &sc->sc_iba, iicbus_print); 201 return 1; 202 } 203 204 int 205 dwiic_detach(device_t self, int flags) 206 { 207 struct dwiic_softc *sc = device_private(self); 208 209 dwiic_enable(sc, 0); 210 if (sc->sc_ih != NULL) { 211 intr_disestablish(sc->sc_ih); 212 sc->sc_ih = NULL; 213 } 214 215 return 0; 216 } 217 218 bool 219 dwiic_suspend(device_t self, const pmf_qual_t *qual) 220 { 221 struct dwiic_softc *sc = device_private(self); 222 223 /* disable controller */ 224 dwiic_enable(sc, 0); 225 226 /* disable interrupts */ 227 dwiic_write(sc, DW_IC_INTR_MASK, 0); 228 dwiic_read(sc, DW_IC_CLR_INTR); 229 if (sc->sc_power != NULL) { 230 if (!sc->sc_power(sc, 0)) { 231 aprint_error_dev(sc->sc_dev, "failed to power off\n"); 232 } 233 } 234 return true; 235 } 236 237 bool 238 dwiic_resume(device_t self, const pmf_qual_t *qual) 239 { 240 struct dwiic_softc *sc = device_private(self); 241 if (sc->sc_power != NULL) { 242 if (!sc->sc_power(sc, 1)) { 243 aprint_error_dev(sc->sc_dev, "failed to power up\n"); 244 return false; 245 } 246 } 247 dwiic_init(sc); 248 return true; 249 } 250 251 static uint32_t 252 dwiic_read(struct dwiic_softc *sc, int offset) 253 { 254 u_int32_t b = bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset); 255 256 DPRINTF(("%s: read at 0x%x = 0x%x\n", device_xname(sc->sc_dev), offset, b)); 257 258 return b; 259 } 260 261 static void 262 dwiic_write(struct dwiic_softc *sc, int offset, uint32_t val) 263 { 264 bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, val); 265 266 DPRINTF(("%s: write at 0x%x: 0x%x\n", device_xname(sc->sc_dev), offset, 267 val)); 268 } 269 270 static int 271 dwiic_i2c_acquire_bus(void *cookie, int flags) 272 { 273 struct dwiic_softc *sc = cookie; 274 275 if (cold || sc->sc_poll || (flags & I2C_F_POLL)) 276 return (0); 277 278 mutex_enter(&sc->sc_i2c_lock); 279 return 1; 280 } 281 282 void 283 dwiic_i2c_release_bus(void *cookie, int flags) 284 { 285 struct dwiic_softc *sc = cookie; 286 287 if (cold || sc->sc_poll || (flags & I2C_F_POLL)) 288 return; 289 290 mutex_exit(&sc->sc_i2c_lock); 291 } 292 293 static int 294 dwiic_init(struct dwiic_softc *sc) 295 { 296 uint32_t reg; 297 298 /* make sure we're talking to a device we know */ 299 reg = dwiic_read(sc, DW_IC_COMP_TYPE); 300 if (reg != DW_IC_COMP_TYPE_VALUE) { 301 DPRINTF(("%s: invalid component type 0x%x\n", 302 device_xname(sc->sc_dev), reg)); 303 return 1; 304 } 305 306 /* disable the adapter */ 307 dwiic_enable(sc, 0); 308 309 /* write standard-mode SCL timing parameters */ 310 dwiic_write(sc, DW_IC_SS_SCL_HCNT, sc->ss_hcnt); 311 dwiic_write(sc, DW_IC_SS_SCL_LCNT, sc->ss_lcnt); 312 313 /* and fast-mode SCL timing parameters */ 314 dwiic_write(sc, DW_IC_FS_SCL_HCNT, sc->fs_hcnt); 315 dwiic_write(sc, DW_IC_FS_SCL_LCNT, sc->fs_lcnt); 316 317 /* SDA hold time */ 318 reg = dwiic_read(sc, DW_IC_COMP_VERSION); 319 if (reg >= DW_IC_SDA_HOLD_MIN_VERS) 320 dwiic_write(sc, DW_IC_SDA_HOLD, sc->sda_hold_time); 321 322 /* FIFO threshold levels */ 323 sc->tx_fifo_depth = 32; 324 sc->rx_fifo_depth = 32; 325 dwiic_write(sc, DW_IC_TX_TL, sc->tx_fifo_depth / 2); 326 dwiic_write(sc, DW_IC_RX_TL, 0); 327 328 /* configure as i2c master with fast speed */ 329 sc->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | 330 DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; 331 dwiic_write(sc, DW_IC_CON, sc->master_cfg); 332 333 return 0; 334 } 335 336 static void 337 dwiic_enable(struct dwiic_softc *sc, bool enable) 338 { 339 int retries; 340 341 for (retries = 100; retries > 0; retries--) { 342 dwiic_write(sc, DW_IC_ENABLE, enable); 343 if ((dwiic_read(sc, DW_IC_ENABLE_STATUS) & 1) == enable) 344 return; 345 346 DELAY(25); 347 } 348 349 aprint_error_dev(sc->sc_dev, "failed to %sable\n", 350 (enable ? "en" : "dis")); 351 } 352 353 static int 354 dwiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf, 355 size_t cmdlen, void *buf, size_t len, int flags) 356 { 357 struct dwiic_softc *sc = cookie; 358 u_int32_t ic_con, st, cmd, resp; 359 int retries, tx_limit, rx_avail, x, readpos; 360 const uint8_t *bcmd; 361 uint8_t *bdata; 362 363 if (cold || sc->sc_poll) 364 flags |= I2C_F_POLL; 365 366 DPRINTF(("%s: %s: op %d, addr 0x%02x, cmdlen %zu, len %zu, " 367 "flags 0x%02x\n", device_xname(sc->sc_dev), __func__, op, addr, cmdlen, 368 len, flags)); 369 370 /* setup transfer */ 371 sc->sc_i2c_xfer.op = op; 372 sc->sc_i2c_xfer.buf = buf; 373 sc->sc_i2c_xfer.len = len; 374 sc->sc_i2c_xfer.flags = flags; 375 sc->sc_i2c_xfer.error = 0; 376 377 /* wait for bus to be idle */ 378 for (retries = 100; retries > 0; retries--) { 379 st = dwiic_read(sc, DW_IC_STATUS); 380 if (!(st & DW_IC_STATUS_ACTIVITY)) 381 break; 382 DELAY(1000); 383 } 384 DPRINTF(("%s: %s: status 0x%x\n", device_xname(sc->sc_dev), __func__, st)); 385 if (st & DW_IC_STATUS_ACTIVITY) { 386 return (1); 387 } 388 389 /* disable controller */ 390 dwiic_enable(sc, 0); 391 392 /* set slave address */ 393 ic_con = dwiic_read(sc, DW_IC_CON); 394 ic_con &= ~DW_IC_CON_10BITADDR_MASTER; 395 dwiic_write(sc, DW_IC_CON, ic_con); 396 dwiic_write(sc, DW_IC_TAR, addr); 397 398 /* disable interrupts */ 399 dwiic_write(sc, DW_IC_INTR_MASK, 0); 400 dwiic_read(sc, DW_IC_CLR_INTR); 401 402 /* enable controller */ 403 dwiic_enable(sc, 1); 404 405 /* wait until the controller is ready for commands */ 406 if (flags & I2C_F_POLL) 407 DELAY(200); 408 else { 409 mutex_enter(&sc->sc_int_lock); 410 dwiic_read(sc, DW_IC_CLR_INTR); 411 dwiic_write(sc, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY); 412 413 if (cv_timedwait(&sc->sc_int_writewait, 414 &sc->sc_int_lock, hz / 2) != 0) 415 aprint_error_dev(sc->sc_dev, 416 "timed out waiting for tx_empty intr\n"); 417 dwiic_write(sc, DW_IC_INTR_MASK, 0); 418 dwiic_read(sc, DW_IC_CLR_INTR); 419 mutex_exit(&sc->sc_int_lock); 420 } 421 422 /* send our command, one byte at a time */ 423 if (cmdlen > 0) { 424 bcmd = (const void *)cmdbuf; 425 426 DPRINTF(("%s: %s: sending cmd (len %zu):", device_xname(sc->sc_dev), 427 __func__, cmdlen)); 428 for (x = 0; x < cmdlen; x++) 429 DPRINTF((" %02x", bcmd[x])); 430 DPRINTF(("\n")); 431 432 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR); 433 if (cmdlen > tx_limit) { 434 /* TODO */ 435 aprint_error_dev(sc->sc_dev, "can't write %zu (> %d)\n", 436 cmdlen, tx_limit); 437 sc->sc_i2c_xfer.error = 1; 438 return (1); 439 } 440 441 for (x = 0; x < cmdlen; x++) { 442 cmd = bcmd[x]; 443 /* 444 * Generate STOP condition if this is the last 445 * byte of the transfer. 446 */ 447 if (x == (cmdlen - 1) && len == 0 && I2C_OP_STOP_P(op)) 448 cmd |= DW_IC_DATA_CMD_STOP; 449 dwiic_write(sc, DW_IC_DATA_CMD, cmd); 450 } 451 } 452 453 bdata = (void *)buf; 454 x = readpos = 0; 455 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR); 456 457 DPRINTF(("%s: %s: need to read %zu bytes, can send %d read reqs\n", 458 device_xname(sc->sc_dev), __func__, len, tx_limit)); 459 460 while (x < len) { 461 if (I2C_OP_WRITE_P(op)) 462 cmd = bdata[x]; 463 else 464 cmd = DW_IC_DATA_CMD_READ; 465 466 /* 467 * Generate RESTART condition if we're reversing 468 * direction. 469 */ 470 if (x == 0 && cmdlen > 0 && I2C_OP_READ_P(op)) 471 cmd |= DW_IC_DATA_CMD_RESTART; 472 /* 473 * Generate STOP conditon on the last byte of the 474 * transfer. 475 */ 476 if (x == (len - 1) && I2C_OP_STOP_P(op)) 477 cmd |= DW_IC_DATA_CMD_STOP; 478 479 dwiic_write(sc, DW_IC_DATA_CMD, cmd); 480 481 tx_limit--; 482 x++; 483 484 /* 485 * As TXFLR fills up, we need to clear it out by reading all 486 * available data. 487 */ 488 while (tx_limit == 0 || x == len) { 489 DPRINTF(("%s: %s: tx_limit %d, sent %d read reqs\n", 490 device_xname(sc->sc_dev), __func__, tx_limit, x)); 491 492 if (flags & I2C_F_POLL) { 493 for (retries = 100; retries > 0; retries--) { 494 rx_avail = dwiic_read(sc, DW_IC_RXFLR); 495 if (rx_avail > 0) 496 break; 497 DELAY(50); 498 } 499 } else { 500 mutex_enter(&sc->sc_int_lock); 501 dwiic_read(sc, DW_IC_CLR_INTR); 502 dwiic_write(sc, DW_IC_INTR_MASK, 503 DW_IC_INTR_RX_FULL); 504 505 if (cv_timedwait(&sc->sc_int_readwait, 506 &sc->sc_int_lock, hz / 2) != 0) 507 aprint_error_dev(sc->sc_dev, 508 "timed out waiting for " 509 "rx_full intr\n"); 510 511 dwiic_write(sc, DW_IC_INTR_MASK, 0); 512 dwiic_read(sc, DW_IC_CLR_INTR); 513 mutex_exit(&sc->sc_int_lock); 514 rx_avail = dwiic_read(sc, DW_IC_RXFLR); 515 } 516 517 if (rx_avail == 0) { 518 aprint_error_dev(sc->sc_dev, 519 "timed out reading remaining %d\n", 520 (int)(len - 1 - readpos)); 521 sc->sc_i2c_xfer.error = 1; 522 return (1); 523 } 524 525 DPRINTF(("%s: %s: %d avail to read (%zu remaining)\n", 526 device_xname(sc->sc_dev), __func__, rx_avail, 527 len - readpos)); 528 529 while (rx_avail > 0) { 530 resp = dwiic_read(sc, DW_IC_DATA_CMD); 531 if (readpos < len) { 532 bdata[readpos] = resp; 533 readpos++; 534 } 535 rx_avail--; 536 } 537 538 if (readpos >= len) 539 break; 540 541 DPRINTF(("%s: still need to read %d bytes\n", 542 device_xname(sc->sc_dev), (int)(len - readpos))); 543 tx_limit = sc->tx_fifo_depth - 544 dwiic_read(sc, DW_IC_TXFLR); 545 } 546 } 547 548 return 0; 549 } 550 551 static uint32_t 552 dwiic_read_clear_intrbits(struct dwiic_softc *sc) 553 { 554 uint32_t stat; 555 556 stat = dwiic_read(sc, DW_IC_INTR_STAT); 557 558 if (stat & DW_IC_INTR_RX_UNDER) 559 dwiic_read(sc, DW_IC_CLR_RX_UNDER); 560 if (stat & DW_IC_INTR_RX_OVER) 561 dwiic_read(sc, DW_IC_CLR_RX_OVER); 562 if (stat & DW_IC_INTR_TX_OVER) 563 dwiic_read(sc, DW_IC_CLR_TX_OVER); 564 if (stat & DW_IC_INTR_RD_REQ) 565 dwiic_read(sc, DW_IC_CLR_RD_REQ); 566 if (stat & DW_IC_INTR_TX_ABRT) 567 dwiic_read(sc, DW_IC_CLR_TX_ABRT); 568 if (stat & DW_IC_INTR_RX_DONE) 569 dwiic_read(sc, DW_IC_CLR_RX_DONE); 570 if (stat & DW_IC_INTR_ACTIVITY) 571 dwiic_read(sc, DW_IC_CLR_ACTIVITY); 572 if (stat & DW_IC_INTR_STOP_DET) 573 dwiic_read(sc, DW_IC_CLR_STOP_DET); 574 if (stat & DW_IC_INTR_START_DET) 575 dwiic_read(sc, DW_IC_CLR_START_DET); 576 if (stat & DW_IC_INTR_GEN_CALL) 577 dwiic_read(sc, DW_IC_CLR_GEN_CALL); 578 579 return stat; 580 } 581 582 int 583 dwiic_intr(void *arg) 584 { 585 struct dwiic_softc *sc = arg; 586 uint32_t en, stat; 587 588 en = dwiic_read(sc, DW_IC_ENABLE); 589 /* probably for the other controller */ 590 if (!en) 591 return 0; 592 593 stat = dwiic_read_clear_intrbits(sc); 594 DPRINTF(("%s: %s: enabled=0x%x stat=0x%x\n", device_xname(sc->sc_dev), 595 __func__, en, stat)); 596 if (!(stat & ~DW_IC_INTR_ACTIVITY)) 597 return 1; 598 599 if (stat & DW_IC_INTR_TX_ABRT) 600 sc->sc_i2c_xfer.error = 1; 601 602 if (sc->sc_i2c_xfer.flags & I2C_F_POLL) 603 DPRINTF(("%s: %s: intr in poll mode?\n", device_xname(sc->sc_dev), 604 __func__)); 605 else { 606 mutex_enter(&sc->sc_int_lock); 607 if (stat & DW_IC_INTR_RX_FULL) { 608 dwiic_write(sc, DW_IC_INTR_MASK, 0); 609 DPRINTF(("%s: %s: waking up reader\n", 610 device_xname(sc->sc_dev), __func__)); 611 cv_signal(&sc->sc_int_readwait); 612 } 613 if (stat & DW_IC_INTR_TX_EMPTY) { 614 dwiic_write(sc, DW_IC_INTR_MASK, 0); 615 DPRINTF(("%s: %s: waking up writer\n", 616 device_xname(sc->sc_dev), __func__)); 617 cv_signal(&sc->sc_int_writewait); 618 } 619 mutex_exit(&sc->sc_int_lock); 620 } 621 622 return 1; 623 } 624