Lines Matching +full:zynq +full:- +full:can +full:- +full:1
1 /*-
8 * 1. Redistributions of source code must retain the above copyright
53 {"xlnx,zy7_spi", 1},
54 {"xlnx,zynq-spi-1.0", 1},
55 {"cdns,spi-r1p6", 1},
85 #define SPI_SC_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
86 #define SPI_SC_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
88 mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), NULL, MTX_DEF)
89 #define SPI_SC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
90 #define SPI_SC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
92 #define RD4(sc, off) (bus_read_4((sc)->mem_res, (off)))
93 #define WR4(sc, off, val) (bus_write_4((sc)->mem_res, (off), (val)))
97 * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
101 #define ZY7_SPI_CONFIG_MODEFAIL_GEN_EN (1 << 17)
102 #define ZY7_SPI_CONFIG_MAN_STRT (1 << 16)
103 #define ZY7_SPI_CONFIG_MAN_STRT_EN (1 << 15)
104 #define ZY7_SPI_CONFIG_MAN_CS (1 << 14)
106 #define ZY7_SPI_CONFIG_CS(x) ((0xf ^ (1 << (x))) << 10)
107 #define ZY7_SPI_CONFIG_PERI_SEL (1 << 9)
108 #define ZY7_SPI_CONFIG_REF_CLK (1 << 8)
112 #define ZY7_SPI_CONFIG_CLK_PH (1 << 2) /* clock phase */
113 #define ZY7_SPI_CONFIG_CLK_POL (1 << 1) /* clock polatiry */
114 #define ZY7_SPI_CONFIG_MODE_SEL (1 << 0) /* master enable */
120 #define ZY7_SPI_INTR_TX_FIFO_UNDERFLOW (1 << 6)
121 #define ZY7_SPI_INTR_RX_FIFO_FULL (1 << 5)
122 #define ZY7_SPI_INTR_RX_FIFO_NOT_EMPTY (1 << 4)
123 #define ZY7_SPI_INTR_TX_FIFO_FULL (1 << 3)
124 #define ZY7_SPI_INTR_TX_FIFO_NOT_FULL (1 << 2)
125 #define ZY7_SPI_INTR_MODE_FAULT (1 << 1)
126 #define ZY7_SPI_INTR_RX_OVERFLOW (1 << 0)
129 #define ZY7_SPI_ENABLE (1 << 0)
154 if (sc->tx_bytes_sent < sc->cmd->tx_cmd_sz) in zy7_spi_write_fifo()
156 byte = *((uint8_t *)sc->cmd->tx_cmd + in zy7_spi_write_fifo()
157 sc->tx_bytes_sent); in zy7_spi_write_fifo()
160 byte = *((uint8_t *)sc->cmd->tx_data + in zy7_spi_write_fifo()
161 (sc->tx_bytes_sent - sc->cmd->tx_cmd_sz)); in zy7_spi_write_fifo()
165 sc->tx_bytes_sent++; in zy7_spi_write_fifo()
166 nbytes--; in zy7_spi_write_fifo()
179 if (sc->rx_bytes_rcvd < sc->cmd->rx_cmd_sz) in zy7_spi_read_fifo()
181 *((uint8_t *)sc->cmd->rx_cmd + sc->rx_bytes_rcvd) = in zy7_spi_read_fifo()
185 *((uint8_t *)sc->cmd->rx_data + in zy7_spi_read_fifo()
186 (sc->rx_bytes_rcvd - sc->cmd->rx_cmd_sz)) = in zy7_spi_read_fifo()
189 sc->rx_bytes_rcvd++; in zy7_spi_read_fifo()
191 } while (sc->rx_bytes_rcvd < sc->rx_bytes && in zy7_spi_read_fifo()
220 sc->interrupts++; in zy7_spi_intr()
224 /* Stray interrupts can happen if a transfer gets interrupted. */ in zy7_spi_intr()
225 if (!sc->busy) { in zy7_spi_intr()
226 sc->stray_ints++; in zy7_spi_intr()
232 device_printf(sc->dev, "rx fifo overflow!\n"); in zy7_spi_intr()
233 sc->rx_overflows++; in zy7_spi_intr()
241 if (sc->rx_bytes_rcvd < sc->rx_bytes && in zy7_spi_intr()
244 if (sc->rx_bytes_rcvd == sc->rx_bytes) in zy7_spi_intr()
253 sc->tx_underflows++; in zy7_spi_intr()
261 if (sc->tx_bytes_sent < sc->tx_bytes && in zy7_spi_intr()
263 zy7_spi_write_fifo(sc, MIN(96, sc->tx_bytes - in zy7_spi_intr()
264 sc->tx_bytes_sent)); in zy7_spi_intr()
266 if (sc->tx_bytes_sent == sc->tx_bytes) { in zy7_spi_intr()
278 if (sc->tx_bytes_sent == sc->tx_bytes && in zy7_spi_intr()
279 sc->rx_bytes_rcvd == sc->rx_bytes) { in zy7_spi_intr()
280 /* De-assert CS. */ in zy7_spi_intr()
281 sc->cfg_reg_shadow &= in zy7_spi_intr()
283 sc->cfg_reg_shadow |= ZY7_SPI_CONFIG_CS_MASK; in zy7_spi_intr()
284 WR4(sc, ZY7_SPI_CONFIG_REG, sc->cfg_reg_shadow); in zy7_spi_intr()
286 wakeup(sc->dev); in zy7_spi_intr()
299 baud_div = 1; in zy7_spi_init_hw()
300 while ((sc->ref_clock >> (baud_div + 1)) > sc->spi_clock && in zy7_spi_init_hw()
304 device_printf(sc->dev, "cannot configure clock divider: ref=%d" in zy7_spi_init_hw()
305 " spi=%d.\n", sc->ref_clock, sc->spi_clock); in zy7_spi_init_hw()
308 sc->spi_clk_real_freq = sc->ref_clock >> (baud_div + 1); in zy7_spi_init_hw()
311 sc->cfg_reg_shadow = in zy7_spi_init_hw()
316 WR4(sc, ZY7_SPI_CONFIG_REG, sc->cfg_reg_shadow); in zy7_spi_init_hw()
320 WR4(sc, ZY7_SPI_RX_THRESH_REG, 1); in zy7_spi_init_hw()
343 &sc->spi_clk_real_freq, 0, "SPI clock real frequency"); in zy7_spi_add_sysctls()
346 &sc->rx_overflows, 0, "RX FIFO overflow events"); in zy7_spi_add_sysctls()
349 &sc->tx_underflows, 0, "TX FIFO underflow events"); in zy7_spi_add_sysctls()
352 &sc->interrupts, 0, "interrupt calls"); in zy7_spi_add_sysctls()
355 &sc->stray_ints, 0, "stray interrupts"); in zy7_spi_add_sysctls()
365 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) in zy7_spi_probe()
368 device_set_desc(dev, "Zynq SPI Controller"); in zy7_spi_probe()
384 sc->dev = dev; in zy7_spi_attach()
388 /* Get ref-clock and spi-clock properties. */ in zy7_spi_attach()
390 if (OF_getprop(node, "ref-clock", &cell, sizeof(cell)) > 0) in zy7_spi_attach()
391 sc->ref_clock = fdt32_to_cpu(cell); in zy7_spi_attach()
393 device_printf(dev, "must have ref-clock property\n"); in zy7_spi_attach()
396 if (OF_getprop(node, "spi-clock", &cell, sizeof(cell)) > 0) in zy7_spi_attach()
397 sc->spi_clock = fdt32_to_cpu(cell); in zy7_spi_attach()
399 sc->spi_clock = ZY7_SPI_DEFAULT_SPI_CLOCK; in zy7_spi_attach()
403 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, in zy7_spi_attach()
405 if (sc->mem_res == NULL) { in zy7_spi_attach()
413 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, in zy7_spi_attach()
415 if (sc->irq_res == NULL) { in zy7_spi_attach()
422 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, in zy7_spi_attach()
423 NULL, zy7_spi_intr, sc, &sc->intrhandle); in zy7_spi_attach()
437 sc->child = device_add_child(dev, "spibus", DEVICE_UNIT_ANY); in zy7_spi_attach()
458 if (sc->mem_res != NULL) { in zy7_spi_detach()
468 if (sc->irq_res != NULL) { in zy7_spi_detach()
469 if (sc->intrhandle) in zy7_spi_detach()
470 bus_teardown_intr(dev, sc->irq_res, sc->intrhandle); in zy7_spi_detach()
472 rman_get_rid(sc->irq_res), sc->irq_res); in zy7_spi_detach()
476 if (sc->mem_res != NULL) in zy7_spi_detach()
478 rman_get_rid(sc->mem_res), sc->mem_res); in zy7_spi_detach()
500 KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, in zy7_spi_transfer()
502 KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, in zy7_spi_transfer()
518 while (sc->busy != 0) { in zy7_spi_transfer()
519 err = mtx_sleep(dev, &sc->sc_mtx, 0, "zspi0", 0); in zy7_spi_transfer()
527 sc->busy = 1; in zy7_spi_transfer()
528 sc->cmd = cmd; in zy7_spi_transfer()
529 sc->tx_bytes = sc->cmd->tx_cmd_sz + sc->cmd->tx_data_sz; in zy7_spi_transfer()
530 sc->tx_bytes_sent = 0; in zy7_spi_transfer()
531 sc->rx_bytes = sc->cmd->rx_cmd_sz + sc->cmd->rx_data_sz; in zy7_spi_transfer()
532 sc->rx_bytes_rcvd = 0; in zy7_spi_transfer()
541 sc->cfg_reg_shadow |= ZY7_SPI_CONFIG_CLK_PH; in zy7_spi_transfer()
543 sc->cfg_reg_shadow |= ZY7_SPI_CONFIG_CLK_POL; in zy7_spi_transfer()
546 sc->cfg_reg_shadow &= ~ZY7_SPI_CONFIG_CS_MASK; in zy7_spi_transfer()
547 sc->cfg_reg_shadow |= ZY7_SPI_CONFIG_CS(cs); in zy7_spi_transfer()
548 WR4(sc, ZY7_SPI_CONFIG_REG, sc->cfg_reg_shadow); in zy7_spi_transfer()
551 err = mtx_sleep(dev, &sc->sc_mtx, 0, "zspi1", hz * 2); in zy7_spi_transfer()
556 sc->busy = 0; in zy7_spi_transfer()
588 MODULE_DEPEND(zy7_spi, ofw_spibus, 1, 1, 1);