1 /* $OpenBSD: dwiic.c,v 1.21 2024/08/17 02:35:00 deraadt Exp $ */ 2 /* 3 * Synopsys DesignWare I2C controller 4 * 5 * Copyright (c) 2015-2017 joshua stein <jcs@openbsd.org> 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/param.h> 21 #include <sys/systm.h> 22 #include <sys/kernel.h> 23 24 #include <dev/i2c/i2cvar.h> 25 26 #include <dev/ic/dwiicvar.h> 27 28 struct cfdriver dwiic_cd = { 29 NULL, "dwiic", DV_DULL 30 }; 31 32 int 33 dwiic_activate(struct device *self, int act) 34 { 35 struct dwiic_softc *sc = (struct dwiic_softc *)self; 36 int rv; 37 38 switch (act) { 39 case DVACT_SUSPEND: 40 rv = config_activate_children(self, act); 41 /* disable controller */ 42 dwiic_enable(sc, 0); 43 44 /* disable interrupts */ 45 dwiic_write(sc, DW_IC_INTR_MASK, 0); 46 dwiic_read(sc, DW_IC_CLR_INTR); 47 break; 48 case DVACT_RESUME: 49 /* if it became enabled for some reason, force it down */ 50 dwiic_enable(sc, 0); 51 52 dwiic_write(sc, DW_IC_INTR_MASK, 0); 53 dwiic_read(sc, DW_IC_CLR_INTR); 54 55 /* write standard-mode SCL timing parameters */ 56 dwiic_write(sc, DW_IC_SS_SCL_HCNT, sc->ss_hcnt); 57 dwiic_write(sc, DW_IC_SS_SCL_LCNT, sc->ss_lcnt); 58 59 /* and fast-mode SCL timing parameters */ 60 dwiic_write(sc, DW_IC_FS_SCL_HCNT, sc->fs_hcnt); 61 dwiic_write(sc, DW_IC_FS_SCL_LCNT, sc->fs_lcnt); 62 63 /* SDA hold time */ 64 dwiic_write(sc, DW_IC_SDA_HOLD, sc->sda_hold_time); 65 66 dwiic_write(sc, DW_IC_TX_TL, sc->tx_fifo_depth / 2); 67 dwiic_write(sc, DW_IC_RX_TL, 0); 68 69 /* configure as i2c master with fast speed */ 70 sc->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | 71 DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; 72 dwiic_write(sc, DW_IC_CON, sc->master_cfg); 73 rv = config_activate_children(self, act); 74 break; 75 default: 76 rv = config_activate_children(self, act); 77 break; 78 } 79 return rv; 80 } 81 82 int 83 dwiic_i2c_print(void *aux, const char *pnp) 84 { 85 struct i2c_attach_args *ia = aux; 86 87 if (pnp != NULL) 88 printf("\"%s\" at %s", ia->ia_name, pnp); 89 90 printf(" addr 0x%x", ia->ia_addr); 91 92 return UNCONF; 93 } 94 95 uint32_t 96 dwiic_read(struct dwiic_softc *sc, int offset) 97 { 98 u_int32_t b = bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset); 99 100 DPRINTF(("%s: read at 0x%x = 0x%x\n", sc->sc_dev.dv_xname, offset, b)); 101 102 return b; 103 } 104 105 void 106 dwiic_write(struct dwiic_softc *sc, int offset, uint32_t val) 107 { 108 DPRINTF(("%s: write at 0x%x: 0x%x\n", sc->sc_dev.dv_xname, offset, 109 val)); 110 111 bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, val); 112 } 113 114 int 115 dwiic_i2c_acquire_bus(void *cookie, int flags) 116 { 117 struct dwiic_softc *sc = cookie; 118 119 if (cold || sc->sc_poll || (flags & I2C_F_POLL)) 120 return (0); 121 122 return rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR); 123 } 124 125 void 126 dwiic_i2c_release_bus(void *cookie, int flags) 127 { 128 struct dwiic_softc *sc = cookie; 129 130 if (cold || sc->sc_poll || (flags & I2C_F_POLL)) 131 return; 132 133 rw_exit(&sc->sc_i2c_lock); 134 } 135 136 int 137 dwiic_init(struct dwiic_softc *sc) 138 { 139 uint32_t reg; 140 uint8_t tx_fifo_depth; 141 uint8_t rx_fifo_depth; 142 143 /* make sure we're talking to a device we know */ 144 reg = dwiic_read(sc, DW_IC_COMP_TYPE); 145 if (reg != DW_IC_COMP_TYPE_VALUE) { 146 DPRINTF(("%s: invalid component type 0x%x\n", 147 sc->sc_dev.dv_xname, reg)); 148 return 1; 149 } 150 151 /* fetch default timing parameters if not already specified */ 152 if (!sc->ss_hcnt) 153 sc->ss_hcnt = dwiic_read(sc, DW_IC_SS_SCL_HCNT); 154 if (!sc->ss_lcnt) 155 sc->ss_lcnt = dwiic_read(sc, DW_IC_SS_SCL_LCNT); 156 if (!sc->fs_hcnt) 157 sc->fs_hcnt = dwiic_read(sc, DW_IC_FS_SCL_HCNT); 158 if (!sc->fs_lcnt) 159 sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT); 160 if (!sc->sda_hold_time) 161 sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD); 162 163 /* disable the adapter */ 164 dwiic_enable(sc, 0); 165 166 /* write standard-mode SCL timing parameters */ 167 dwiic_write(sc, DW_IC_SS_SCL_HCNT, sc->ss_hcnt); 168 dwiic_write(sc, DW_IC_SS_SCL_LCNT, sc->ss_lcnt); 169 170 /* and fast-mode SCL timing parameters */ 171 dwiic_write(sc, DW_IC_FS_SCL_HCNT, sc->fs_hcnt); 172 dwiic_write(sc, DW_IC_FS_SCL_LCNT, sc->fs_lcnt); 173 174 /* SDA hold time */ 175 reg = dwiic_read(sc, DW_IC_COMP_VERSION); 176 if (reg >= DW_IC_SDA_HOLD_MIN_VERS) 177 dwiic_write(sc, DW_IC_SDA_HOLD, sc->sda_hold_time); 178 179 /* FIFO threshold levels */ 180 sc->tx_fifo_depth = 32; 181 sc->rx_fifo_depth = 32; 182 reg = dwiic_read(sc, DW_IC_COMP_PARAM_1); 183 tx_fifo_depth = DW_IC_TX_FIFO_DEPTH(reg); 184 rx_fifo_depth = DW_IC_RX_FIFO_DEPTH(reg); 185 if (tx_fifo_depth > 1 && tx_fifo_depth < sc->tx_fifo_depth) 186 sc->tx_fifo_depth = tx_fifo_depth; 187 if (rx_fifo_depth > 1 && rx_fifo_depth < sc->rx_fifo_depth) 188 sc->rx_fifo_depth = rx_fifo_depth; 189 190 dwiic_write(sc, DW_IC_TX_TL, sc->tx_fifo_depth / 2); 191 dwiic_write(sc, DW_IC_RX_TL, 0); 192 193 /* configure as i2c master with fast speed */ 194 sc->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | 195 DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; 196 dwiic_write(sc, DW_IC_CON, sc->master_cfg); 197 198 return 0; 199 } 200 201 void 202 dwiic_enable(struct dwiic_softc *sc, int enable) 203 { 204 int retries; 205 206 for (retries = 100; retries > 0; retries--) { 207 dwiic_write(sc, DW_IC_ENABLE, enable); 208 if ((dwiic_read(sc, DW_IC_ENABLE_STATUS) & 1) == enable) 209 return; 210 211 DELAY(25); 212 } 213 214 printf("%s: failed to %sable\n", sc->sc_dev.dv_xname, 215 (enable ? "en" : "dis")); 216 } 217 218 int 219 dwiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf, 220 size_t cmdlen, void *buf, size_t len, int flags) 221 { 222 struct dwiic_softc *sc = cookie; 223 u_int32_t ic_con, st, cmd, resp; 224 int retries, tx_limit, rx_avail, x, readpos; 225 uint8_t *b; 226 int s; 227 228 if (sc->sc_busy) 229 return 1; 230 231 sc->sc_busy++; 232 233 DPRINTF(("%s: %s: op %d, addr 0x%02x, cmdlen %zu, len %zu, " 234 "flags 0x%02x\n", sc->sc_dev.dv_xname, __func__, op, addr, cmdlen, 235 len, flags)); 236 237 /* setup transfer */ 238 sc->sc_i2c_xfer.op = op; 239 sc->sc_i2c_xfer.buf = buf; 240 sc->sc_i2c_xfer.len = len; 241 sc->sc_i2c_xfer.flags = flags; 242 sc->sc_i2c_xfer.error = 0; 243 244 /* wait for bus to be idle */ 245 for (retries = 100; retries > 0; retries--) { 246 st = dwiic_read(sc, DW_IC_STATUS); 247 if (!(st & DW_IC_STATUS_ACTIVITY)) 248 break; 249 DELAY(1000); 250 } 251 DPRINTF(("%s: %s: status 0x%x\n", sc->sc_dev.dv_xname, __func__, st)); 252 if (st & DW_IC_STATUS_ACTIVITY) { 253 sc->sc_busy = 0; 254 return (1); 255 } 256 257 if (cold || sc->sc_poll) 258 flags |= I2C_F_POLL; 259 260 /* disable controller */ 261 dwiic_enable(sc, 0); 262 263 /* set slave address */ 264 ic_con = dwiic_read(sc, DW_IC_CON); 265 ic_con &= ~DW_IC_CON_10BITADDR_MASTER; 266 dwiic_write(sc, DW_IC_CON, ic_con); 267 dwiic_write(sc, DW_IC_TAR, addr); 268 269 /* disable interrupts */ 270 dwiic_write(sc, DW_IC_INTR_MASK, 0); 271 dwiic_read(sc, DW_IC_CLR_INTR); 272 273 /* enable controller */ 274 dwiic_enable(sc, 1); 275 276 /* wait until the controller is ready for commands */ 277 if (flags & I2C_F_POLL) 278 DELAY(200); 279 else { 280 s = splbio(); 281 dwiic_read(sc, DW_IC_CLR_INTR); 282 dwiic_write(sc, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY); 283 284 if (tsleep_nsec(&sc->sc_writewait, PRIBIO, "dwiic", 285 MSEC_TO_NSEC(500)) != 0) 286 printf("%s: timed out waiting for tx_empty intr\n", 287 sc->sc_dev.dv_xname); 288 splx(s); 289 } 290 291 /* send our command, one byte at a time */ 292 if (cmdlen > 0) { 293 b = (void *)cmdbuf; 294 295 DPRINTF(("%s: %s: sending cmd (len %zu):", sc->sc_dev.dv_xname, 296 __func__, cmdlen)); 297 for (x = 0; x < cmdlen; x++) 298 DPRINTF((" %02x", b[x])); 299 DPRINTF(("\n")); 300 301 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR); 302 if (cmdlen > tx_limit) { 303 /* TODO */ 304 printf("%s: can't write %zu (> %d)\n", 305 sc->sc_dev.dv_xname, cmdlen, tx_limit); 306 sc->sc_i2c_xfer.error = 1; 307 sc->sc_busy = 0; 308 return (1); 309 } 310 311 for (x = 0; x < cmdlen; x++) { 312 cmd = b[x]; 313 /* 314 * Generate STOP condition if this is the last 315 * byte of the transfer. 316 */ 317 if (x == (cmdlen - 1) && len == 0 && I2C_OP_STOP_P(op)) 318 cmd |= DW_IC_DATA_CMD_STOP; 319 dwiic_write(sc, DW_IC_DATA_CMD, cmd); 320 } 321 } 322 323 b = (void *)buf; 324 x = readpos = 0; 325 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR); 326 327 DPRINTF(("%s: %s: need to read %zu bytes, can send %d read reqs\n", 328 sc->sc_dev.dv_xname, __func__, len, tx_limit)); 329 330 while (x < len) { 331 if (I2C_OP_WRITE_P(op)) 332 cmd = b[x]; 333 else 334 cmd = DW_IC_DATA_CMD_READ; 335 336 /* 337 * Generate RESTART condition if we're reversing 338 * direction. 339 */ 340 if (x == 0 && cmdlen > 0 && I2C_OP_READ_P(op)) 341 cmd |= DW_IC_DATA_CMD_RESTART; 342 /* 343 * Generate STOP condition on the last byte of the 344 * transfer. 345 */ 346 if (x == (len - 1) && I2C_OP_STOP_P(op)) 347 cmd |= DW_IC_DATA_CMD_STOP; 348 349 dwiic_write(sc, DW_IC_DATA_CMD, cmd); 350 351 /* 352 * For a block read, get the byte count before 353 * continuing to read the data bytes. 354 */ 355 if (I2C_OP_READ_P(op) && I2C_OP_BLKMODE_P(op) && readpos == 0) 356 tx_limit = 1; 357 358 tx_limit--; 359 x++; 360 361 /* 362 * As TXFLR fills up, we need to clear it out by reading all 363 * available data. 364 */ 365 while (I2C_OP_READ_P(op) && (tx_limit == 0 || x == len)) { 366 DPRINTF(("%s: %s: tx_limit %d, sent %d read reqs\n", 367 sc->sc_dev.dv_xname, __func__, tx_limit, x)); 368 369 if (flags & I2C_F_POLL) { 370 for (retries = 1000; retries > 0; retries--) { 371 rx_avail = dwiic_read(sc, DW_IC_RXFLR); 372 if (rx_avail > 0) 373 break; 374 DELAY(50); 375 } 376 } else { 377 s = splbio(); 378 dwiic_read(sc, DW_IC_CLR_INTR); 379 dwiic_write(sc, DW_IC_INTR_MASK, 380 DW_IC_INTR_RX_FULL); 381 382 if (tsleep_nsec(&sc->sc_readwait, PRIBIO, 383 "dwiic", MSEC_TO_NSEC(500)) != 0) 384 printf("%s: timed out waiting for " 385 "rx_full intr\n", 386 sc->sc_dev.dv_xname); 387 splx(s); 388 389 rx_avail = dwiic_read(sc, DW_IC_RXFLR); 390 } 391 392 if (rx_avail == 0) { 393 printf("%s: timed out reading remaining %d\n", 394 sc->sc_dev.dv_xname, (int)(len - readpos)); 395 sc->sc_i2c_xfer.error = 1; 396 sc->sc_busy = 0; 397 398 return (1); 399 } 400 401 DPRINTF(("%s: %s: %d avail to read (%zu remaining)\n", 402 sc->sc_dev.dv_xname, __func__, rx_avail, 403 len - readpos)); 404 405 while (rx_avail > 0) { 406 resp = dwiic_read(sc, DW_IC_DATA_CMD); 407 if (readpos < len) { 408 b[readpos] = resp; 409 readpos++; 410 } 411 rx_avail--; 412 } 413 414 /* 415 * Update the transfer length when doing a 416 * block read. 417 */ 418 if (I2C_OP_BLKMODE_P(op) && readpos > 0 && len > b[0]) 419 len = b[0] + 1; 420 421 if (readpos >= len) 422 break; 423 424 DPRINTF(("%s: still need to read %d bytes\n", 425 sc->sc_dev.dv_xname, (int)(len - readpos))); 426 tx_limit = sc->tx_fifo_depth - 427 dwiic_read(sc, DW_IC_TXFLR); 428 } 429 430 if (I2C_OP_WRITE_P(op) && tx_limit == 0 && x < len) { 431 if (flags & I2C_F_POLL) { 432 for (retries = 1000; retries > 0; retries--) { 433 tx_limit = sc->tx_fifo_depth - 434 dwiic_read(sc, DW_IC_TXFLR); 435 if (tx_limit > 0) 436 break; 437 DELAY(50); 438 } 439 } else { 440 s = splbio(); 441 dwiic_read(sc, DW_IC_CLR_INTR); 442 dwiic_write(sc, DW_IC_INTR_MASK, 443 DW_IC_INTR_TX_EMPTY); 444 445 if (tsleep_nsec(&sc->sc_writewait, PRIBIO, 446 "dwiic", MSEC_TO_NSEC(500)) != 0) 447 printf("%s: timed out waiting for " 448 "tx_empty intr\n", 449 sc->sc_dev.dv_xname); 450 splx(s); 451 452 tx_limit = sc->tx_fifo_depth - 453 dwiic_read(sc, DW_IC_TXFLR); 454 } 455 456 if (tx_limit == 0) { 457 printf("%s: timed out writing remaining %d\n", 458 sc->sc_dev.dv_xname, (int)(len - x)); 459 sc->sc_i2c_xfer.error = 1; 460 sc->sc_busy = 0; 461 462 return (1); 463 } 464 } 465 } 466 467 if (I2C_OP_STOP_P(op) && I2C_OP_WRITE_P(op)) { 468 if (flags & I2C_F_POLL) { 469 for (retries = 100; retries > 0; retries--) { 470 st = dwiic_read(sc, DW_IC_RAW_INTR_STAT); 471 if (st & DW_IC_INTR_STOP_DET) 472 break; 473 DELAY(1000); 474 } 475 if (!(st & DW_IC_INTR_STOP_DET)) 476 printf("%s: timed out waiting for bus idle\n", 477 sc->sc_dev.dv_xname); 478 } else { 479 s = splbio(); 480 while (sc->sc_busy) { 481 dwiic_write(sc, DW_IC_INTR_MASK, 482 DW_IC_INTR_STOP_DET); 483 if (tsleep_nsec(&sc->sc_busy, PRIBIO, "dwiic", 484 MSEC_TO_NSEC(500)) != 0) 485 printf("%s: timed out waiting for " 486 "stop intr\n", 487 sc->sc_dev.dv_xname); 488 } 489 splx(s); 490 } 491 } 492 sc->sc_busy = 0; 493 494 return 0; 495 } 496 497 uint32_t 498 dwiic_read_clear_intrbits(struct dwiic_softc *sc) 499 { 500 uint32_t stat; 501 502 stat = dwiic_read(sc, DW_IC_INTR_STAT); 503 504 if (stat & DW_IC_INTR_RX_UNDER) 505 dwiic_read(sc, DW_IC_CLR_RX_UNDER); 506 if (stat & DW_IC_INTR_RX_OVER) 507 dwiic_read(sc, DW_IC_CLR_RX_OVER); 508 if (stat & DW_IC_INTR_TX_OVER) 509 dwiic_read(sc, DW_IC_CLR_TX_OVER); 510 if (stat & DW_IC_INTR_RD_REQ) 511 dwiic_read(sc, DW_IC_CLR_RD_REQ); 512 if (stat & DW_IC_INTR_TX_ABRT) 513 dwiic_read(sc, DW_IC_CLR_TX_ABRT); 514 if (stat & DW_IC_INTR_RX_DONE) 515 dwiic_read(sc, DW_IC_CLR_RX_DONE); 516 if (stat & DW_IC_INTR_ACTIVITY) 517 dwiic_read(sc, DW_IC_CLR_ACTIVITY); 518 if (stat & DW_IC_INTR_STOP_DET) 519 dwiic_read(sc, DW_IC_CLR_STOP_DET); 520 if (stat & DW_IC_INTR_START_DET) 521 dwiic_read(sc, DW_IC_CLR_START_DET); 522 if (stat & DW_IC_INTR_GEN_CALL) 523 dwiic_read(sc, DW_IC_CLR_GEN_CALL); 524 525 return stat; 526 } 527 528 int 529 dwiic_intr(void *arg) 530 { 531 struct dwiic_softc *sc = arg; 532 uint32_t en, stat; 533 534 en = dwiic_read(sc, DW_IC_ENABLE); 535 /* probably for the other controller */ 536 if (!en) 537 return 0; 538 539 stat = dwiic_read_clear_intrbits(sc); 540 DPRINTF(("%s: %s: enabled=0x%x stat=0x%x\n", sc->sc_dev.dv_xname, 541 __func__, en, stat)); 542 if (!(stat & ~DW_IC_INTR_ACTIVITY)) 543 return 0; 544 545 if (stat & DW_IC_INTR_TX_ABRT) 546 sc->sc_i2c_xfer.error = 1; 547 548 if (sc->sc_i2c_xfer.flags & I2C_F_POLL) 549 DPRINTF(("%s: %s: intr in poll mode?\n", sc->sc_dev.dv_xname, 550 __func__)); 551 else { 552 if (stat & DW_IC_INTR_RX_FULL) { 553 dwiic_write(sc, DW_IC_INTR_MASK, 0); 554 DPRINTF(("%s: %s: waking up reader\n", 555 sc->sc_dev.dv_xname, __func__)); 556 wakeup(&sc->sc_readwait); 557 } 558 if (stat & DW_IC_INTR_TX_EMPTY) { 559 dwiic_write(sc, DW_IC_INTR_MASK, 0); 560 DPRINTF(("%s: %s: waking up writer\n", 561 sc->sc_dev.dv_xname, __func__)); 562 wakeup(&sc->sc_writewait); 563 } 564 if (stat & DW_IC_INTR_STOP_DET) { 565 dwiic_write(sc, DW_IC_INTR_MASK, 0); 566 sc->sc_busy = 0; 567 wakeup(&sc->sc_busy); 568 } 569 } 570 571 return 1; 572 } 573