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