1 /* $NetBSD: dwiic.c,v 1.7 2019/12/23 15:28:08 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@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.7 2019/12/23 15:28:08 thorpej 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 uint32_t dwiic_read(struct dwiic_softc *, int); 149 static void dwiic_write(struct dwiic_softc *, int, uint32_t); 150 static int dwiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, 151 size_t, void *, size_t, int); 152 153 bool 154 dwiic_attach(struct dwiic_softc *sc) 155 { 156 if (sc->sc_power != NULL) { 157 if (!sc->sc_power(sc, 1)) { 158 aprint_error_dev(sc->sc_dev, "failed to power up\n"); 159 return 0; 160 } 161 } 162 163 /* fetch timing parameters */ 164 if (sc->ss_hcnt == 0) 165 sc->ss_hcnt = dwiic_read(sc, DW_IC_SS_SCL_HCNT); 166 if (sc->ss_lcnt == 0) 167 sc->ss_lcnt = dwiic_read(sc, DW_IC_SS_SCL_LCNT); 168 if (sc->fs_hcnt == 0) 169 sc->fs_hcnt = dwiic_read(sc, DW_IC_FS_SCL_HCNT); 170 if (sc->fs_lcnt == 0) 171 sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT); 172 if (sc->sda_hold_time == 0) 173 sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD); 174 175 if (dwiic_init(sc)) { 176 aprint_error_dev(sc->sc_dev, "failed initializing\n"); 177 return 0; 178 } 179 180 /* leave the controller disabled */ 181 dwiic_write(sc, DW_IC_INTR_MASK, 0); 182 dwiic_enable(sc, 0); 183 dwiic_read(sc, DW_IC_CLR_INTR); 184 185 mutex_init(&sc->sc_int_lock, MUTEX_DEFAULT, IPL_VM); 186 cv_init(&sc->sc_int_readwait, "dwiicr"); 187 cv_init(&sc->sc_int_writewait, "dwiicw"); 188 cv_init(&sc->sc_int_stopwait, "dwiics"); 189 190 /* setup and attach iic bus */ 191 iic_tag_init(&sc->sc_i2c_tag); 192 sc->sc_i2c_tag.ic_cookie = sc; 193 sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec; 194 195 sc->sc_iba.iba_tag = &sc->sc_i2c_tag; 196 197 /* config_found_ia for "i2cbus" is done in the bus-attachment glue */ 198 199 return 1; 200 } 201 202 int 203 dwiic_detach(device_t self, int flags) 204 { 205 struct dwiic_softc *sc = device_private(self); 206 207 dwiic_enable(sc, 0); 208 if (sc->sc_ih != NULL) { 209 intr_disestablish(sc->sc_ih); 210 sc->sc_ih = NULL; 211 } 212 213 return 0; 214 } 215 216 bool 217 dwiic_suspend(device_t self, const pmf_qual_t *qual) 218 { 219 struct dwiic_softc *sc = device_private(self); 220 221 /* disable controller */ 222 dwiic_enable(sc, 0); 223 224 /* disable interrupts */ 225 dwiic_write(sc, DW_IC_INTR_MASK, 0); 226 dwiic_read(sc, DW_IC_CLR_INTR); 227 if (sc->sc_power != NULL) { 228 if (!sc->sc_power(sc, 0)) { 229 device_printf(sc->sc_dev, "failed to power off\n"); 230 } 231 } 232 return true; 233 } 234 235 bool 236 dwiic_resume(device_t self, const pmf_qual_t *qual) 237 { 238 struct dwiic_softc *sc = device_private(self); 239 if (sc->sc_power != NULL) { 240 if (!sc->sc_power(sc, 1)) { 241 device_printf(sc->sc_dev, "failed to power up\n"); 242 return false; 243 } 244 } 245 dwiic_init(sc); 246 return true; 247 } 248 249 static uint32_t 250 dwiic_read(struct dwiic_softc *sc, int offset) 251 { 252 u_int32_t b = bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset); 253 254 DPRINTF(("%s: read at 0x%x = 0x%x\n", device_xname(sc->sc_dev), offset, b)); 255 256 return b; 257 } 258 259 static void 260 dwiic_write(struct dwiic_softc *sc, int offset, uint32_t val) 261 { 262 bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, val); 263 264 DPRINTF(("%s: write at 0x%x: 0x%x\n", device_xname(sc->sc_dev), offset, 265 val)); 266 } 267 268 static int 269 dwiic_init(struct dwiic_softc *sc) 270 { 271 uint32_t reg; 272 273 /* make sure we're talking to a device we know */ 274 reg = dwiic_read(sc, DW_IC_COMP_TYPE); 275 if (reg != DW_IC_COMP_TYPE_VALUE) { 276 DPRINTF(("%s: invalid component type 0x%x\n", 277 device_xname(sc->sc_dev), reg)); 278 return 1; 279 } 280 281 /* disable the adapter */ 282 dwiic_enable(sc, 0); 283 284 /* write standard-mode SCL timing parameters */ 285 dwiic_write(sc, DW_IC_SS_SCL_HCNT, sc->ss_hcnt); 286 dwiic_write(sc, DW_IC_SS_SCL_LCNT, sc->ss_lcnt); 287 288 /* and fast-mode SCL timing parameters */ 289 dwiic_write(sc, DW_IC_FS_SCL_HCNT, sc->fs_hcnt); 290 dwiic_write(sc, DW_IC_FS_SCL_LCNT, sc->fs_lcnt); 291 292 /* SDA hold time */ 293 reg = dwiic_read(sc, DW_IC_COMP_VERSION); 294 if (reg >= DW_IC_SDA_HOLD_MIN_VERS) 295 dwiic_write(sc, DW_IC_SDA_HOLD, sc->sda_hold_time); 296 297 /* FIFO threshold levels */ 298 sc->tx_fifo_depth = 32; 299 sc->rx_fifo_depth = 32; 300 dwiic_write(sc, DW_IC_TX_TL, sc->tx_fifo_depth / 2); 301 dwiic_write(sc, DW_IC_RX_TL, 0); 302 303 /* configure as i2c master with fast speed */ 304 sc->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | 305 DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; 306 dwiic_write(sc, DW_IC_CON, sc->master_cfg); 307 308 return 0; 309 } 310 311 static void 312 dwiic_enable(struct dwiic_softc *sc, bool enable) 313 { 314 int retries; 315 316 for (retries = 100; retries > 0; retries--) { 317 dwiic_write(sc, DW_IC_ENABLE, enable); 318 if ((dwiic_read(sc, DW_IC_ENABLE_STATUS) & 1) == enable) 319 return; 320 321 DELAY(25); 322 } 323 324 device_printf(sc->sc_dev, "failed to %sable\n", 325 (enable ? "en" : "dis")); 326 } 327 328 static int 329 dwiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf, 330 size_t cmdlen, void *buf, size_t len, int flags) 331 { 332 struct dwiic_softc *sc = cookie; 333 u_int32_t ic_con, st, cmd, resp; 334 int retries, tx_limit, rx_avail, x, readpos; 335 const uint8_t *bcmd; 336 uint8_t *bdata; 337 338 if (sc->sc_poll) 339 flags |= I2C_F_POLL; 340 341 DPRINTF(("%s: %s: op %d, addr 0x%02x, cmdlen %zu, len %zu, " 342 "flags 0x%02x\n", device_xname(sc->sc_dev), __func__, op, addr, cmdlen, 343 len, flags)); 344 345 /* setup transfer */ 346 sc->sc_i2c_xfer.op = op; 347 sc->sc_i2c_xfer.buf = buf; 348 sc->sc_i2c_xfer.len = len; 349 sc->sc_i2c_xfer.flags = flags; 350 sc->sc_i2c_xfer.error = 0; 351 352 /* wait for bus to be idle */ 353 for (retries = 100; retries > 0; retries--) { 354 st = dwiic_read(sc, DW_IC_STATUS); 355 if (!(st & DW_IC_STATUS_ACTIVITY)) 356 break; 357 DELAY(1000); 358 } 359 DPRINTF(("%s: %s: status 0x%x\n", device_xname(sc->sc_dev), __func__, st)); 360 if (st & DW_IC_STATUS_ACTIVITY) { 361 return (1); 362 } 363 364 /* disable controller */ 365 dwiic_enable(sc, 0); 366 367 /* set slave address */ 368 ic_con = dwiic_read(sc, DW_IC_CON); 369 ic_con &= ~DW_IC_CON_10BITADDR_MASTER; 370 dwiic_write(sc, DW_IC_CON, ic_con); 371 dwiic_write(sc, DW_IC_TAR, addr); 372 373 /* disable interrupts */ 374 dwiic_write(sc, DW_IC_INTR_MASK, 0); 375 dwiic_read(sc, DW_IC_CLR_INTR); 376 377 /* enable controller */ 378 dwiic_enable(sc, 1); 379 380 /* wait until the controller is ready for commands */ 381 if (flags & I2C_F_POLL) 382 DELAY(200); 383 else { 384 mutex_enter(&sc->sc_int_lock); 385 dwiic_read(sc, DW_IC_CLR_INTR); 386 dwiic_write(sc, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY); 387 388 if (cv_timedwait(&sc->sc_int_writewait, 389 &sc->sc_int_lock, hz / 2) != 0) 390 device_printf(sc->sc_dev, 391 "timed out waiting for tx_empty intr\n"); 392 dwiic_write(sc, DW_IC_INTR_MASK, 0); 393 dwiic_read(sc, DW_IC_CLR_INTR); 394 mutex_exit(&sc->sc_int_lock); 395 } 396 397 /* send our command, one byte at a time */ 398 if (cmdlen > 0) { 399 bcmd = (const void *)cmdbuf; 400 401 DPRINTF(("%s: %s: sending cmd (len %zu):", device_xname(sc->sc_dev), 402 __func__, cmdlen)); 403 for (x = 0; x < cmdlen; x++) 404 DPRINTF((" %02x", bcmd[x])); 405 DPRINTF(("\n")); 406 407 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR); 408 if (cmdlen > tx_limit) { 409 /* TODO */ 410 device_printf(sc->sc_dev, "can't write %zu (> %d)\n", 411 cmdlen, tx_limit); 412 sc->sc_i2c_xfer.error = 1; 413 return (1); 414 } 415 416 for (x = 0; x < cmdlen; x++) { 417 cmd = bcmd[x]; 418 /* 419 * Generate STOP condition if this is the last 420 * byte of the transfer. 421 */ 422 if (x == (cmdlen - 1) && len == 0 && I2C_OP_STOP_P(op)) 423 cmd |= DW_IC_DATA_CMD_STOP; 424 dwiic_write(sc, DW_IC_DATA_CMD, cmd); 425 } 426 } 427 428 bdata = (void *)buf; 429 x = readpos = 0; 430 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR); 431 432 DPRINTF(("%s: %s: need to read %zu bytes, can send %d read reqs\n", 433 device_xname(sc->sc_dev), __func__, len, tx_limit)); 434 435 while (x < len) { 436 if (I2C_OP_WRITE_P(op)) 437 cmd = bdata[x]; 438 else 439 cmd = DW_IC_DATA_CMD_READ; 440 441 /* 442 * Generate RESTART condition if we're reversing 443 * direction. 444 */ 445 if (x == 0 && cmdlen > 0 && I2C_OP_READ_P(op)) 446 cmd |= DW_IC_DATA_CMD_RESTART; 447 /* 448 * Generate STOP conditon on the last byte of the 449 * transfer. 450 */ 451 if (x == (len - 1) && I2C_OP_STOP_P(op)) 452 cmd |= DW_IC_DATA_CMD_STOP; 453 454 dwiic_write(sc, DW_IC_DATA_CMD, cmd); 455 456 tx_limit--; 457 x++; 458 459 /* 460 * As TXFLR fills up, we need to clear it out by reading all 461 * available data. 462 */ 463 while (I2C_OP_READ_P(op) && (tx_limit == 0 || x == len)) { 464 DPRINTF(("%s: %s: tx_limit %d, sent %d read reqs\n", 465 device_xname(sc->sc_dev), __func__, tx_limit, x)); 466 467 if (flags & I2C_F_POLL) { 468 for (retries = 100; retries > 0; retries--) { 469 rx_avail = dwiic_read(sc, DW_IC_RXFLR); 470 if (rx_avail > 0) 471 break; 472 DELAY(50); 473 } 474 } else { 475 mutex_enter(&sc->sc_int_lock); 476 dwiic_read(sc, DW_IC_CLR_INTR); 477 dwiic_write(sc, DW_IC_INTR_MASK, 478 DW_IC_INTR_RX_FULL); 479 480 if (cv_timedwait(&sc->sc_int_readwait, 481 &sc->sc_int_lock, hz / 2) != 0) 482 device_printf(sc->sc_dev, 483 "timed out waiting for " 484 "rx_full intr\n"); 485 486 dwiic_write(sc, DW_IC_INTR_MASK, 0); 487 dwiic_read(sc, DW_IC_CLR_INTR); 488 mutex_exit(&sc->sc_int_lock); 489 rx_avail = dwiic_read(sc, DW_IC_RXFLR); 490 } 491 492 if (rx_avail == 0) { 493 device_printf(sc->sc_dev, 494 "timed out reading remaining %d\n", 495 (int)(len - 1 - readpos)); 496 sc->sc_i2c_xfer.error = 1; 497 return (1); 498 } 499 500 DPRINTF(("%s: %s: %d avail to read (%zu remaining)\n", 501 device_xname(sc->sc_dev), __func__, rx_avail, 502 len - readpos)); 503 504 while (rx_avail > 0) { 505 resp = dwiic_read(sc, DW_IC_DATA_CMD); 506 if (readpos < len) { 507 bdata[readpos] = resp; 508 readpos++; 509 } 510 rx_avail--; 511 } 512 513 if (readpos >= len) 514 break; 515 516 DPRINTF(("%s: still need to read %d bytes\n", 517 device_xname(sc->sc_dev), (int)(len - readpos))); 518 tx_limit = sc->tx_fifo_depth - 519 dwiic_read(sc, DW_IC_TXFLR); 520 } 521 } 522 523 if (I2C_OP_STOP_P(op) && I2C_OP_WRITE_P(op)) { 524 if (flags & I2C_F_POLL) { 525 /* wait for bus to be idle */ 526 for (retries = 100; retries > 0; retries--) { 527 st = dwiic_read(sc, DW_IC_STATUS); 528 if (!(st & DW_IC_STATUS_ACTIVITY)) 529 break; 530 DELAY(1000); 531 } 532 if (st & DW_IC_STATUS_ACTIVITY) 533 device_printf(sc->sc_dev, "timed out waiting " 534 "for bus idle\n"); 535 } else { 536 mutex_enter(&sc->sc_int_lock); 537 dwiic_read(sc, DW_IC_CLR_INTR); 538 dwiic_write(sc, DW_IC_INTR_MASK, 539 DW_IC_INTR_STOP_DET); 540 if (cv_timedwait(&sc->sc_int_stopwait, 541 &sc->sc_int_lock, hz / 2) != 0) 542 device_printf(sc->sc_dev, "timed out waiting " 543 "for stop intr\n"); 544 dwiic_write(sc, DW_IC_INTR_MASK, 0); 545 dwiic_read(sc, DW_IC_CLR_INTR); 546 mutex_exit(&sc->sc_int_lock); 547 } 548 } 549 550 return 0; 551 } 552 553 static uint32_t 554 dwiic_read_clear_intrbits(struct dwiic_softc *sc) 555 { 556 uint32_t stat; 557 558 stat = dwiic_read(sc, DW_IC_INTR_STAT); 559 560 if (stat & DW_IC_INTR_RX_UNDER) 561 dwiic_read(sc, DW_IC_CLR_RX_UNDER); 562 if (stat & DW_IC_INTR_RX_OVER) 563 dwiic_read(sc, DW_IC_CLR_RX_OVER); 564 if (stat & DW_IC_INTR_TX_OVER) 565 dwiic_read(sc, DW_IC_CLR_TX_OVER); 566 if (stat & DW_IC_INTR_RD_REQ) 567 dwiic_read(sc, DW_IC_CLR_RD_REQ); 568 if (stat & DW_IC_INTR_TX_ABRT) 569 dwiic_read(sc, DW_IC_CLR_TX_ABRT); 570 if (stat & DW_IC_INTR_RX_DONE) 571 dwiic_read(sc, DW_IC_CLR_RX_DONE); 572 if (stat & DW_IC_INTR_ACTIVITY) 573 dwiic_read(sc, DW_IC_CLR_ACTIVITY); 574 if (stat & DW_IC_INTR_STOP_DET) 575 dwiic_read(sc, DW_IC_CLR_STOP_DET); 576 if (stat & DW_IC_INTR_START_DET) 577 dwiic_read(sc, DW_IC_CLR_START_DET); 578 if (stat & DW_IC_INTR_GEN_CALL) 579 dwiic_read(sc, DW_IC_CLR_GEN_CALL); 580 581 return stat; 582 } 583 584 int 585 dwiic_intr(void *arg) 586 { 587 struct dwiic_softc *sc = arg; 588 uint32_t en, stat; 589 590 en = dwiic_read(sc, DW_IC_ENABLE); 591 /* probably for the other controller */ 592 if (!en) 593 return 0; 594 595 stat = dwiic_read_clear_intrbits(sc); 596 DPRINTF(("%s: %s: enabled=0x%x stat=0x%x\n", device_xname(sc->sc_dev), 597 __func__, en, stat)); 598 if (!(stat & ~DW_IC_INTR_ACTIVITY)) 599 return 1; 600 601 if (stat & DW_IC_INTR_TX_ABRT) 602 sc->sc_i2c_xfer.error = 1; 603 604 if (sc->sc_i2c_xfer.flags & I2C_F_POLL) 605 DPRINTF(("%s: %s: intr in poll mode?\n", device_xname(sc->sc_dev), 606 __func__)); 607 else { 608 mutex_enter(&sc->sc_int_lock); 609 if (stat & DW_IC_INTR_RX_FULL) { 610 dwiic_write(sc, DW_IC_INTR_MASK, 0); 611 DPRINTF(("%s: %s: waking up reader\n", 612 device_xname(sc->sc_dev), __func__)); 613 cv_signal(&sc->sc_int_readwait); 614 } 615 if (stat & DW_IC_INTR_TX_EMPTY) { 616 dwiic_write(sc, DW_IC_INTR_MASK, 0); 617 DPRINTF(("%s: %s: waking up writer\n", 618 device_xname(sc->sc_dev), __func__)); 619 cv_signal(&sc->sc_int_writewait); 620 } 621 if (stat & DW_IC_INTR_STOP_DET) { 622 dwiic_write(sc, DW_IC_INTR_MASK, 0); 623 DPRINTF(("%s: %s: waking up stopper\n", 624 device_xname(sc->sc_dev), __func__)); 625 cv_signal(&sc->sc_int_stopwait); 626 } 627 mutex_exit(&sc->sc_int_lock); 628 } 629 630 return 1; 631 } 632