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