Lines Matching +full:stacked +full:- +full:memories
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
31 * This is a driver for the Quad-SPI Flash Controller in the Xilinx
32 * Zynq-7000 SoC.
64 {"xlnx,zynq-qspi-1.0", 1},
98 #define QSPI_SC_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
99 #define QSPI_SC_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
101 mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), NULL, MTX_DEF)
102 #define QSPI_SC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
103 #define QSPI_SC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
105 #define RD4(sc, off) (bus_read_4((sc)->mem_res, (off)))
106 #define WR4(sc, off, val) (bus_write_4((sc)->mem_res, (off), (val)))
110 * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
232 if (sc->tx_bytes_sent < sc->cmd->tx_cmd_sz) {
234 n = MIN(nvalid, sc->cmd->tx_cmd_sz -
235 sc->tx_bytes_sent);
236 memcpy(&data, (uint8_t *)sc->cmd->tx_cmd +
237 sc->tx_bytes_sent, n);
242 sc->cmd->tx_data, nvalid - n);
246 memcpy(&data, (uint8_t *)sc->cmd->tx_data +
247 (sc->tx_bytes_sent - sc->cmd->tx_cmd_sz), nvalid);
264 sc->tx_bytes_sent += nvalid;
265 nbytes -= nvalid;
278 nbytes = MIN(4, sc->rx_bytes - sc->rx_bytes_rcvd);
281 * Last word in non-word-multiple transfer is packed
282 * non-intuitively.
285 data >>= 8 * (4 - nbytes);
287 if (sc->rx_bytes_rcvd < sc->cmd->rx_cmd_sz) {
289 n = MIN(nbytes, sc->cmd->rx_cmd_sz -
290 sc->rx_bytes_rcvd);
291 memcpy((uint8_t *)sc->cmd->rx_cmd + sc->rx_bytes_rcvd,
293 sc->rx_bytes_rcvd += n;
294 nbytes -= n;
300 memcpy((uint8_t *)sc->cmd->rx_data +
301 (sc->rx_bytes_rcvd - sc->cmd->rx_cmd_sz),
303 sc->rx_bytes_rcvd += nbytes;
306 } while (sc->rx_bytes_rcvd < sc->rx_bytes &&
335 sc->interrupts++;
340 if (!sc->busy) {
341 sc->stray_ints++;
347 device_printf(sc->dev, "rx fifo overflow!\n");
348 sc->rx_overflows++;
356 if (sc->rx_bytes_rcvd < sc->rx_bytes &&
359 if (sc->rx_bytes_rcvd == sc->rx_bytes)
372 sc->tx_underflows++;
380 if (sc->tx_bytes_sent < sc->tx_bytes &&
382 zy7_qspi_write_fifo(sc, MIN(240, sc->tx_bytes -
383 sc->tx_bytes_sent));
385 if (sc->tx_bytes_sent == sc->tx_bytes) {
398 if (sc->tx_bytes_sent == sc->tx_bytes &&
399 sc->rx_bytes_rcvd == sc->rx_bytes) {
400 /* De-assert CS. */
401 sc->cfg_reg_shadow |= ZY7_QSPI_CONFIG_PCS;
402 WR4(sc, ZY7_QSPI_CONFIG_REG, sc->cfg_reg_shadow);
404 wakeup(sc->dev);
417 sc->lqspi_cfg_shadow = RD4(sc, ZY7_QSPI_LQSPI_CFG_REG);
418 sc->lqspi_cfg_shadow &= ~(ZY7_QSPI_LQSPI_CFG_LINEAR |
421 if (sc->is_dual) {
422 sc->lqspi_cfg_shadow |= ZY7_QSPI_LQSPI_CFG_TWO_MEM;
423 if (sc->is_stacked) {
424 sc->lqspi_cfg_shadow &=
426 sc->lqspi_cfg_shadow |=
427 ZY7_QSPI_LQSPI_CFG_INST_CODE(sc->is_dio ?
430 sc->lqspi_cfg_shadow |= ZY7_QSPI_LQSPI_CFG_SEP_BUS;
432 WR4(sc, ZY7_QSPI_LQSPI_CFG_REG, sc->lqspi_cfg_shadow);
436 while ((sc->ref_clock >> (baud_div + 1)) > sc->spi_clock &&
440 device_printf(sc->dev, "cannot configure clock divider: ref=%d"
441 " spi=%d.\n", sc->ref_clock, sc->spi_clock);
444 sc->spi_clk_real_freq = sc->ref_clock >> (baud_div + 1);
459 sc->cfg_reg_shadow =
468 WR4(sc, ZY7_QSPI_CONFIG_REG, sc->cfg_reg_shadow);
499 &sc->spi_clk_real_freq, 0, "SPI clock real frequency");
502 &sc->rx_overflows, 0, "RX FIFO overflow events");
505 &sc->tx_underflows, 0, "TX FIFO underflow events");
508 &sc->interrupts, 0, "interrupt calls");
511 &sc->stray_ints, 0, "stray interrupts");
521 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
524 device_set_desc(dev, "Zynq Quad-SPI Flash Controller");
538 sc->dev = dev;
542 /* Get ref-clock, spi-clock, and other properties. */
544 if (OF_getprop(node, "ref-clock", &cell, sizeof(cell)) > 0)
545 sc->ref_clock = fdt32_to_cpu(cell);
547 device_printf(dev, "must have ref-clock property\n");
550 if (OF_getprop(node, "spi-clock", &cell, sizeof(cell)) > 0)
551 sc->spi_clock = fdt32_to_cpu(cell);
553 sc->spi_clock = ZY7_QSPI_DEFAULT_SPI_CLOCK;
554 if (OF_getprop(node, "is-stacked", &cell, sizeof(cell)) > 0 &&
556 sc->is_dual = 1;
557 sc->is_stacked = 1;
558 } else if (OF_getprop(node, "is-dual", &cell, sizeof(cell)) > 0 &&
560 sc->is_dual = 1;
561 if (OF_getprop(node, "is-dio", &cell, sizeof(cell)) > 0 &&
563 sc->is_dio = 1;
567 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
569 if (sc->mem_res == NULL) {
577 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
579 if (sc->irq_res == NULL) {
586 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
587 NULL, zy7_qspi_intr, sc, &sc->intrhandle);
601 sc->child = device_add_child(dev, "spibus", DEVICE_UNIT_ANY);
622 if (sc->mem_res != NULL) {
632 if (sc->irq_res != NULL) {
633 if (sc->intrhandle)
634 bus_teardown_intr(dev, sc->irq_res, sc->intrhandle);
636 rman_get_rid(sc->irq_res), sc->irq_res);
640 if (sc->mem_res != NULL)
642 rman_get_rid(sc->mem_res), sc->mem_res);
662 KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
664 KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
667 if (sc->is_dual && cmd->tx_data_sz % 2 != 0) {
669 "transfers in dual mode. (sz=%d)\n", cmd->tx_data_sz);
676 while (sc->busy != 0) {
677 err = mtx_sleep(dev, &sc->sc_mtx, 0, "zqspi0", 0);
685 sc->busy = 1;
686 sc->cmd = cmd;
687 sc->tx_bytes = sc->cmd->tx_cmd_sz + sc->cmd->tx_data_sz;
688 sc->tx_bytes_sent = 0;
689 sc->rx_bytes = sc->cmd->rx_cmd_sz + sc->cmd->rx_data_sz;
690 sc->rx_bytes_rcvd = 0;
697 #ifdef SPI_XFER_U_PAGE /* XXX: future support for stacked memories. */
698 if (sc->is_stacked) {
699 if ((cmd->flags & SPI_XFER_U_PAGE) != 0)
700 sc->lqspi_cfg_shadow |= ZY7_QSPI_LQSPI_CFG_U_PAGE;
702 sc->lqspi_cfg_shadow &= ~ZY7_QSPI_LQSPI_CFG_U_PAGE;
703 WR4(sc, ZY7_QSPI_LQSPI_CFG_REG, sc->lqspi_cfg_shadow);
708 sc->cfg_reg_shadow &= ~ZY7_QSPI_CONFIG_PCS;
709 WR4(sc, ZY7_QSPI_CONFIG_REG, sc->cfg_reg_shadow);
712 err = mtx_sleep(dev, &sc->sc_mtx, 0, "zqspi1", hz * 2);
717 sc->busy = 0;