Lines Matching +full:rx +full:- +full:tx +full:- +full:swap

7  * SPDX-License-Identifier: GPL-2.0+
12 #include <linux/clk-provider.h>
30 * - all transfers are cutted in 16 words burst because the FIFO hangs on
31 * TX underflow, and there is no TX "Half-Empty" interrupt, so we go by
33 * - CS management is dumb, and goes UP between every burst, so is really a
68 #define SPICC_TE_EN BIT(0) /* TX FIFO Empty Interrupt */
69 #define SPICC_TH_EN BIT(1) /* TX FIFO Half-Full Interrupt */
70 #define SPICC_TF_EN BIT(2) /* TX FIFO Full Interrupt */
71 #define SPICC_RR_EN BIT(3) /* RX FIFO Ready Interrupt */
72 #define SPICC_RH_EN BIT(4) /* RX FIFO Half-Full Interrupt */
73 #define SPICC_RF_EN BIT(5) /* RX FIFO Full Interrupt */
74 #define SPICC_RO_EN BIT(6) /* RX FIFO Overflow Interrupt */
88 #define SPICC_TE BIT(0) /* TX FIFO Empty Interrupt */
89 #define SPICC_TH BIT(1) /* TX FIFO Half-Full Interrupt */
90 #define SPICC_TF BIT(2) /* TX FIFO Full Interrupt */
91 #define SPICC_RR BIT(3) /* RX FIFO Ready Interrupt */
92 #define SPICC_RH BIT(4) /* RX FIFO Half-Full Interrupt */
93 #define SPICC_RF BIT(5) /* RX FIFO Full Interrupt */
94 #define SPICC_RO BIT(6) /* RX FIFO Overflow Interrupt */
101 #define SPICC_TXCNT_MASK GENMASK(4, 0) /* TX FIFO Counter */
102 #define SPICC_RXCNT_MASK GENMASK(9, 5) /* RX FIFO Counter */
104 #define SPICC_LBC_RO BIT(13) /* Loop Back Control Read-Only */
105 #define SPICC_LBC_W1 BIT(14) /* Loop Back Control Write-Only */
106 #define SPICC_SWAP_RO BIT(14) /* RX FIFO Data Swap Read-Only */
107 #define SPICC_SWAP_W1 BIT(15) /* RX FIFO Data Swap Write-Only */
108 #define SPICC_DLYCTL_RO_MASK GENMASK(20, 15) /* Delay Control Read-Only */
124 #define SPICC_FIFORST_RO_MASK GENMASK(22, 21) /* FIFO Softreset Read-Only */
125 #define SPICC_FIFORST_W1_MASK GENMASK(23, 22) /* FIFO Softreset Write-Only */
175 if (!spicc->data->has_oen) in meson_spicc_oen_enable()
178 conf = readl_relaxed(spicc->base + SPICC_ENH_CTL0) | in meson_spicc_oen_enable()
181 writel_relaxed(conf, spicc->base + SPICC_ENH_CTL0); in meson_spicc_oen_enable()
187 readl_relaxed(spicc->base + SPICC_STATREG)); in meson_spicc_txfull()
193 readl_relaxed(spicc->base + SPICC_STATREG)); in meson_spicc_rxready()
198 unsigned int bytes = spicc->bytes_per_word; in meson_spicc_pull_data()
203 while (bytes--) { in meson_spicc_pull_data()
204 byte = *spicc->tx_buf++; in meson_spicc_pull_data()
209 spicc->tx_remain--; in meson_spicc_pull_data()
216 unsigned int bytes = spicc->bytes_per_word; in meson_spicc_push_data()
220 while (bytes--) { in meson_spicc_push_data()
222 *spicc->rx_buf++ = byte; in meson_spicc_push_data()
226 spicc->rx_remain--; in meson_spicc_push_data()
231 /* Empty RX FIFO */ in meson_spicc_rx()
232 while (spicc->rx_remain && in meson_spicc_rx()
235 readl_relaxed(spicc->base + SPICC_RXDATA)); in meson_spicc_rx()
240 /* Fill Up TX FIFO */ in meson_spicc_tx()
241 while (spicc->tx_remain && in meson_spicc_tx()
244 spicc->base + SPICC_TXDATA); in meson_spicc_tx()
251 spicc->xfer_remain / in meson_spicc_setup_burst()
252 spicc->bytes_per_word, in meson_spicc_setup_burst()
253 spicc->data->fifo_size); in meson_spicc_setup_burst()
255 spicc->tx_remain = burst_len; in meson_spicc_setup_burst()
256 spicc->rx_remain = burst_len; in meson_spicc_setup_burst()
257 spicc->xfer_remain -= burst_len * spicc->bytes_per_word; in meson_spicc_setup_burst()
262 burst_len - 1), in meson_spicc_setup_burst()
263 spicc->base + SPICC_CONREG); in meson_spicc_setup_burst()
265 /* Fill TX FIFO */ in meson_spicc_setup_burst()
273 writel_bits_relaxed(SPICC_TC, SPICC_TC, spicc->base + SPICC_STATREG); in meson_spicc_irq()
275 /* Empty RX FIFO */ in meson_spicc_irq()
278 if (!spicc->xfer_remain) { in meson_spicc_irq()
280 writel(0, spicc->base + SPICC_INTREG); in meson_spicc_irq()
282 spi_finalize_current_transfer(spicc->master); in meson_spicc_irq()
291 writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG); in meson_spicc_irq()
302 if (spicc->data->has_enhance_clk_div) { in meson_spicc_auto_io_delay()
304 readl_relaxed(spicc->base + SPICC_ENH_CTL0)); in meson_spicc_auto_io_delay()
309 readl_relaxed(spicc->base + SPICC_CONREG)); in meson_spicc_auto_io_delay()
316 hz = clk_get_rate(spicc->clk); in meson_spicc_auto_io_delay()
331 conf = readl_relaxed(spicc->base + SPICC_TESTREG); in meson_spicc_auto_io_delay()
336 writel_relaxed(conf, spicc->base + SPICC_TESTREG); in meson_spicc_auto_io_delay()
345 conf = conf_orig = readl_relaxed(spicc->base + SPICC_CONREG); in meson_spicc_setup_xfer()
350 (spicc->bytes_per_word << 3) - 1); in meson_spicc_setup_xfer()
354 writel_relaxed(conf, spicc->base + SPICC_CONREG); in meson_spicc_setup_xfer()
356 clk_set_rate(spicc->clk, xfer->speed_hz); in meson_spicc_setup_xfer()
360 writel_relaxed(0, spicc->base + SPICC_DMAREG); in meson_spicc_setup_xfer()
365 if (spicc->data->has_oen) in meson_spicc_reset_fifo()
368 spicc->base + SPICC_ENH_CTL0); in meson_spicc_reset_fifo()
371 spicc->base + SPICC_TESTREG); in meson_spicc_reset_fifo()
374 readl_relaxed(spicc->base + SPICC_RXDATA); in meson_spicc_reset_fifo()
376 if (spicc->data->has_oen) in meson_spicc_reset_fifo()
378 spicc->base + SPICC_ENH_CTL0); in meson_spicc_reset_fifo()
388 spicc->xfer = xfer; in meson_spicc_transfer_one()
391 spicc->tx_buf = (u8 *)xfer->tx_buf; in meson_spicc_transfer_one()
392 spicc->rx_buf = (u8 *)xfer->rx_buf; in meson_spicc_transfer_one()
393 spicc->xfer_remain = xfer->len; in meson_spicc_transfer_one()
395 /* Pre-calculate word size */ in meson_spicc_transfer_one()
396 spicc->bytes_per_word = in meson_spicc_transfer_one()
397 DIV_ROUND_UP(spicc->xfer->bits_per_word, 8); in meson_spicc_transfer_one()
399 if (xfer->len % spicc->bytes_per_word) in meson_spicc_transfer_one()
400 return -EINVAL; in meson_spicc_transfer_one()
411 writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG); in meson_spicc_transfer_one()
414 writel_relaxed(SPICC_TC_EN, spicc->base + SPICC_INTREG); in meson_spicc_transfer_one()
423 struct spi_device *spi = message->spi; in meson_spicc_prepare_message()
427 spicc->message = message; in meson_spicc_prepare_message()
436 if (spi->mode & SPI_CPOL) in meson_spicc_prepare_message()
441 if (spi->mode & SPI_CPHA) in meson_spicc_prepare_message()
448 if (spi->mode & SPI_CS_HIGH) in meson_spicc_prepare_message()
453 if (spi->mode & SPI_READY) in meson_spicc_prepare_message()
459 conf |= FIELD_PREP(SPICC_CS_MASK, spi->chip_select); in meson_spicc_prepare_message()
464 conf |= FIELD_PREP(SPICC_BITLENGTH_MASK, 8 - 1); in meson_spicc_prepare_message()
466 writel_relaxed(conf, spicc->base + SPICC_CONREG); in meson_spicc_prepare_message()
469 writel_relaxed(0, spicc->base + SPICC_PERIODREG); in meson_spicc_prepare_message()
471 writel_bits_relaxed(SPICC_LBC_W1, 0, spicc->base + SPICC_TESTREG); in meson_spicc_prepare_message()
481 writel(0, spicc->base + SPICC_INTREG); in meson_spicc_unprepare_transfer()
483 device_reset_optional(&spicc->pdev->dev); in meson_spicc_unprepare_transfer()
490 if (!spi->controller_state) in meson_spicc_setup()
491 spi->controller_state = spi_master_get_devdata(spi->master); in meson_spicc_setup()
498 spi->controller_state = NULL; in meson_spicc_cleanup()
503 * x-----------------x x------------x x------\
504 * |---| pow2 fixed div |---| pow2 div |----| |
505 * | x-----------------x x------------x | |
506 * src ---| | mux |-- out
507 * | x-----------------x x------------x | |
508 * |---| enh fixed div |---| enh div |0---| |
509 * x-----------------x x------------x x------/
512 * src -> pow2 fixed div -> pow2 div -> out
515 * src -> pow2 fixed div -> pow2 div -> mux -> out
516 * src -> enh fixed div -> enh div -> mux -> out
519 * pclk -> pow2 fixed div -> pow2 div -> mux -> out
520 * pclk -> enh fixed div -> enh div -> mux -> out
525 struct device *dev = &spicc->pdev->dev; in meson_spicc_clk_init()
543 return -ENOMEM; in meson_spicc_clk_init()
549 if (spicc->data->has_pclk) in meson_spicc_clk_init()
550 parent_data[0].hw = __clk_get_hw(spicc->pclk); in meson_spicc_clk_init()
552 parent_data[0].hw = __clk_get_hw(spicc->core); in meson_spicc_clk_init()
555 pow2_fixed_div->mult = 1, in meson_spicc_clk_init()
556 pow2_fixed_div->div = 4, in meson_spicc_clk_init()
557 pow2_fixed_div->hw.init = &init; in meson_spicc_clk_init()
559 clk = devm_clk_register(dev, &pow2_fixed_div->hw); in meson_spicc_clk_init()
565 return -ENOMEM; in meson_spicc_clk_init()
571 parent_data[0].hw = &pow2_fixed_div->hw; in meson_spicc_clk_init()
574 pow2_div->shift = 16, in meson_spicc_clk_init()
575 pow2_div->width = 3, in meson_spicc_clk_init()
576 pow2_div->flags = CLK_DIVIDER_POWER_OF_TWO, in meson_spicc_clk_init()
577 pow2_div->reg = spicc->base + SPICC_CONREG; in meson_spicc_clk_init()
578 pow2_div->hw.init = &init; in meson_spicc_clk_init()
580 clk = devm_clk_register(dev, &pow2_div->hw); in meson_spicc_clk_init()
584 if (!spicc->data->has_enhance_clk_div) { in meson_spicc_clk_init()
585 spicc->clk = clk; in meson_spicc_clk_init()
593 return -ENOMEM; in meson_spicc_clk_init()
599 if (spicc->data->has_pclk) in meson_spicc_clk_init()
600 parent_data[0].hw = __clk_get_hw(spicc->pclk); in meson_spicc_clk_init()
602 parent_data[0].hw = __clk_get_hw(spicc->core); in meson_spicc_clk_init()
605 enh_fixed_div->mult = 1, in meson_spicc_clk_init()
606 enh_fixed_div->div = 2, in meson_spicc_clk_init()
607 enh_fixed_div->hw.init = &init; in meson_spicc_clk_init()
609 clk = devm_clk_register(dev, &enh_fixed_div->hw); in meson_spicc_clk_init()
615 return -ENOMEM; in meson_spicc_clk_init()
621 parent_data[0].hw = &enh_fixed_div->hw; in meson_spicc_clk_init()
624 enh_div->shift = 16, in meson_spicc_clk_init()
625 enh_div->width = 8, in meson_spicc_clk_init()
626 enh_div->reg = spicc->base + SPICC_ENH_CTL0; in meson_spicc_clk_init()
627 enh_div->hw.init = &init; in meson_spicc_clk_init()
629 clk = devm_clk_register(dev, &enh_div->hw); in meson_spicc_clk_init()
635 return -ENOMEM; in meson_spicc_clk_init()
640 parent_data[0].hw = &pow2_div->hw; in meson_spicc_clk_init()
641 parent_data[1].hw = &enh_div->hw; in meson_spicc_clk_init()
645 mux->mask = 0x1, in meson_spicc_clk_init()
646 mux->shift = 24, in meson_spicc_clk_init()
647 mux->reg = spicc->base + SPICC_ENH_CTL0; in meson_spicc_clk_init()
648 mux->hw.init = &init; in meson_spicc_clk_init()
650 spicc->clk = devm_clk_register(dev, &mux->hw); in meson_spicc_clk_init()
651 if (WARN_ON(IS_ERR(spicc->clk))) in meson_spicc_clk_init()
652 return PTR_ERR(spicc->clk); in meson_spicc_clk_init()
663 master = spi_alloc_master(&pdev->dev, sizeof(*spicc)); in meson_spicc_probe()
665 dev_err(&pdev->dev, "master allocation failed\n"); in meson_spicc_probe()
666 return -ENOMEM; in meson_spicc_probe()
669 spicc->master = master; in meson_spicc_probe()
671 spicc->data = of_device_get_match_data(&pdev->dev); in meson_spicc_probe()
672 if (!spicc->data) { in meson_spicc_probe()
673 dev_err(&pdev->dev, "failed to get match data\n"); in meson_spicc_probe()
674 ret = -EINVAL; in meson_spicc_probe()
678 spicc->pdev = pdev; in meson_spicc_probe()
681 spicc->base = devm_platform_ioremap_resource(pdev, 0); in meson_spicc_probe()
682 if (IS_ERR(spicc->base)) { in meson_spicc_probe()
683 dev_err(&pdev->dev, "io resource mapping failed\n"); in meson_spicc_probe()
684 ret = PTR_ERR(spicc->base); in meson_spicc_probe()
690 spicc->base + SPICC_CONREG); in meson_spicc_probe()
693 writel_relaxed(0, spicc->base + SPICC_INTREG); in meson_spicc_probe()
696 ret = devm_request_irq(&pdev->dev, irq, meson_spicc_irq, in meson_spicc_probe()
699 dev_err(&pdev->dev, "irq request failed\n"); in meson_spicc_probe()
703 spicc->core = devm_clk_get(&pdev->dev, "core"); in meson_spicc_probe()
704 if (IS_ERR(spicc->core)) { in meson_spicc_probe()
705 dev_err(&pdev->dev, "core clock request failed\n"); in meson_spicc_probe()
706 ret = PTR_ERR(spicc->core); in meson_spicc_probe()
710 if (spicc->data->has_pclk) { in meson_spicc_probe()
711 spicc->pclk = devm_clk_get(&pdev->dev, "pclk"); in meson_spicc_probe()
712 if (IS_ERR(spicc->pclk)) { in meson_spicc_probe()
713 dev_err(&pdev->dev, "pclk clock request failed\n"); in meson_spicc_probe()
714 ret = PTR_ERR(spicc->pclk); in meson_spicc_probe()
719 ret = clk_prepare_enable(spicc->core); in meson_spicc_probe()
721 dev_err(&pdev->dev, "core clock enable failed\n"); in meson_spicc_probe()
725 ret = clk_prepare_enable(spicc->pclk); in meson_spicc_probe()
727 dev_err(&pdev->dev, "pclk clock enable failed\n"); in meson_spicc_probe()
731 device_reset_optional(&pdev->dev); in meson_spicc_probe()
733 master->num_chipselect = 4; in meson_spicc_probe()
734 master->dev.of_node = pdev->dev.of_node; in meson_spicc_probe()
735 master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH; in meson_spicc_probe()
736 master->bits_per_word_mask = SPI_BPW_MASK(32) | in meson_spicc_probe()
740 master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX); in meson_spicc_probe()
741 master->min_speed_hz = spicc->data->min_speed_hz; in meson_spicc_probe()
742 master->max_speed_hz = spicc->data->max_speed_hz; in meson_spicc_probe()
743 master->setup = meson_spicc_setup; in meson_spicc_probe()
744 master->cleanup = meson_spicc_cleanup; in meson_spicc_probe()
745 master->prepare_message = meson_spicc_prepare_message; in meson_spicc_probe()
746 master->unprepare_transfer_hardware = meson_spicc_unprepare_transfer; in meson_spicc_probe()
747 master->transfer_one = meson_spicc_transfer_one; in meson_spicc_probe()
748 master->use_gpio_descriptors = true; in meson_spicc_probe()
754 dev_err(&pdev->dev, "clock registration failed\n"); in meson_spicc_probe()
758 ret = devm_spi_register_master(&pdev->dev, master); in meson_spicc_probe()
760 dev_err(&pdev->dev, "spi master registration failed\n"); in meson_spicc_probe()
767 clk_disable_unprepare(spicc->core); in meson_spicc_probe()
768 clk_disable_unprepare(spicc->pclk); in meson_spicc_probe()
781 writel(0, spicc->base + SPICC_CONREG); in meson_spicc_remove()
783 clk_disable_unprepare(spicc->core); in meson_spicc_remove()
784 clk_disable_unprepare(spicc->pclk); in meson_spicc_remove()
814 .compatible = "amlogic,meson-gx-spicc",
818 .compatible = "amlogic,meson-axg-spicc",
822 .compatible = "amlogic,meson-g12a-spicc",
833 .name = "meson-spicc",