Lines Matching +full:geni +full:- +full:i2c
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2025 Poul-Henning Kamp <phk@FreeBSD.org>
27 * QualComm GENI I2C controller
29 * The GENI is actually a multi-protocol serial controller, so a lot of
125 #define RD(sc, reg) bus_read_4((sc)->regs_res, reg)
126 #define WR(sc, reg, val) bus_write_4((sc)->regs_res, reg, val)
131 device_printf(sc->dev, "Register Dump\n"); in geni_dump_regs()
133 device_printf(sc->dev, \ in geni_dump_regs()
142 static SYSCTL_NODE(_hw, OID_AUTO, geniiic, CTLFLAG_RW, 0, "GENI I2C");
156 mtx_lock_spin(&sc->intr_lock); in geniiic_intr()
160 if (sc->rx_buf != NULL && rx_fifo_status & 0x3f) { in geniiic_intr()
163 unsigned gotlen = (((rx_fifo_status & 0x3f) << 2)-1) * 4; in geniiic_intr()
173 for (u = 0; u < 4 && sc->rx_len && gotlen; u++) { in geniiic_intr()
174 *sc->rx_buf++ = data & 0xff; in geniiic_intr()
176 sc->rx_len--; in geniiic_intr()
177 gotlen--; in geniiic_intr()
187 sc->rx_complete = true; in geniiic_intr()
194 sc->cmd_status = m_status; in geniiic_intr()
196 if (sc->rx_buf == NULL) { in geniiic_intr()
197 device_printf(sc->dev, in geniiic_intr()
202 device_printf(sc->dev, in geniiic_intr()
205 device_printf(sc->dev, in geniiic_intr()
208 device_printf(sc->dev, in geniiic_intr()
211 device_printf(sc->dev, in geniiic_intr()
219 mtx_unlock_spin(&sc->intr_lock); in geniiic_intr()
248 sc->rx_complete = false; in geniiic_read()
249 sc->rx_fifo = false; in geniiic_read()
250 sc->rx_buf = buf; in geniiic_read()
251 sc->rx_len = len; in geniiic_read()
264 WR(sc, GENI_RX_WATERMARK_REG, sc->rx_fifo_size - 4); in geniiic_read()
274 mtx_lock_spin(&sc->intr_lock); in geniiic_read()
275 sc->rx_fifo = false; in geniiic_read()
278 msleep_spin_sbt(sc, &sc->intr_lock, in geniiic_read()
280 if (sc->rx_complete) in geniiic_read()
283 if (msec > sc->worst) { in geniiic_read()
284 device_printf(sc->dev, in geniiic_read()
285 "Tworst from %u to %u\n", sc->worst, msec); in geniiic_read()
287 sc->worst = msec; in geniiic_read()
290 if (!sc->rx_complete) { in geniiic_read()
295 device_printf(sc->dev, in geniiic_read()
296 "Incomplete read (residual %x)\n", sc->rx_len); in geniiic_read()
299 sc->rx_buf = NULL; in geniiic_read()
300 len = sc->rx_len; in geniiic_read()
301 sc->rx_len = 0; in geniiic_read()
303 mtx_unlock_spin(&sc->intr_lock); in geniiic_read()
306 device_printf(sc->dev, \ in geniiic_read()
308 slave, len, cmd, sc->cmd_status \ in geniiic_read()
312 unsigned unit = device_get_unit(sc->dev); in geniiic_read()
321 if (sc->cmd_status & (1<<10)) { in geniiic_read()
361 if (len) { data |= *buf << 0; buf++; len--; } in geniiic_write()
362 if (len) { data |= *buf << 8; buf++; len--; } in geniiic_write()
363 if (len) { data |= *buf << 16; buf++; len--; } in geniiic_write()
364 if (len) { data |= *buf << 24; buf++; len--; } in geniiic_write()
376 device_printf(sc->dev, in geniiic_write()
402 if (sc->nfail > 4) { in geniiic_transfer()
407 sx_xlock(&sc->real_bus_lock); in geniiic_transfer()
419 (u < nmsgs - 1) && (msgs[u].flags & IIC_M_NOSTOP); in geniiic_transfer()
437 sc->nfail++; in geniiic_transfer()
439 sc->nfail = 0; in geniiic_transfer()
440 sx_xunlock(&sc->real_bus_lock); in geniiic_transfer()
489 if (sx_try_xlock(&sc->bus_lock) == 0) in geniiic_callback()
492 sc->bus_locked = true; in geniiic_callback()
496 if (!sc->bus_locked) { in geniiic_callback()
499 sc->bus_locked = false; in geniiic_callback()
500 sx_xunlock(&sc->bus_lock); in geniiic_callback()
518 mtx_init(&sc->intr_lock, "geniiic intr lock", NULL, MTX_SPIN); in geniiic_attach()
519 sx_init(&sc->real_bus_lock, "geniiic real bus lock"); in geniiic_attach()
520 sx_init(&sc->bus_lock, "geniiic bus lock"); in geniiic_attach()
522 sc->rx_fifo_size = (RD(sc, GENI_HW_PARAM_1) >> 16) & 0x3f; in geniiic_attach()
523 device_printf(sc->dev, " RX fifo size= 0x%x\n", sc->rx_fifo_size); in geniiic_attach()
532 sc->iicbus = device_add_child(sc->dev, "iicbus", DEVICE_UNIT_ANY); in geniiic_attach()
533 if (sc->iicbus == NULL) { in geniiic_attach()
534 device_printf(sc->dev, "iicbus driver not found\n"); in geniiic_attach()
538 error = bus_setup_intr(sc->dev, in geniiic_attach()
539 sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, in geniiic_attach()
540 geniiic_intr, NULL, sc, &sc->intr_handle); in geniiic_attach()
542 device_printf(sc->dev, in geniiic_attach()
546 bus_attach_children(sc->dev); in geniiic_attach()
555 error = bus_generic_detach(sc->dev); in geniiic_detach()
561 if (sc->intr_handle) { in geniiic_detach()
562 bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle); in geniiic_detach()
565 sx_xlock(&sc->bus_lock); in geniiic_detach()
566 sx_xlock(&sc->real_bus_lock); in geniiic_detach()
568 geniiic_reset(sc->dev, 0, 0, NULL); in geniiic_detach()
569 sc->iicbus = NULL; in geniiic_detach()
570 sc->intr_handle = NULL; in geniiic_detach()
572 sx_xunlock(&sc->real_bus_lock); in geniiic_detach()
573 sx_xunlock(&sc->bus_lock); in geniiic_detach()
575 sx_destroy(&sc->real_bus_lock); in geniiic_detach()
576 sx_destroy(&sc->bus_lock); in geniiic_detach()
578 mtx_destroy(&sc->intr_lock); in geniiic_detach()
587 device_printf(sc->dev, "suspend method is NO-OP (good luck!)\n"); in geniiic_suspend()
589 error = bus_generic_suspend(sc->dev); in geniiic_suspend()
598 device_printf(sc->dev, "resume method is NO-OP (good luck!)\n"); in geniiic_resume()
600 error = bus_generic_resume(sc->dev); in geniiic_resume()