Lines Matching +full:axi +full:- +full:spi +full:- +full:engine +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0-only
3 * SPI-Engine SPI controller driver
6 * Author: Lars-Peter Clausen <lars@metafoo.de>
14 #include <linux/fpga/adi-axi-common.h>
21 #include <linux/spi/offload/provider.h>
22 #include <linux/spi/spi.h>
23 #include <trace/events/spi.h>
56 #define SPI_ENGINE_INT_SDO_ALMOST_EMPTY BIT(1)
64 #define SPI_ENGINE_CONFIG_CPOL BIT(1)
84 /* Arbitrary sync ID for use by host->cur_msg */
103 /* default sizes - can be changed when SPI Engine firmware is compiled */
113 * struct spi_engine_message_state - SPI engine per-message state
167 p->length++; in spi_engine_program_add_cmd()
170 p->instructions[p->length - 1] = cmd; in spi_engine_program_add_cmd()
173 static unsigned int spi_engine_get_config(struct spi_device *spi) in spi_engine_get_config() argument
177 if (spi->mode & SPI_CPOL) in spi_engine_get_config()
179 if (spi->mode & SPI_CPHA) in spi_engine_get_config()
181 if (spi->mode & SPI_3WIRE) in spi_engine_get_config()
183 if (spi->mode & SPI_MOSI_IDLE_HIGH) in spi_engine_get_config()
185 if (spi->mode & SPI_MOSI_IDLE_LOW) in spi_engine_get_config()
196 if (xfer->bits_per_word <= 8) in spi_engine_gen_xfer()
197 len = xfer->len; in spi_engine_gen_xfer()
198 else if (xfer->bits_per_word <= 16) in spi_engine_gen_xfer()
199 len = xfer->len / 2; in spi_engine_gen_xfer()
201 len = xfer->len / 4; in spi_engine_gen_xfer()
207 if (xfer->tx_buf || (xfer->offload_flags & SPI_OFFLOAD_XFER_TX_STREAM)) in spi_engine_gen_xfer()
209 if (xfer->rx_buf || (xfer->offload_flags & SPI_OFFLOAD_XFER_RX_STREAM)) in spi_engine_gen_xfer()
213 SPI_ENGINE_CMD_TRANSFER(flags, n - 1)); in spi_engine_gen_xfer()
214 len -= n; in spi_engine_gen_xfer()
232 t = DIV_ROUND_UP_ULL((u64)(delay_ns - inst_ns) * sclk_hz, NSEC_PER_SEC); in spi_engine_gen_sleep()
236 spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_SLEEP(n - 1)); in spi_engine_gen_sleep()
237 t -= n; in spi_engine_gen_sleep()
242 struct spi_device *spi, bool assert) in spi_engine_gen_cs() argument
247 mask ^= BIT(spi_get_chipselect(spi, 0)); in spi_engine_gen_cs()
255 * The SPI core does most of the message/transfer validation and filling in
260 * is called twice and would otherwise result in double-evaluation.
262 * Returns 0 on success, -EINVAL on failure.
266 unsigned int clk_div, max_hz = msg->spi->controller->max_speed_hz; in spi_engine_precompile_message()
269 list_for_each_entry(xfer, &msg->transfers, transfer_list) { in spi_engine_precompile_message()
271 if (msg->offload && xfer->rx_buf) in spi_engine_precompile_message()
272 return -EINVAL; in spi_engine_precompile_message()
274 clk_div = DIV_ROUND_UP(max_hz, xfer->speed_hz); in spi_engine_precompile_message()
275 xfer->effective_speed_hz = max_hz / min(clk_div, 256U); in spi_engine_precompile_message()
284 struct spi_device *spi = msg->spi; in spi_engine_compile_message() local
285 struct spi_controller *host = spi->controller; in spi_engine_compile_message()
295 inst_ns = DIV_ROUND_UP(NSEC_PER_SEC, host->max_speed_hz); in spi_engine_compile_message()
297 clk_div = 1; in spi_engine_compile_message()
301 spi_engine_get_config(spi))); in spi_engine_compile_message()
303 xfer = list_first_entry(&msg->transfers, struct spi_transfer, transfer_list); in spi_engine_compile_message()
304 spi_engine_gen_cs(p, dry, spi, !xfer->cs_off); in spi_engine_compile_message()
306 list_for_each_entry(xfer, &msg->transfers, transfer_list) { in spi_engine_compile_message()
307 new_clk_div = host->max_speed_hz / xfer->effective_speed_hz; in spi_engine_compile_message()
310 /* actual divider used is register value + 1 */ in spi_engine_compile_message()
313 clk_div - 1)); in spi_engine_compile_message()
316 if (bits_per_word != xfer->bits_per_word && xfer->len) { in spi_engine_compile_message()
317 bits_per_word = xfer->bits_per_word; in spi_engine_compile_message()
324 spi_engine_gen_sleep(p, dry, spi_delay_to_ns(&xfer->delay, xfer), in spi_engine_compile_message()
325 inst_ns, xfer->effective_speed_hz); in spi_engine_compile_message()
327 if (xfer->cs_change) { in spi_engine_compile_message()
328 if (list_is_last(&xfer->transfer_list, &msg->transfers)) { in spi_engine_compile_message()
331 if (!xfer->cs_off) in spi_engine_compile_message()
332 spi_engine_gen_cs(p, dry, spi, false); in spi_engine_compile_message()
335 &xfer->cs_change_delay, xfer), inst_ns, in spi_engine_compile_message()
336 xfer->effective_speed_hz); in spi_engine_compile_message()
338 if (!list_next_entry(xfer, transfer_list)->cs_off) in spi_engine_compile_message()
339 spi_engine_gen_cs(p, dry, spi, true); in spi_engine_compile_message()
341 } else if (!list_is_last(&xfer->transfer_list, &msg->transfers) && in spi_engine_compile_message()
342 xfer->cs_off != list_next_entry(xfer, transfer_list)->cs_off) { in spi_engine_compile_message()
343 spi_engine_gen_cs(p, dry, spi, xfer->cs_off); in spi_engine_compile_message()
348 spi_engine_gen_cs(p, dry, spi, false); in spi_engine_compile_message()
354 if (clk_div != 1) in spi_engine_compile_message()
365 xfer = list_first_entry(&msg->transfers, in spi_engine_xfer_next()
367 } else if (list_is_last(&xfer->transfer_list, &msg->transfers)) { in spi_engine_xfer_next()
378 struct spi_engine_message_state *st = msg->state; in spi_engine_tx_next()
379 struct spi_transfer *xfer = st->tx_xfer; in spi_engine_tx_next()
383 } while (xfer && !xfer->tx_buf); in spi_engine_tx_next()
385 st->tx_xfer = xfer; in spi_engine_tx_next()
387 st->tx_length = xfer->len; in spi_engine_tx_next()
388 st->tx_buf = xfer->tx_buf; in spi_engine_tx_next()
390 st->tx_buf = NULL; in spi_engine_tx_next()
396 struct spi_engine_message_state *st = msg->state; in spi_engine_rx_next()
397 struct spi_transfer *xfer = st->rx_xfer; in spi_engine_rx_next()
401 } while (xfer && !xfer->rx_buf); in spi_engine_rx_next()
403 st->rx_xfer = xfer; in spi_engine_rx_next()
405 st->rx_length = xfer->len; in spi_engine_rx_next()
406 st->rx_buf = xfer->rx_buf; in spi_engine_rx_next()
408 st->rx_buf = NULL; in spi_engine_rx_next()
415 void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_CMD_FIFO; in spi_engine_write_cmd_fifo()
416 struct spi_engine_message_state *st = msg->state; in spi_engine_write_cmd_fifo()
420 n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_CMD_FIFO_ROOM); in spi_engine_write_cmd_fifo()
421 while (n && st->cmd_length) { in spi_engine_write_cmd_fifo()
422 m = min(n, st->cmd_length); in spi_engine_write_cmd_fifo()
423 buf = st->cmd_buf; in spi_engine_write_cmd_fifo()
426 st->cmd_buf += m; in spi_engine_write_cmd_fifo()
427 st->cmd_length -= m; in spi_engine_write_cmd_fifo()
428 n -= m; in spi_engine_write_cmd_fifo()
431 return st->cmd_length != 0; in spi_engine_write_cmd_fifo()
437 void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDO_DATA_FIFO; in spi_engine_write_tx_fifo()
438 struct spi_engine_message_state *st = msg->state; in spi_engine_write_tx_fifo()
441 n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDO_FIFO_ROOM); in spi_engine_write_tx_fifo()
442 while (n && st->tx_length) { in spi_engine_write_tx_fifo()
443 if (st->tx_xfer->bits_per_word <= 8) { in spi_engine_write_tx_fifo()
444 const u8 *buf = st->tx_buf; in spi_engine_write_tx_fifo()
446 m = min(n, st->tx_length); in spi_engine_write_tx_fifo()
449 st->tx_buf += m; in spi_engine_write_tx_fifo()
450 st->tx_length -= m; in spi_engine_write_tx_fifo()
451 } else if (st->tx_xfer->bits_per_word <= 16) { in spi_engine_write_tx_fifo()
452 const u16 *buf = (const u16 *)st->tx_buf; in spi_engine_write_tx_fifo()
454 m = min(n, st->tx_length / 2); in spi_engine_write_tx_fifo()
457 st->tx_buf += m * 2; in spi_engine_write_tx_fifo()
458 st->tx_length -= m * 2; in spi_engine_write_tx_fifo()
460 const u32 *buf = (const u32 *)st->tx_buf; in spi_engine_write_tx_fifo()
462 m = min(n, st->tx_length / 4); in spi_engine_write_tx_fifo()
465 st->tx_buf += m * 4; in spi_engine_write_tx_fifo()
466 st->tx_length -= m * 4; in spi_engine_write_tx_fifo()
468 n -= m; in spi_engine_write_tx_fifo()
469 if (st->tx_length == 0) in spi_engine_write_tx_fifo()
473 return st->tx_length != 0; in spi_engine_write_tx_fifo()
479 void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDI_DATA_FIFO; in spi_engine_read_rx_fifo()
480 struct spi_engine_message_state *st = msg->state; in spi_engine_read_rx_fifo()
483 n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDI_FIFO_LEVEL); in spi_engine_read_rx_fifo()
484 while (n && st->rx_length) { in spi_engine_read_rx_fifo()
485 if (st->rx_xfer->bits_per_word <= 8) { in spi_engine_read_rx_fifo()
486 u8 *buf = st->rx_buf; in spi_engine_read_rx_fifo()
488 m = min(n, st->rx_length); in spi_engine_read_rx_fifo()
491 st->rx_buf += m; in spi_engine_read_rx_fifo()
492 st->rx_length -= m; in spi_engine_read_rx_fifo()
493 } else if (st->rx_xfer->bits_per_word <= 16) { in spi_engine_read_rx_fifo()
494 u16 *buf = (u16 *)st->rx_buf; in spi_engine_read_rx_fifo()
496 m = min(n, st->rx_length / 2); in spi_engine_read_rx_fifo()
499 st->rx_buf += m * 2; in spi_engine_read_rx_fifo()
500 st->rx_length -= m * 2; in spi_engine_read_rx_fifo()
502 u32 *buf = (u32 *)st->rx_buf; in spi_engine_read_rx_fifo()
504 m = min(n, st->rx_length / 4); in spi_engine_read_rx_fifo()
507 st->rx_buf += m * 4; in spi_engine_read_rx_fifo()
508 st->rx_length -= m * 4; in spi_engine_read_rx_fifo()
510 n -= m; in spi_engine_read_rx_fifo()
511 if (st->rx_length == 0) in spi_engine_read_rx_fifo()
515 return st->rx_length != 0; in spi_engine_read_rx_fifo()
521 struct spi_message *msg = host->cur_msg; in spi_engine_irq()
525 int completed_id = -1; in spi_engine_irq()
527 pending = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_INT_PENDING); in spi_engine_irq()
531 spi_engine->base + SPI_ENGINE_REG_INT_PENDING); in spi_engine_irq()
533 spi_engine->base + SPI_ENGINE_REG_SYNC_ID); in spi_engine_irq()
536 spin_lock(&spi_engine->lock); in spi_engine_irq()
555 msg->status = 0; in spi_engine_irq()
556 msg->actual_length = msg->frame_length; in spi_engine_irq()
557 complete(&spi_engine->msg_complete); in spi_engine_irq()
563 spi_engine->int_enable &= ~disable_int; in spi_engine_irq()
564 writel_relaxed(spi_engine->int_enable, in spi_engine_irq()
565 spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); in spi_engine_irq()
568 spin_unlock(&spi_engine->lock); in spi_engine_irq()
575 struct spi_controller *host = msg->spi->controller; in spi_engine_offload_prepare()
577 struct spi_engine_program *p = msg->opt_state; in spi_engine_offload_prepare()
578 struct spi_engine_offload *priv = msg->offload->priv; in spi_engine_offload_prepare()
585 if (p->length > spi_engine->offload_ctrl_mem_size) in spi_engine_offload_prepare()
586 return -EINVAL; in spi_engine_offload_prepare()
589 list_for_each_entry(xfer, &msg->transfers, transfer_list) { in spi_engine_offload_prepare()
591 if (xfer->rx_buf) in spi_engine_offload_prepare()
592 return -EINVAL; in spi_engine_offload_prepare()
594 if (!xfer->tx_buf) in spi_engine_offload_prepare()
597 if (xfer->bits_per_word <= 8) in spi_engine_offload_prepare()
598 tx_word_count += xfer->len; in spi_engine_offload_prepare()
599 else if (xfer->bits_per_word <= 16) in spi_engine_offload_prepare()
600 tx_word_count += xfer->len / 2; in spi_engine_offload_prepare()
602 tx_word_count += xfer->len / 4; in spi_engine_offload_prepare()
605 if (tx_word_count && !(spi_engine->offload_caps & SPI_OFFLOAD_CAP_TX_STATIC_DATA)) in spi_engine_offload_prepare()
606 return -EINVAL; in spi_engine_offload_prepare()
608 if (tx_word_count > spi_engine->offload_sdo_mem_size) in spi_engine_offload_prepare()
609 return -EINVAL; in spi_engine_offload_prepare()
615 if (test_and_set_bit_lock(SPI_ENGINE_OFFLOAD_FLAG_PREPARED, &priv->flags)) in spi_engine_offload_prepare()
616 return -EBUSY; in spi_engine_offload_prepare()
618 cmd_addr = spi_engine->base + in spi_engine_offload_prepare()
619 SPI_ENGINE_REG_OFFLOAD_CMD_FIFO(priv->offload_num); in spi_engine_offload_prepare()
620 sdo_addr = spi_engine->base + in spi_engine_offload_prepare()
621 SPI_ENGINE_REG_OFFLOAD_SDO_FIFO(priv->offload_num); in spi_engine_offload_prepare()
623 list_for_each_entry(xfer, &msg->transfers, transfer_list) { in spi_engine_offload_prepare()
624 if (!xfer->tx_buf) in spi_engine_offload_prepare()
627 if (xfer->bits_per_word <= 8) { in spi_engine_offload_prepare()
628 const u8 *buf = xfer->tx_buf; in spi_engine_offload_prepare()
630 for (i = 0; i < xfer->len; i++) in spi_engine_offload_prepare()
632 } else if (xfer->bits_per_word <= 16) { in spi_engine_offload_prepare()
633 const u16 *buf = xfer->tx_buf; in spi_engine_offload_prepare()
635 for (i = 0; i < xfer->len / 2; i++) in spi_engine_offload_prepare()
638 const u32 *buf = xfer->tx_buf; in spi_engine_offload_prepare()
640 for (i = 0; i < xfer->len / 4; i++) in spi_engine_offload_prepare()
645 for (i = 0; i < p->length; i++) in spi_engine_offload_prepare()
646 writel_relaxed(p->instructions[i], cmd_addr); in spi_engine_offload_prepare()
653 struct spi_engine_offload *priv = offload->priv; in spi_engine_offload_unprepare()
654 struct spi_engine *spi_engine = priv->spi_engine; in spi_engine_offload_unprepare()
656 writel_relaxed(1, spi_engine->base + in spi_engine_offload_unprepare()
657 SPI_ENGINE_REG_OFFLOAD_RESET(priv->offload_num)); in spi_engine_offload_unprepare()
658 writel_relaxed(0, spi_engine->base + in spi_engine_offload_unprepare()
659 SPI_ENGINE_REG_OFFLOAD_RESET(priv->offload_num)); in spi_engine_offload_unprepare()
661 clear_bit_unlock(SPI_ENGINE_OFFLOAD_FLAG_PREPARED, &priv->flags); in spi_engine_offload_unprepare()
676 p = kzalloc(struct_size(p, instructions, p_dry.length + 1), GFP_KERNEL); in spi_engine_optimize_message()
678 return -ENOMEM; in spi_engine_optimize_message()
683 msg->offload ? 0 : AXI_SPI_ENGINE_CUR_MSG_SYNC_ID)); in spi_engine_optimize_message()
685 msg->opt_state = p; in spi_engine_optimize_message()
687 if (msg->offload) { in spi_engine_optimize_message()
690 msg->opt_state = NULL; in spi_engine_optimize_message()
701 if (msg->offload) in spi_engine_unoptimize_message()
702 spi_engine_offload_unprepare(msg->offload); in spi_engine_unoptimize_message()
704 kfree(msg->opt_state); in spi_engine_unoptimize_message()
710 *spi_engine_get_offload(struct spi_device *spi, in spi_engine_get_offload() argument
713 struct spi_controller *host = spi->controller; in spi_engine_get_offload()
717 if (!spi_engine->offload) in spi_engine_get_offload()
718 return ERR_PTR(-ENODEV); in spi_engine_get_offload()
720 if (config->capability_flags & ~spi_engine->offload_caps) in spi_engine_get_offload()
721 return ERR_PTR(-EINVAL); in spi_engine_get_offload()
723 priv = spi_engine->offload->priv; in spi_engine_get_offload()
725 if (test_and_set_bit_lock(SPI_ENGINE_OFFLOAD_FLAG_ASSIGNED, &priv->flags)) in spi_engine_get_offload()
726 return ERR_PTR(-EBUSY); in spi_engine_get_offload()
728 return spi_engine->offload; in spi_engine_get_offload()
733 struct spi_engine_offload *priv = offload->priv; in spi_engine_put_offload()
735 clear_bit_unlock(SPI_ENGINE_OFFLOAD_FLAG_ASSIGNED, &priv->flags); in spi_engine_put_offload()
740 struct spi_controller *host = device->controller; in spi_engine_setup()
743 if (device->mode & SPI_CS_HIGH) in spi_engine_setup()
744 spi_engine->cs_inv |= BIT(spi_get_chipselect(device, 0)); in spi_engine_setup()
746 spi_engine->cs_inv &= ~BIT(spi_get_chipselect(device, 0)); in spi_engine_setup()
748 writel_relaxed(SPI_ENGINE_CMD_CS_INV(spi_engine->cs_inv), in spi_engine_setup()
749 spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); in spi_engine_setup()
756 spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); in spi_engine_setup()
765 struct spi_engine_message_state *st = &spi_engine->msg_state; in spi_engine_transfer_one_message()
766 struct spi_engine_program *p = msg->opt_state; in spi_engine_transfer_one_message()
770 if (msg->offload) { in spi_engine_transfer_one_message()
771 dev_err(&host->dev, "Single transfer offload not supported\n"); in spi_engine_transfer_one_message()
772 msg->status = -EOPNOTSUPP; in spi_engine_transfer_one_message()
778 st->cmd_buf = p->instructions; in spi_engine_transfer_one_message()
779 st->cmd_length = p->length; in spi_engine_transfer_one_message()
780 msg->state = st; in spi_engine_transfer_one_message()
782 reinit_completion(&spi_engine->msg_complete); in spi_engine_transfer_one_message()
787 list_for_each_entry(xfer, &msg->transfers, transfer_list) in spi_engine_transfer_one_message()
791 spin_lock_irqsave(&spi_engine->lock, flags); in spi_engine_transfer_one_message()
801 if (st->rx_length != 0) in spi_engine_transfer_one_message()
807 spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); in spi_engine_transfer_one_message()
808 spi_engine->int_enable = int_enable; in spi_engine_transfer_one_message()
809 spin_unlock_irqrestore(&spi_engine->lock, flags); in spi_engine_transfer_one_message()
811 if (!wait_for_completion_timeout(&spi_engine->msg_complete, in spi_engine_transfer_one_message()
813 dev_err(&host->dev, in spi_engine_transfer_one_message()
815 msg->status = -ETIMEDOUT; in spi_engine_transfer_one_message()
821 list_for_each_entry(xfer, &msg->transfers, transfer_list) in spi_engine_transfer_one_message()
828 return msg->status; in spi_engine_transfer_one_message()
833 struct spi_engine_offload *priv = offload->priv; in spi_engine_trigger_enable()
834 struct spi_engine *spi_engine = priv->spi_engine; in spi_engine_trigger_enable()
837 reg = readl_relaxed(spi_engine->base + in spi_engine_trigger_enable()
838 SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num)); in spi_engine_trigger_enable()
840 writel_relaxed(reg, spi_engine->base + in spi_engine_trigger_enable()
841 SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num)); in spi_engine_trigger_enable()
847 struct spi_engine_offload *priv = offload->priv; in spi_engine_trigger_disable()
848 struct spi_engine *spi_engine = priv->spi_engine; in spi_engine_trigger_disable()
851 reg = readl_relaxed(spi_engine->base + in spi_engine_trigger_disable()
852 SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num)); in spi_engine_trigger_disable()
854 writel_relaxed(reg, spi_engine->base + in spi_engine_trigger_disable()
855 SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num)); in spi_engine_trigger_disable()
861 struct spi_engine_offload *priv = offload->priv; in spi_engine_tx_stream_request_dma_chan()
864 snprintf(name, sizeof(name), "offload%u-tx", priv->offload_num); in spi_engine_tx_stream_request_dma_chan()
866 return dma_request_chan(offload->provider_dev, name); in spi_engine_tx_stream_request_dma_chan()
872 struct spi_engine_offload *priv = offload->priv; in spi_engine_rx_stream_request_dma_chan()
875 snprintf(name, sizeof(name), "offload%u-rx", priv->offload_num); in spi_engine_rx_stream_request_dma_chan()
877 return dma_request_chan(offload->provider_dev, name); in spi_engine_rx_stream_request_dma_chan()
891 writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); in spi_engine_release_hw()
892 writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); in spi_engine_release_hw()
893 writel_relaxed(0x01, spi_engine->base + SPI_ENGINE_REG_RESET); in spi_engine_release_hw()
907 host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi_engine)); in spi_engine_probe()
909 return -ENOMEM; in spi_engine_probe()
913 spin_lock_init(&spi_engine->lock); in spi_engine_probe()
914 init_completion(&spi_engine->msg_complete); in spi_engine_probe()
917 * REVISIT: for now, all SPI Engines only have one offload. In the in spi_engine_probe()
923 if (device_property_present(&pdev->dev, "trigger-sources")) { in spi_engine_probe()
926 spi_engine->offload = in spi_engine_probe()
927 devm_spi_offload_alloc(&pdev->dev, in spi_engine_probe()
929 if (IS_ERR(spi_engine->offload)) in spi_engine_probe()
930 return PTR_ERR(spi_engine->offload); in spi_engine_probe()
932 priv = spi_engine->offload->priv; in spi_engine_probe()
933 priv->spi_engine = spi_engine; in spi_engine_probe()
934 priv->offload_num = 0; in spi_engine_probe()
936 spi_engine->offload->ops = &spi_engine_offload_ops; in spi_engine_probe()
937 spi_engine->offload_caps = SPI_OFFLOAD_CAP_TRIGGER; in spi_engine_probe()
939 if (device_property_match_string(&pdev->dev, "dma-names", "offload0-rx") >= 0) { in spi_engine_probe()
940 spi_engine->offload_caps |= SPI_OFFLOAD_CAP_RX_STREAM_DMA; in spi_engine_probe()
941 spi_engine->offload->xfer_flags |= SPI_OFFLOAD_XFER_RX_STREAM; in spi_engine_probe()
944 if (device_property_match_string(&pdev->dev, "dma-names", "offload0-tx") >= 0) { in spi_engine_probe()
945 spi_engine->offload_caps |= SPI_OFFLOAD_CAP_TX_STREAM_DMA; in spi_engine_probe()
946 spi_engine->offload->xfer_flags |= SPI_OFFLOAD_XFER_TX_STREAM; in spi_engine_probe()
952 spi_engine->offload_caps |= SPI_OFFLOAD_CAP_TX_STATIC_DATA; in spi_engine_probe()
956 spi_engine->clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk"); in spi_engine_probe()
957 if (IS_ERR(spi_engine->clk)) in spi_engine_probe()
958 return PTR_ERR(spi_engine->clk); in spi_engine_probe()
960 spi_engine->ref_clk = devm_clk_get_enabled(&pdev->dev, "spi_clk"); in spi_engine_probe()
961 if (IS_ERR(spi_engine->ref_clk)) in spi_engine_probe()
962 return PTR_ERR(spi_engine->ref_clk); in spi_engine_probe()
964 spi_engine->base = devm_platform_ioremap_resource(pdev, 0); in spi_engine_probe()
965 if (IS_ERR(spi_engine->base)) in spi_engine_probe()
966 return PTR_ERR(spi_engine->base); in spi_engine_probe()
968 version = readl(spi_engine->base + ADI_AXI_REG_VERSION); in spi_engine_probe()
969 if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) { in spi_engine_probe()
970 dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%u\n", in spi_engine_probe()
974 return -ENODEV; in spi_engine_probe()
977 if (ADI_AXI_PCORE_VER_MINOR(version) >= 1) { in spi_engine_probe()
978 unsigned int sizes = readl(spi_engine->base + in spi_engine_probe()
981 spi_engine->offload_ctrl_mem_size = 1 << in spi_engine_probe()
983 spi_engine->offload_sdo_mem_size = 1 << in spi_engine_probe()
986 spi_engine->offload_ctrl_mem_size = SPI_ENGINE_OFFLOAD_CMD_FIFO_SIZE; in spi_engine_probe()
987 spi_engine->offload_sdo_mem_size = SPI_ENGINE_OFFLOAD_SDO_FIFO_SIZE; in spi_engine_probe()
990 writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_RESET); in spi_engine_probe()
991 writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); in spi_engine_probe()
992 writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); in spi_engine_probe()
994 ret = devm_add_action_or_reset(&pdev->dev, spi_engine_release_hw, in spi_engine_probe()
999 ret = devm_request_irq(&pdev->dev, irq, spi_engine_irq, 0, pdev->name, in spi_engine_probe()
1004 host->dev.of_node = pdev->dev.of_node; in spi_engine_probe()
1005 host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE; in spi_engine_probe()
1006 host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); in spi_engine_probe()
1007 host->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2; in spi_engine_probe()
1008 host->transfer_one_message = spi_engine_transfer_one_message; in spi_engine_probe()
1009 host->optimize_message = spi_engine_optimize_message; in spi_engine_probe()
1010 host->unoptimize_message = spi_engine_unoptimize_message; in spi_engine_probe()
1011 host->get_offload = spi_engine_get_offload; in spi_engine_probe()
1012 host->put_offload = spi_engine_put_offload; in spi_engine_probe()
1013 host->num_chipselect = 8; in spi_engine_probe()
1016 if (ADI_AXI_PCORE_VER_MAJOR(version) >= 1) { in spi_engine_probe()
1018 host->mode_bits |= SPI_CS_HIGH; in spi_engine_probe()
1019 host->setup = spi_engine_setup; in spi_engine_probe()
1022 host->mode_bits |= SPI_MOSI_IDLE_LOW | SPI_MOSI_IDLE_HIGH; in spi_engine_probe()
1025 if (host->max_speed_hz == 0) in spi_engine_probe()
1026 return dev_err_probe(&pdev->dev, -EINVAL, "spi_clk rate is 0"); in spi_engine_probe()
1028 return devm_spi_register_controller(&pdev->dev, host); in spi_engine_probe()
1032 { .compatible = "adi,axi-spi-engine-1.00.a" },
1040 .name = "spi-engine",
1046 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
1047 MODULE_DESCRIPTION("Analog Devices SPI engine peripheral driver");