Lines Matching +full:rx +full:- +full:ctrl
7 * SPDX-License-Identifier: GPL-2.0+
29 * - all transfers are cutted in 16 words burst because the FIFO hangs on
30 * TX underflow, and there is no TX "Half-Empty" interrupt, so we go by
32 * - CS management is dumb, and goes UP between every burst, so is really a
69 #define SPICC_TH_EN BIT(1) /* TX FIFO Half-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 */
89 #define SPICC_TH BIT(1) /* TX FIFO Half-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 */
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 */
109 #define SPICC_DLYCTL_W1_MASK GENMASK(21, 16) /* Delay Control Write-Only */
110 #define SPICC_FIFORST_RO_MASK GENMASK(22, 21) /* FIFO Softreset Read-Only */
111 #define SPICC_FIFORST_W1_MASK GENMASK(23, 22) /* FIFO Softreset Write-Only */
145 readl_relaxed(spicc->base + SPICC_STATREG)); in meson_spicc_txfull()
151 readl_relaxed(spicc->base + SPICC_STATREG)); in meson_spicc_rxready()
156 unsigned int bytes = spicc->bytes_per_word; in meson_spicc_pull_data()
161 while (bytes--) { in meson_spicc_pull_data()
162 byte = *spicc->tx_buf++; in meson_spicc_pull_data()
167 spicc->tx_remain--; in meson_spicc_pull_data()
174 unsigned int bytes = spicc->bytes_per_word; in meson_spicc_push_data()
178 while (bytes--) { in meson_spicc_push_data()
180 *spicc->rx_buf++ = byte; in meson_spicc_push_data()
184 spicc->rx_remain--; in meson_spicc_push_data()
189 /* Empty RX FIFO */ in meson_spicc_rx()
190 while (spicc->rx_remain && in meson_spicc_rx()
193 readl_relaxed(spicc->base + SPICC_RXDATA)); in meson_spicc_rx()
199 while (spicc->tx_remain && in meson_spicc_tx()
202 spicc->base + SPICC_TXDATA); in meson_spicc_tx()
208 if (spicc->rx_remain > SPICC_FIFO_HALF) in meson_spicc_setup_rx_irq()
220 spicc->tx_remain = burst_len; in meson_spicc_setup_burst()
221 spicc->rx_remain = burst_len; in meson_spicc_setup_burst()
222 spicc->xfer_remain -= burst_len * spicc->bytes_per_word; in meson_spicc_setup_burst()
223 spicc->is_burst_end = false; in meson_spicc_setup_burst()
224 if (burst_len < SPICC_BURST_MAX || !spicc->xfer_remain) in meson_spicc_setup_burst()
225 spicc->is_last_burst = true; in meson_spicc_setup_burst()
227 spicc->is_last_burst = false; in meson_spicc_setup_burst()
233 spicc->base + SPICC_CONREG); in meson_spicc_setup_burst()
242 u32 ctrl = readl_relaxed(spicc->base + SPICC_INTREG); in meson_spicc_irq() local
243 u32 stat = readl_relaxed(spicc->base + SPICC_STATREG) & ctrl; in meson_spicc_irq()
245 ctrl &= ~(SPICC_RH_EN | SPICC_RR_EN); in meson_spicc_irq()
247 /* Empty RX FIFO */ in meson_spicc_irq()
251 if (!spicc->tx_remain && !spicc->rx_remain) { in meson_spicc_irq()
252 spicc->is_burst_end = true; in meson_spicc_irq()
255 ctrl |= SPICC_TC_EN; in meson_spicc_irq()
258 stat = readl_relaxed(spicc->base + SPICC_STATREG) & ctrl; in meson_spicc_irq()
262 if ((stat & SPICC_TC) && spicc->is_burst_end) { in meson_spicc_irq()
266 writel_relaxed(SPICC_TC, spicc->base + SPICC_STATREG); in meson_spicc_irq()
269 ctrl &= ~SPICC_TC_EN; in meson_spicc_irq()
271 if (spicc->is_last_burst) { in meson_spicc_irq()
273 writel(0, spicc->base + SPICC_INTREG); in meson_spicc_irq()
275 spi_finalize_current_transfer(spicc->master); in meson_spicc_irq()
281 spicc->xfer_remain / spicc->bytes_per_word, in meson_spicc_irq()
289 spicc->base + SPICC_CONREG); in meson_spicc_irq()
292 /* Setup RX interrupt trigger */ in meson_spicc_irq()
293 ctrl = meson_spicc_setup_rx_irq(spicc, ctrl); in meson_spicc_irq()
296 writel(ctrl, spicc->base + SPICC_INTREG); in meson_spicc_irq()
307 parent = clk_get_rate(spicc->core); in meson_spicc_setup_speed()
321 dev_warn_once(&spicc->pdev->dev, "unable to get close to speed %u\n", in meson_spicc_setup_speed()
326 dev_dbg(&spicc->pdev->dev, "parent %lu, speed %u -> %lu (%u)\n", in meson_spicc_setup_speed()
341 conf = conf_orig = readl_relaxed(spicc->base + SPICC_CONREG); in meson_spicc_setup_xfer()
344 conf = meson_spicc_setup_speed(spicc, conf, xfer->speed_hz); in meson_spicc_setup_xfer()
349 (spicc->bytes_per_word << 3) - 1); in meson_spicc_setup_xfer()
353 writel_relaxed(conf, spicc->base + SPICC_CONREG); in meson_spicc_setup_xfer()
365 spicc->xfer = xfer; in meson_spicc_transfer_one()
368 spicc->tx_buf = (u8 *)xfer->tx_buf; in meson_spicc_transfer_one()
369 spicc->rx_buf = (u8 *)xfer->rx_buf; in meson_spicc_transfer_one()
370 spicc->xfer_remain = xfer->len; in meson_spicc_transfer_one()
372 /* Pre-calculate word size */ in meson_spicc_transfer_one()
373 spicc->bytes_per_word = in meson_spicc_transfer_one()
374 DIV_ROUND_UP(spicc->xfer->bits_per_word, 8); in meson_spicc_transfer_one()
380 spicc->xfer_remain / spicc->bytes_per_word, in meson_spicc_transfer_one()
388 writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG); in meson_spicc_transfer_one()
391 writel_relaxed(irq, spicc->base + SPICC_INTREG); in meson_spicc_transfer_one()
400 struct spi_device *spi = message->spi; in meson_spicc_prepare_message()
404 spicc->message = message; in meson_spicc_prepare_message()
413 if (spi->mode & SPI_CPOL) in meson_spicc_prepare_message()
418 if (spi->mode & SPI_CPHA) in meson_spicc_prepare_message()
425 if (spi->mode & SPI_CS_HIGH) in meson_spicc_prepare_message()
430 if (spi->mode & SPI_READY) in meson_spicc_prepare_message()
436 conf |= FIELD_PREP(SPICC_CS_MASK, spi->chip_select); in meson_spicc_prepare_message()
441 conf |= FIELD_PREP(SPICC_BITLENGTH_MASK, 8 - 1); in meson_spicc_prepare_message()
443 writel_relaxed(conf, spicc->base + SPICC_CONREG); in meson_spicc_prepare_message()
446 writel_relaxed(0, spicc->base + SPICC_PERIODREG); in meson_spicc_prepare_message()
448 writel_bits_relaxed(BIT(24), BIT(24), spicc->base + SPICC_TESTREG); in meson_spicc_prepare_message()
458 writel(0, spicc->base + SPICC_INTREG); in meson_spicc_unprepare_transfer()
461 writel_bits_relaxed(SPICC_ENABLE, 0, spicc->base + SPICC_CONREG); in meson_spicc_unprepare_transfer()
463 device_reset_optional(&spicc->pdev->dev); in meson_spicc_unprepare_transfer()
472 if (!spi->controller_state) in meson_spicc_setup()
473 spi->controller_state = spi_master_get_devdata(spi->master); in meson_spicc_setup()
474 else if (gpio_is_valid(spi->cs_gpio)) in meson_spicc_setup()
476 else if (spi->cs_gpio == -ENOENT) in meson_spicc_setup()
479 if (gpio_is_valid(spi->cs_gpio)) { in meson_spicc_setup()
480 ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev)); in meson_spicc_setup()
482 dev_err(&spi->dev, "failed to request cs gpio\n"); in meson_spicc_setup()
488 ret = gpio_direction_output(spi->cs_gpio, in meson_spicc_setup()
489 !(spi->mode & SPI_CS_HIGH)); in meson_spicc_setup()
496 if (gpio_is_valid(spi->cs_gpio)) in meson_spicc_cleanup()
497 gpio_free(spi->cs_gpio); in meson_spicc_cleanup()
499 spi->controller_state = NULL; in meson_spicc_cleanup()
509 master = spi_alloc_master(&pdev->dev, sizeof(*spicc)); in meson_spicc_probe()
511 dev_err(&pdev->dev, "master allocation failed\n"); in meson_spicc_probe()
512 return -ENOMEM; in meson_spicc_probe()
515 spicc->master = master; in meson_spicc_probe()
517 spicc->pdev = pdev; in meson_spicc_probe()
521 spicc->base = devm_ioremap_resource(&pdev->dev, res); in meson_spicc_probe()
522 if (IS_ERR(spicc->base)) { in meson_spicc_probe()
523 dev_err(&pdev->dev, "io resource mapping failed\n"); in meson_spicc_probe()
524 ret = PTR_ERR(spicc->base); in meson_spicc_probe()
529 writel_relaxed(0, spicc->base + SPICC_INTREG); in meson_spicc_probe()
532 ret = devm_request_irq(&pdev->dev, irq, meson_spicc_irq, in meson_spicc_probe()
535 dev_err(&pdev->dev, "irq request failed\n"); in meson_spicc_probe()
539 spicc->core = devm_clk_get(&pdev->dev, "core"); in meson_spicc_probe()
540 if (IS_ERR(spicc->core)) { in meson_spicc_probe()
541 dev_err(&pdev->dev, "core clock request failed\n"); in meson_spicc_probe()
542 ret = PTR_ERR(spicc->core); in meson_spicc_probe()
546 ret = clk_prepare_enable(spicc->core); in meson_spicc_probe()
548 dev_err(&pdev->dev, "core clock enable failed\n"); in meson_spicc_probe()
551 rate = clk_get_rate(spicc->core); in meson_spicc_probe()
553 device_reset_optional(&pdev->dev); in meson_spicc_probe()
555 master->num_chipselect = 4; in meson_spicc_probe()
556 master->dev.of_node = pdev->dev.of_node; in meson_spicc_probe()
557 master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH; in meson_spicc_probe()
558 master->bits_per_word_mask = SPI_BPW_MASK(32) | in meson_spicc_probe()
562 master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX); in meson_spicc_probe()
563 master->min_speed_hz = rate >> 9; in meson_spicc_probe()
564 master->setup = meson_spicc_setup; in meson_spicc_probe()
565 master->cleanup = meson_spicc_cleanup; in meson_spicc_probe()
566 master->prepare_message = meson_spicc_prepare_message; in meson_spicc_probe()
567 master->unprepare_transfer_hardware = meson_spicc_unprepare_transfer; in meson_spicc_probe()
568 master->transfer_one = meson_spicc_transfer_one; in meson_spicc_probe()
572 master->max_speed_hz = SPICC_MAX_FREQ; in meson_spicc_probe()
574 master->max_speed_hz = rate >> 2; in meson_spicc_probe()
576 ret = devm_spi_register_master(&pdev->dev, master); in meson_spicc_probe()
578 dev_err(&pdev->dev, "spi master registration failed\n"); in meson_spicc_probe()
585 clk_disable_unprepare(spicc->core); in meson_spicc_probe()
598 writel(0, spicc->base + SPICC_CONREG); in meson_spicc_remove()
600 clk_disable_unprepare(spicc->core); in meson_spicc_remove()
606 { .compatible = "amlogic,meson-gx-spicc", },
607 { .compatible = "amlogic,meson-axg-spicc", },
616 .name = "meson-spicc",