Lines Matching +full:pre +full:- +full:configurable
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
31 * Driver for imx Enhanced Configurable SPI; master-mode only.
143 {"fsl,imx51-ecspi", true},
144 {"fsl,imx53-ecspi", true},
145 {"fsl,imx6dl-ecspi", true},
146 {"fsl,imx6q-ecspi", true},
147 {"fsl,imx6sx-ecspi", true},
148 {"fsl,imx6ul-ecspi", true},
156 return (bus_read_4(sc->memres, offset)); in RD4()
163 bus_write_4(sc->memres, offset, value); in WR4()
169 u_int post, pre; in spi_calc_clockdiv() local
172 if (sc->basefreq <= busfreq) in spi_calc_clockdiv()
176 * Brute-force this; all real-world bus speeds are going to be found on in spi_calc_clockdiv()
180 pre = ((sc->basefreq >> post) / busfreq) - 1; in spi_calc_clockdiv()
181 if (pre < 16) in spi_calc_clockdiv()
186 pre = 15; in spi_calc_clockdiv()
190 if (sc->debug >= 2) { in spi_calc_clockdiv()
191 device_printf(sc->dev, in spi_calc_clockdiv()
192 "base %u bus %u; pre %u, post %u; actual busfreq %u\n", in spi_calc_clockdiv()
193 sc->basefreq, busfreq, pre, post, in spi_calc_clockdiv()
194 (sc->basefreq / (pre + 1)) / (1 << post)); in spi_calc_clockdiv()
197 return (pre << CTLREG_PREDIV_SHIFT) | (post << CTLREG_POSTDIV_SHIFT); in spi_calc_clockdiv()
207 * active-high in the dts, but are supposed to be treated as active-low in spi_set_chipsel()
210 * slave can say its chipsel is active-high, so if that option is in spi_set_chipsel()
215 if (sc->debug >= 2) { in spi_set_chipsel()
216 device_printf(sc->dev, "chipsel %u changed to %u\n", in spi_set_chipsel()
224 gpio_pin_set_active(sc->cspins[cs & ~SPIBUS_CS_HIGH], pinactive); in spi_set_chipsel()
225 gpio_pin_is_active(sc->cspins[cs & ~SPIBUS_CS_HIGH], &pinactive); in spi_set_chipsel()
237 sc->ctlreg = CTLREG_EN | CTLREG_CMODES_MASTER | CTLREG_SMC; in spi_hw_setup()
238 sc->ctlreg |= spi_calc_clockdiv(sc, freq); in spi_hw_setup()
239 sc->ctlreg |= 7 << CTLREG_BLEN_SHIFT; /* XXX byte at a time */ in spi_hw_setup()
240 WR4(sc, ECSPI_CTLREG, sc->ctlreg); in spi_hw_setup()
244 * SPI hardware's chip-select set to zero. The actual chip select is in spi_hw_setup()
276 while (sc->rxidx < sc->rxlen && (RD4(sc, ECSPI_STATREG) & SREG_RR)) { in spi_empty_rxfifo()
277 sc->rxbuf[sc->rxidx++] = (uint8_t)RD4(sc, ECSPI_RXDATA); in spi_empty_rxfifo()
278 --sc->fifocnt; in spi_empty_rxfifo()
286 while (sc->txidx < sc->txlen && sc->fifocnt < FIFO_SIZE) { in spi_fill_txfifo()
287 WR4(sc, ECSPI_TXDATA, sc->txbuf[sc->txidx++]); in spi_fill_txfifo()
288 ++sc->fifocnt; in spi_fill_txfifo()
295 if (sc->txidx == sc->txlen) in spi_fill_txfifo()
296 sc->intreg = (sc->intreg & ~INTREG_TDREN) | INTREG_TEEN; in spi_fill_txfifo()
305 mtx_lock(&sc->mtx); in spi_intr()
308 intreg = sc->intreg; in spi_intr()
318 if (sc->debug || bootverbose) { in spi_intr()
319 device_printf(sc->dev, "rxoverflow rxidx %u txidx %u\n", in spi_intr()
320 sc->rxidx, sc->txidx); in spi_intr()
322 sc->intreg = 0; in spi_intr()
324 mtx_unlock(&sc->mtx); in spi_intr()
336 * - If Transfer Complete is set (shift register is empty) and we've in spi_intr()
338 * - Else if Tx Fifo Empty is set, we need to stop waiting for that and in spi_intr()
342 if (sc->txidx == sc->txlen) { in spi_intr()
343 if ((status & SREG_TC) && sc->fifocnt == 0) { in spi_intr()
344 sc->intreg = 0; in spi_intr()
347 sc->intreg &= ~(sc->intreg & ~INTREG_TEEN); in spi_intr()
348 sc->intreg |= INTREG_TCEN | INTREG_RREN; in spi_intr()
357 if (sc->intreg != intreg) { in spi_intr()
358 WR4(sc, ECSPI_INTREG, sc->intreg); in spi_intr()
362 if (sc->debug >= 3) { in spi_intr()
363 device_printf(sc->dev, in spi_intr()
365 status, intreg, sc->intreg); in spi_intr()
368 mtx_unlock(&sc->mtx); in spi_intr()
376 if (sc->debug >= 1) { in spi_xfer_buf()
377 device_printf(sc->dev, in spi_xfer_buf()
385 sc->rxbuf = rxbuf; in spi_xfer_buf()
386 sc->rxlen = len; in spi_xfer_buf()
387 sc->rxidx = 0; in spi_xfer_buf()
388 sc->txbuf = txbuf; in spi_xfer_buf()
389 sc->txlen = len; in spi_xfer_buf()
390 sc->txidx = 0; in spi_xfer_buf()
391 sc->intreg = INTREG_RDREN | INTREG_TDREN; in spi_xfer_buf()
394 /* Enable interrupts last; spi_fill_txfifo() can change sc->intreg */ in spi_xfer_buf()
395 WR4(sc, ECSPI_INTREG, sc->intreg); in spi_xfer_buf()
398 while (err == 0 && sc->intreg != 0) in spi_xfer_buf()
399 err = msleep(sc, &sc->mtx, 0, "imxspi", 10 * hz); in spi_xfer_buf()
401 if (sc->rxidx != sc->rxlen || sc->txidx != sc->txlen) in spi_xfer_buf()
418 if (cs > CS_MAX || sc->cspins[cs] == NULL) { in spi_transfer()
419 if (sc->debug || bootverbose) in spi_transfer()
420 device_printf(sc->dev, "Invalid chip select %u\n", cs); in spi_transfer()
424 mtx_lock(&sc->mtx); in spi_transfer()
425 device_busy(sc->dev); in spi_transfer()
427 if (sc->debug >= 1) { in spi_transfer()
428 device_printf(sc->dev, in spi_transfer()
439 if (cmd->tx_cmd_sz > 0) in spi_transfer()
440 err = spi_xfer_buf(sc, cmd->rx_cmd, cmd->tx_cmd, in spi_transfer()
441 cmd->tx_cmd_sz); in spi_transfer()
442 if (cmd->tx_data_sz > 0 && err == 0) in spi_transfer()
443 err = spi_xfer_buf(sc, cmd->rx_data, cmd->tx_data, in spi_transfer()
444 cmd->tx_data_sz); in spi_transfer()
450 device_unbusy(sc->dev); in spi_transfer()
451 mtx_unlock(&sc->mtx); in spi_transfer()
473 if ((error = bus_generic_detach(sc->dev)) != 0) in spi_detach()
476 if (sc->spibus != NULL) in spi_detach()
477 device_delete_child(dev, sc->spibus); in spi_detach()
479 for (idx = 0; idx < nitems(sc->cspins); ++idx) { in spi_detach()
480 if (sc->cspins[idx] != NULL) in spi_detach()
481 gpio_pin_release(sc->cspins[idx]); in spi_detach()
484 if (sc->inthandle != NULL) in spi_detach()
485 bus_teardown_intr(sc->dev, sc->intres, sc->inthandle); in spi_detach()
486 if (sc->intres != NULL) in spi_detach()
487 bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->intres); in spi_detach()
488 if (sc->memres != NULL) in spi_detach()
489 bus_release_resource(sc->dev, SYS_RES_MEMORY, 0, sc->memres); in spi_detach()
491 mtx_destroy(&sc->mtx); in spi_detach()
503 sc->dev = dev; in spi_attach()
504 sc->basefreq = imx_ccm_ecspi_hz(); in spi_attach()
506 mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); in spi_attach()
508 /* Set up debug-enable sysctl. */ in spi_attach()
509 SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->dev), in spi_attach()
510 SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), in spi_attach()
511 OID_AUTO, "debug", CTLFLAG_RWTUN, &sc->debug, 0, in spi_attach()
516 sc->memres = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid, in spi_attach()
518 if (sc->memres == NULL) { in spi_attach()
519 device_printf(sc->dev, "could not allocate registers\n"); in spi_attach()
520 spi_detach(sc->dev); in spi_attach()
526 sc->intres = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &rid, in spi_attach()
528 if (sc->intres == NULL) { in spi_attach()
529 device_printf(sc->dev, "could not allocate interrupt\n"); in spi_attach()
530 device_detach(sc->dev); in spi_attach()
533 err = bus_setup_intr(sc->dev, sc->intres, INTR_TYPE_MISC | INTR_MPSAFE, in spi_attach()
534 NULL, spi_intr, sc, &sc->inthandle); in spi_attach()
536 device_printf(sc->dev, "could not setup interrupt handler"); in spi_attach()
537 device_detach(sc->dev); in spi_attach()
542 node = ofw_bus_get_node(sc->dev); in spi_attach()
543 for (idx = 0; idx < nitems(sc->cspins); ++idx) { in spi_attach()
544 err = gpio_pin_get_by_ofw_propidx(sc->dev, node, "cs-gpios", in spi_attach()
545 idx, &sc->cspins[idx]); in spi_attach()
547 gpio_pin_setflags(sc->cspins[idx], GPIO_PIN_OUTPUT); in spi_attach()
548 } else if (sc->debug >= 2) { in spi_attach()
549 device_printf(sc->dev, in spi_attach()
561 * Add the spibus driver as a child, and setup a one-shot intrhook to in spi_attach()
566 sc->spibus = device_add_child(dev, "spibus", DEVICE_UNIT_ANY); in spi_attach()
578 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) in spi_probe()