1 /* $NetBSD: dwiic.c,v 1.11 2025/09/15 15:18:42 thorpej Exp $ */ 2 3 /* $OpenBSD: dwiic.c,v 1.4 2018/05/23 22:08:00 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 (at) 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.11 2025/09/15 15:18:42 thorpej Exp $"); 53 54 #include <sys/param.h> 55 56 #include <sys/atomic.h> 57 #include <sys/bus.h> 58 #include <sys/device.h> 59 #include <sys/kernel.h> 60 #include <sys/systm.h> 61 62 #include <dev/ic/dwiic_var.h> 63 64 //#define DWIIC_DEBUG 65 66 #ifdef DWIIC_DEBUG 67 #define DPRINTF(x) printf x 68 #else 69 #define DPRINTF(x) 70 #endif 71 72 /* register offsets */ 73 #define DW_IC_CON 0x0 74 #define DW_IC_TAR 0x4 75 #define DW_IC_DATA_CMD 0x10 76 #define DW_IC_SS_SCL_HCNT 0x14 77 #define DW_IC_SS_SCL_LCNT 0x18 78 #define DW_IC_FS_SCL_HCNT 0x1c 79 #define DW_IC_FS_SCL_LCNT 0x20 80 #define DW_IC_INTR_STAT 0x2c 81 #define DW_IC_INTR_MASK 0x30 82 #define DW_IC_RAW_INTR_STAT 0x34 83 #define DW_IC_RX_TL 0x38 84 #define DW_IC_TX_TL 0x3c 85 #define DW_IC_CLR_INTR 0x40 86 #define DW_IC_CLR_RX_UNDER 0x44 87 #define DW_IC_CLR_RX_OVER 0x48 88 #define DW_IC_CLR_TX_OVER 0x4c 89 #define DW_IC_CLR_RD_REQ 0x50 90 #define DW_IC_CLR_TX_ABRT 0x54 91 #define DW_IC_CLR_RX_DONE 0x58 92 #define DW_IC_CLR_ACTIVITY 0x5c 93 #define DW_IC_CLR_STOP_DET 0x60 94 #define DW_IC_CLR_START_DET 0x64 95 #define DW_IC_CLR_GEN_CALL 0x68 96 #define DW_IC_ENABLE 0x6c 97 #define DW_IC_STATUS 0x70 98 #define DW_IC_TXFLR 0x74 99 #define DW_IC_RXFLR 0x78 100 #define DW_IC_SDA_HOLD 0x7c 101 #define DW_IC_TX_ABRT_SOURCE 0x80 102 #define DW_IC_ENABLE_STATUS 0x9c 103 #define DW_IC_COMP_PARAM_1 0xf4 104 #define DW_IC_COMP_VERSION 0xf8 105 #define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A 106 #define DW_IC_COMP_TYPE 0xfc 107 #define DW_IC_COMP_TYPE_VALUE 0x44570140 108 109 #define DW_IC_CON_MASTER 0x1 110 #define DW_IC_CON_SPEED_STD 0x2 111 #define DW_IC_CON_SPEED_FAST 0x4 112 #define DW_IC_CON_10BITADDR_MASTER 0x10 113 #define DW_IC_CON_RESTART_EN 0x20 114 #define DW_IC_CON_SLAVE_DISABLE 0x40 115 116 #define DW_IC_DATA_CMD_READ 0x100 117 #define DW_IC_DATA_CMD_STOP 0x200 118 #define DW_IC_DATA_CMD_RESTART 0x400 119 120 #define DW_IC_INTR_RX_UNDER 0x001 121 #define DW_IC_INTR_RX_OVER 0x002 122 #define DW_IC_INTR_RX_FULL 0x004 123 #define DW_IC_INTR_TX_OVER 0x008 124 #define DW_IC_INTR_TX_EMPTY 0x010 125 #define DW_IC_INTR_RD_REQ 0x020 126 #define DW_IC_INTR_TX_ABRT 0x040 127 #define DW_IC_INTR_RX_DONE 0x080 128 #define DW_IC_INTR_ACTIVITY 0x100 129 #define DW_IC_INTR_STOP_DET 0x200 130 #define DW_IC_INTR_START_DET 0x400 131 #define DW_IC_INTR_GEN_CALL 0x800 132 133 #define DW_IC_STATUS_ACTIVITY 0x1 134 135 /* hardware abort codes from the DW_IC_TX_ABRT_SOURCE register */ 136 #define ABRT_7B_ADDR_NOACK 0 137 #define ABRT_10ADDR1_NOACK 1 138 #define ABRT_10ADDR2_NOACK 2 139 #define ABRT_TXDATA_NOACK 3 140 #define ABRT_GCALL_NOACK 4 141 #define ABRT_GCALL_READ 5 142 #define ABRT_SBYTE_ACKDET 7 143 #define ABRT_SBYTE_NORSTRT 9 144 #define ABRT_10B_RD_NORSTRT 10 145 #define ABRT_MASTER_DIS 11 146 #define ARB_LOST 12 147 148 static int dwiic_init(struct dwiic_softc *); 149 static void dwiic_enable(struct dwiic_softc *, bool); 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_int_lock, MUTEX_DEFAULT, IPL_VM); 188 cv_init(&sc->sc_int_readwait, "dwiicr"); 189 cv_init(&sc->sc_int_writewait, "dwiicw"); 190 cv_init(&sc->sc_int_stopwait, "dwiics"); 191 192 /* setup and attach iic bus */ 193 iic_tag_init(&sc->sc_i2c_tag); 194 sc->sc_i2c_tag.ic_cookie = sc; 195 sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec; 196 197 /* config_found for "i2cbus" is done in the bus-attachment glue */ 198 199 atomic_store_release(&sc->sc_attached, true); 200 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 device_printf(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 device_printf(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_init(struct dwiic_softc *sc) 272 { 273 uint32_t reg; 274 275 /* make sure we're talking to a device we know */ 276 reg = dwiic_read(sc, DW_IC_COMP_TYPE); 277 if (reg != DW_IC_COMP_TYPE_VALUE) { 278 DPRINTF(("%s: invalid component type 0x%x\n", 279 device_xname(sc->sc_dev), reg)); 280 return 1; 281 } 282 283 /* disable the adapter */ 284 dwiic_enable(sc, 0); 285 286 /* write standard-mode SCL timing parameters */ 287 dwiic_write(sc, DW_IC_SS_SCL_HCNT, sc->ss_hcnt); 288 dwiic_write(sc, DW_IC_SS_SCL_LCNT, sc->ss_lcnt); 289 290 /* and fast-mode SCL timing parameters */ 291 dwiic_write(sc, DW_IC_FS_SCL_HCNT, sc->fs_hcnt); 292 dwiic_write(sc, DW_IC_FS_SCL_LCNT, sc->fs_lcnt); 293 294 /* SDA hold time */ 295 reg = dwiic_read(sc, DW_IC_COMP_VERSION); 296 if (reg >= DW_IC_SDA_HOLD_MIN_VERS) 297 dwiic_write(sc, DW_IC_SDA_HOLD, sc->sda_hold_time); 298 299 /* FIFO threshold levels */ 300 sc->tx_fifo_depth = 32; 301 sc->rx_fifo_depth = 32; 302 dwiic_write(sc, DW_IC_TX_TL, sc->tx_fifo_depth / 2); 303 dwiic_write(sc, DW_IC_RX_TL, 0); 304 305 /* configure as i2c master with fast speed */ 306 sc->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | 307 DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; 308 dwiic_write(sc, DW_IC_CON, sc->master_cfg); 309 310 return 0; 311 } 312 313 static void 314 dwiic_enable(struct dwiic_softc *sc, bool enable) 315 { 316 int retries; 317 318 for (retries = 100; retries > 0; retries--) { 319 dwiic_write(sc, DW_IC_ENABLE, enable); 320 if ((dwiic_read(sc, DW_IC_ENABLE_STATUS) & 1) == enable) 321 return; 322 323 DELAY(25); 324 } 325 326 device_printf(sc->sc_dev, "failed to %sable\n", 327 (enable ? "en" : "dis")); 328 } 329 330 static int 331 dwiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf, 332 size_t cmdlen, void *buf, size_t len, int flags) 333 { 334 struct dwiic_softc *sc = cookie; 335 u_int32_t ic_con, st, cmd, resp; 336 int retries, tx_limit, rx_avail, x, readpos; 337 const uint8_t *bcmd; 338 uint8_t *bdata; 339 340 if (sc->sc_poll) 341 flags |= I2C_F_POLL; 342 343 DPRINTF(("%s: %s: op %d, addr 0x%02x, cmdlen %zu, len %zu, " 344 "flags 0x%02x\n", device_xname(sc->sc_dev), __func__, op, addr, cmdlen, 345 len, flags)); 346 347 /* setup transfer */ 348 sc->sc_i2c_xfer.op = op; 349 sc->sc_i2c_xfer.buf = buf; 350 sc->sc_i2c_xfer.len = len; 351 sc->sc_i2c_xfer.flags = flags; 352 sc->sc_i2c_xfer.error = 0; 353 354 /* wait for bus to be idle */ 355 for (retries = 100; retries > 0; retries--) { 356 st = dwiic_read(sc, DW_IC_STATUS); 357 if (!(st & DW_IC_STATUS_ACTIVITY)) 358 break; 359 DELAY(1000); 360 } 361 DPRINTF(("%s: %s: status 0x%x\n", device_xname(sc->sc_dev), __func__, st)); 362 if (st & DW_IC_STATUS_ACTIVITY) { 363 return (1); 364 } 365 366 /* disable controller */ 367 dwiic_enable(sc, 0); 368 369 /* set slave address */ 370 ic_con = dwiic_read(sc, DW_IC_CON); 371 ic_con &= ~DW_IC_CON_10BITADDR_MASTER; 372 dwiic_write(sc, DW_IC_CON, ic_con); 373 dwiic_write(sc, DW_IC_TAR, addr); 374 375 /* disable interrupts */ 376 dwiic_write(sc, DW_IC_INTR_MASK, 0); 377 dwiic_read(sc, DW_IC_CLR_INTR); 378 379 /* enable controller */ 380 dwiic_enable(sc, 1); 381 382 /* wait until the controller is ready for commands */ 383 if (flags & I2C_F_POLL) 384 DELAY(200); 385 else { 386 mutex_enter(&sc->sc_int_lock); 387 dwiic_read(sc, DW_IC_CLR_INTR); 388 dwiic_write(sc, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY); 389 390 if (cv_timedwait(&sc->sc_int_writewait, 391 &sc->sc_int_lock, hz / 2) != 0) 392 device_printf(sc->sc_dev, 393 "timed out waiting for tx_empty intr\n"); 394 dwiic_write(sc, DW_IC_INTR_MASK, 0); 395 dwiic_read(sc, DW_IC_CLR_INTR); 396 mutex_exit(&sc->sc_int_lock); 397 } 398 399 /* send our command, one byte at a time */ 400 if (cmdlen > 0) { 401 bcmd = (const void *)cmdbuf; 402 403 DPRINTF(("%s: %s: sending cmd (len %zu):", device_xname(sc->sc_dev), 404 __func__, cmdlen)); 405 for (x = 0; x < cmdlen; x++) 406 DPRINTF((" %02x", bcmd[x])); 407 DPRINTF(("\n")); 408 409 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR); 410 if (cmdlen > tx_limit) { 411 /* TODO */ 412 device_printf(sc->sc_dev, "can't write %zu (> %d)\n", 413 cmdlen, tx_limit); 414 sc->sc_i2c_xfer.error = 1; 415 return (1); 416 } 417 418 for (x = 0; x < cmdlen; x++) { 419 cmd = bcmd[x]; 420 /* 421 * Generate STOP condition if this is the last 422 * byte of the transfer. 423 */ 424 if (x == (cmdlen - 1) && len == 0 && I2C_OP_STOP_P(op)) 425 cmd |= DW_IC_DATA_CMD_STOP; 426 dwiic_write(sc, DW_IC_DATA_CMD, cmd); 427 } 428 } 429 430 bdata = (void *)buf; 431 x = readpos = 0; 432 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR); 433 434 DPRINTF(("%s: %s: need to read %zu bytes, can send %d read reqs\n", 435 device_xname(sc->sc_dev), __func__, len, tx_limit)); 436 437 while (x < len) { 438 if (I2C_OP_WRITE_P(op)) 439 cmd = bdata[x]; 440 else 441 cmd = DW_IC_DATA_CMD_READ; 442 443 /* 444 * Generate RESTART condition if we're reversing 445 * direction. 446 */ 447 if (x == 0 && cmdlen > 0 && I2C_OP_READ_P(op)) 448 cmd |= DW_IC_DATA_CMD_RESTART; 449 /* 450 * Generate STOP condition on the last byte of the 451 * transfer. 452 */ 453 if (x == (len - 1) && I2C_OP_STOP_P(op)) 454 cmd |= DW_IC_DATA_CMD_STOP; 455 456 dwiic_write(sc, DW_IC_DATA_CMD, cmd); 457 458 tx_limit--; 459 x++; 460 461 /* 462 * As TXFLR fills up, we need to clear it out by reading all 463 * available data. 464 */ 465 while (I2C_OP_READ_P(op) && (tx_limit == 0 || x == len)) { 466 DPRINTF(("%s: %s: tx_limit %d, sent %d read reqs\n", 467 device_xname(sc->sc_dev), __func__, tx_limit, x)); 468 469 if (flags & I2C_F_POLL) { 470 for (retries = 100; retries > 0; retries--) { 471 rx_avail = dwiic_read(sc, DW_IC_RXFLR); 472 if (rx_avail > 0) 473 break; 474 DELAY(50); 475 } 476 } else { 477 mutex_enter(&sc->sc_int_lock); 478 dwiic_read(sc, DW_IC_CLR_INTR); 479 dwiic_write(sc, DW_IC_INTR_MASK, 480 DW_IC_INTR_RX_FULL); 481 482 if (cv_timedwait(&sc->sc_int_readwait, 483 &sc->sc_int_lock, hz / 2) != 0) 484 device_printf(sc->sc_dev, 485 "timed out waiting for " 486 "rx_full intr\n"); 487 488 dwiic_write(sc, DW_IC_INTR_MASK, 0); 489 dwiic_read(sc, DW_IC_CLR_INTR); 490 mutex_exit(&sc->sc_int_lock); 491 rx_avail = dwiic_read(sc, DW_IC_RXFLR); 492 } 493 494 if (rx_avail == 0) { 495 device_printf(sc->sc_dev, 496 "timed out reading remaining %d\n", 497 (int)(len - 1 - readpos)); 498 sc->sc_i2c_xfer.error = 1; 499 return (1); 500 } 501 502 DPRINTF(("%s: %s: %d avail to read (%zu remaining)\n", 503 device_xname(sc->sc_dev), __func__, rx_avail, 504 len - readpos)); 505 506 while (rx_avail > 0) { 507 resp = dwiic_read(sc, DW_IC_DATA_CMD); 508 if (readpos < len) { 509 bdata[readpos] = resp; 510 readpos++; 511 } 512 rx_avail--; 513 } 514 515 if (readpos >= len) 516 break; 517 518 DPRINTF(("%s: still need to read %d bytes\n", 519 device_xname(sc->sc_dev), (int)(len - readpos))); 520 tx_limit = sc->tx_fifo_depth - 521 dwiic_read(sc, DW_IC_TXFLR); 522 } 523 } 524 525 if (I2C_OP_STOP_P(op) && I2C_OP_WRITE_P(op)) { 526 if (flags & I2C_F_POLL) { 527 /* wait for bus to be idle */ 528 for (retries = 100; retries > 0; retries--) { 529 st = dwiic_read(sc, DW_IC_STATUS); 530 if (!(st & DW_IC_STATUS_ACTIVITY)) 531 break; 532 DELAY(1000); 533 } 534 if (st & DW_IC_STATUS_ACTIVITY) 535 device_printf(sc->sc_dev, "timed out waiting " 536 "for bus idle\n"); 537 } else { 538 mutex_enter(&sc->sc_int_lock); 539 dwiic_read(sc, DW_IC_CLR_INTR); 540 dwiic_write(sc, DW_IC_INTR_MASK, 541 DW_IC_INTR_STOP_DET); 542 if (cv_timedwait(&sc->sc_int_stopwait, 543 &sc->sc_int_lock, hz / 2) != 0) 544 device_printf(sc->sc_dev, "timed out waiting " 545 "for stop intr\n"); 546 dwiic_write(sc, DW_IC_INTR_MASK, 0); 547 dwiic_read(sc, DW_IC_CLR_INTR); 548 mutex_exit(&sc->sc_int_lock); 549 } 550 } 551 552 return 0; 553 } 554 555 static uint32_t 556 dwiic_read_clear_intrbits(struct dwiic_softc *sc) 557 { 558 uint32_t stat; 559 560 stat = dwiic_read(sc, DW_IC_INTR_STAT); 561 562 if (stat & DW_IC_INTR_RX_UNDER) 563 dwiic_read(sc, DW_IC_CLR_RX_UNDER); 564 if (stat & DW_IC_INTR_RX_OVER) 565 dwiic_read(sc, DW_IC_CLR_RX_OVER); 566 if (stat & DW_IC_INTR_TX_OVER) 567 dwiic_read(sc, DW_IC_CLR_TX_OVER); 568 if (stat & DW_IC_INTR_RD_REQ) 569 dwiic_read(sc, DW_IC_CLR_RD_REQ); 570 if (stat & DW_IC_INTR_TX_ABRT) 571 dwiic_read(sc, DW_IC_CLR_TX_ABRT); 572 if (stat & DW_IC_INTR_RX_DONE) 573 dwiic_read(sc, DW_IC_CLR_RX_DONE); 574 if (stat & DW_IC_INTR_ACTIVITY) 575 dwiic_read(sc, DW_IC_CLR_ACTIVITY); 576 if (stat & DW_IC_INTR_STOP_DET) 577 dwiic_read(sc, DW_IC_CLR_STOP_DET); 578 if (stat & DW_IC_INTR_START_DET) 579 dwiic_read(sc, DW_IC_CLR_START_DET); 580 if (stat & DW_IC_INTR_GEN_CALL) 581 dwiic_read(sc, DW_IC_CLR_GEN_CALL); 582 583 return stat; 584 } 585 586 int 587 dwiic_intr(void *arg) 588 { 589 struct dwiic_softc *sc = arg; 590 uint32_t en, stat; 591 592 /* 593 * Give up if attach hasn't succeeded. If it failed, nothing 594 * to do here. If it is still ongoing and simply hasn't yet 595 * succeeded, interrupts from the device are masked -- so this 596 * interrupt must be shared with another driver -- and any 597 * interrupts applicable to us will be delivered once 598 * interrupts from the device are unmasked in dwiic_i2c_exec. 599 */ 600 if (!atomic_load_acquire(&sc->sc_attached)) 601 return 0; 602 603 en = dwiic_read(sc, DW_IC_ENABLE); 604 /* probably for the other controller */ 605 if (!en) 606 return 0; 607 608 stat = dwiic_read_clear_intrbits(sc); 609 DPRINTF(("%s: %s: enabled=0x%x stat=0x%x\n", device_xname(sc->sc_dev), 610 __func__, en, stat)); 611 if (!(stat & ~DW_IC_INTR_ACTIVITY)) 612 return 1; 613 614 if (stat & DW_IC_INTR_TX_ABRT) 615 sc->sc_i2c_xfer.error = 1; 616 617 if (sc->sc_i2c_xfer.flags & I2C_F_POLL) 618 DPRINTF(("%s: %s: intr in poll mode?\n", device_xname(sc->sc_dev), 619 __func__)); 620 else { 621 mutex_enter(&sc->sc_int_lock); 622 if (stat & DW_IC_INTR_RX_FULL) { 623 dwiic_write(sc, DW_IC_INTR_MASK, 0); 624 DPRINTF(("%s: %s: waking up reader\n", 625 device_xname(sc->sc_dev), __func__)); 626 cv_signal(&sc->sc_int_readwait); 627 } 628 if (stat & DW_IC_INTR_TX_EMPTY) { 629 dwiic_write(sc, DW_IC_INTR_MASK, 0); 630 DPRINTF(("%s: %s: waking up writer\n", 631 device_xname(sc->sc_dev), __func__)); 632 cv_signal(&sc->sc_int_writewait); 633 } 634 if (stat & DW_IC_INTR_STOP_DET) { 635 dwiic_write(sc, DW_IC_INTR_MASK, 0); 636 DPRINTF(("%s: %s: waking up stopper\n", 637 device_xname(sc->sc_dev), __func__)); 638 cv_signal(&sc->sc_int_stopwait); 639 } 640 mutex_exit(&sc->sc_int_lock); 641 } 642 643 return 1; 644 } 645