Lines Matching +full:tx +full:- +full:fifo +full:- +full:depth

1 // SPDX-License-Identifier: GPL-2.0-only
8 #include <linux/dma-mapping.h>
16 #include "spi-dw.h"
39 struct dw_spi *dws = file->private_data; in dw_spi_show_regs()
48 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
49 "%s registers:\n", dev_name(&dws->master->dev)); in dw_spi_show_regs()
50 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
52 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
54 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
56 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
58 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
60 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
62 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
64 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
66 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
68 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
70 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
72 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
74 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
76 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
78 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
80 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
82 len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len, in dw_spi_show_regs()
101 snprintf(name, 32, "dw_spi%d", dws->master->bus_num); in dw_spi_debugfs_init()
102 dws->debugfs = debugfs_create_dir(name, NULL); in dw_spi_debugfs_init()
103 if (!dws->debugfs) in dw_spi_debugfs_init()
104 return -ENOMEM; in dw_spi_debugfs_init()
107 dws->debugfs, (void *)dws, &dw_spi_regs_ops); in dw_spi_debugfs_init()
113 debugfs_remove_recursive(dws->debugfs); in dw_spi_debugfs_remove()
129 struct dw_spi *dws = spi_controller_get_devdata(spi->controller); in dw_spi_set_cs()
132 if (chip && chip->cs_control) in dw_spi_set_cs()
133 chip->cs_control(enable); in dw_spi_set_cs()
136 dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select)); in dw_spi_set_cs()
137 else if (dws->cs_override) in dw_spi_set_cs()
142 /* Return the max entries we can fill into tx fifo */
147 tx_left = (dws->tx_end - dws->tx) / dws->n_bytes; in tx_max()
148 tx_room = dws->fifo_len - dw_readl(dws, DW_SPI_TXFLR); in tx_max()
151 * Another concern is about the tx/rx mismatch, we in tx_max()
152 * though to use (dws->fifo_len - rxflr - txflr) as in tx_max()
153 * one maximum value for tx, but it doesn't cover the in tx_max()
154 * data which is out of tx/rx fifo and inside the in tx_max()
158 rxtx_gap = ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx)) in tx_max()
159 / dws->n_bytes; in tx_max()
161 return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap)); in tx_max()
164 /* Return the max entries we should read out of rx fifo */
167 u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes; in rx_max()
177 while (max--) { in dw_writer()
178 /* Set the tx word if the transfer's original "tx" is not null */ in dw_writer()
179 if (dws->tx_end - dws->len) { in dw_writer()
180 if (dws->n_bytes == 1) in dw_writer()
181 txw = *(u8 *)(dws->tx); in dw_writer()
183 txw = *(u16 *)(dws->tx); in dw_writer()
186 dws->tx += dws->n_bytes; in dw_writer()
195 while (max--) { in dw_reader()
198 if (dws->rx_end - dws->len) { in dw_reader()
199 if (dws->n_bytes == 1) in dw_reader()
200 *(u8 *)(dws->rx) = rxw; in dw_reader()
202 *(u16 *)(dws->rx) = rxw; in dw_reader()
204 dws->rx += dws->n_bytes; in dw_reader()
212 dev_err(&dws->master->dev, "%s\n", msg); in int_error_stop()
213 dws->master->cur_msg->status = -EIO; in int_error_stop()
214 spi_finalize_current_transfer(dws->master); in int_error_stop()
224 int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun"); in interrupt_transfer()
229 if (dws->rx_end == dws->rx) { in interrupt_transfer()
231 spi_finalize_current_transfer(dws->master); in interrupt_transfer()
237 /* Enable TX irq always, it will be disabled when RX finished */ in interrupt_transfer()
253 if (!master->cur_msg) { in dw_spi_irq()
258 return dws->transfer_handler(dws); in dw_spi_irq()
268 } while (dws->rx_end > dws->rx); in poll_transfer()
283 dws->dma_mapped = 0; in dw_spi_transfer_one()
285 dws->tx = (void *)transfer->tx_buf; in dw_spi_transfer_one()
286 dws->tx_end = dws->tx + transfer->len; in dw_spi_transfer_one()
287 dws->rx = transfer->rx_buf; in dw_spi_transfer_one()
288 dws->rx_end = dws->rx + transfer->len; in dw_spi_transfer_one()
289 dws->len = transfer->len; in dw_spi_transfer_one()
294 if (transfer->speed_hz != dws->current_freq) { in dw_spi_transfer_one()
295 if (transfer->speed_hz != chip->speed_hz) { in dw_spi_transfer_one()
297 chip->clk_div = (DIV_ROUND_UP(dws->max_freq, transfer->speed_hz) + 1) & 0xfffe; in dw_spi_transfer_one()
298 chip->speed_hz = transfer->speed_hz; in dw_spi_transfer_one()
300 dws->current_freq = transfer->speed_hz; in dw_spi_transfer_one()
301 spi_set_clk(dws, chip->clk_div); in dw_spi_transfer_one()
304 dws->n_bytes = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE); in dw_spi_transfer_one()
305 dws->dma_width = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE); in dw_spi_transfer_one()
308 cr0 = (transfer->bits_per_word - 1) in dw_spi_transfer_one()
309 | (chip->type << SPI_FRF_OFFSET) in dw_spi_transfer_one()
310 | ((((spi->mode & SPI_CPOL) ? 1 : 0) << SPI_SCOL_OFFSET) | in dw_spi_transfer_one()
311 (((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET)) in dw_spi_transfer_one()
312 | (chip->tmode << SPI_TMOD_OFFSET); in dw_spi_transfer_one()
318 if (chip->cs_control) { in dw_spi_transfer_one()
319 if (dws->rx && dws->tx) in dw_spi_transfer_one()
320 chip->tmode = SPI_TMOD_TR; in dw_spi_transfer_one()
321 else if (dws->rx) in dw_spi_transfer_one()
322 chip->tmode = SPI_TMOD_RO; in dw_spi_transfer_one()
324 chip->tmode = SPI_TMOD_TO; in dw_spi_transfer_one()
327 cr0 |= (chip->tmode << SPI_TMOD_OFFSET); in dw_spi_transfer_one()
333 if (master->can_dma && master->can_dma(master, spi, transfer)) in dw_spi_transfer_one()
334 dws->dma_mapped = master->cur_msg_mapped; in dw_spi_transfer_one()
341 * we only need set the TXEI IRQ, as TX/RX always happen syncronizely in dw_spi_transfer_one()
343 if (dws->dma_mapped) { in dw_spi_transfer_one()
344 ret = dws->dma_ops->dma_setup(dws, transfer); in dw_spi_transfer_one()
349 } else if (!chip->poll_mode) { in dw_spi_transfer_one()
350 txlevel = min_t(u16, dws->fifo_len / 2, dws->len / dws->n_bytes); in dw_spi_transfer_one()
358 dws->transfer_handler = interrupt_transfer; in dw_spi_transfer_one()
363 if (dws->dma_mapped) { in dw_spi_transfer_one()
364 ret = dws->dma_ops->dma_transfer(dws, transfer); in dw_spi_transfer_one()
369 if (chip->poll_mode) in dw_spi_transfer_one()
380 if (dws->dma_mapped) in dw_spi_handle_err()
381 dws->dma_ops->dma_stop(dws); in dw_spi_handle_err()
397 return -ENOMEM; in dw_spi_setup()
405 chip_info = spi->controller_data; in dw_spi_setup()
409 if (chip_info->cs_control) in dw_spi_setup()
410 chip->cs_control = chip_info->cs_control; in dw_spi_setup()
412 chip->poll_mode = chip_info->poll_mode; in dw_spi_setup()
413 chip->type = chip_info->type; in dw_spi_setup()
416 chip->tmode = SPI_TMOD_TR; in dw_spi_setup()
429 /* Restart the controller, disable all interrupts, clean rx fifo */
435 * Try to detect the FIFO depth if not set by interface driver, in spi_hw_init()
436 * the depth could be from 2 to 256 from HW spec in spi_hw_init()
438 if (!dws->fifo_len) { in spi_hw_init()
439 u32 fifo; in spi_hw_init() local
441 for (fifo = 1; fifo < 256; fifo++) { in spi_hw_init()
442 dw_writel(dws, DW_SPI_TXFLTR, fifo); in spi_hw_init()
443 if (fifo != dw_readl(dws, DW_SPI_TXFLTR)) in spi_hw_init()
448 dws->fifo_len = (fifo == 1) ? 0 : fifo; in spi_hw_init()
449 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len); in spi_hw_init()
453 if (dws->cs_override) in spi_hw_init()
466 return -ENOMEM; in dw_spi_add_host()
468 dws->master = master; in dw_spi_add_host()
469 dws->type = SSI_MOTO_SPI; in dw_spi_add_host()
470 dws->dma_inited = 0; in dw_spi_add_host()
471 dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR); in dw_spi_add_host()
475 ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev), in dw_spi_add_host()
482 master->use_gpio_descriptors = true; in dw_spi_add_host()
483 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; in dw_spi_add_host()
484 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); in dw_spi_add_host()
485 master->bus_num = dws->bus_num; in dw_spi_add_host()
486 master->num_chipselect = dws->num_cs; in dw_spi_add_host()
487 master->setup = dw_spi_setup; in dw_spi_add_host()
488 master->cleanup = dw_spi_cleanup; in dw_spi_add_host()
489 master->set_cs = dw_spi_set_cs; in dw_spi_add_host()
490 master->transfer_one = dw_spi_transfer_one; in dw_spi_add_host()
491 master->handle_err = dw_spi_handle_err; in dw_spi_add_host()
492 master->max_speed_hz = dws->max_freq; in dw_spi_add_host()
493 master->dev.of_node = dev->of_node; in dw_spi_add_host()
494 master->dev.fwnode = dev->fwnode; in dw_spi_add_host()
495 master->flags = SPI_MASTER_GPIO_SS; in dw_spi_add_host()
497 if (dws->set_cs) in dw_spi_add_host()
498 master->set_cs = dws->set_cs; in dw_spi_add_host()
503 if (dws->dma_ops && dws->dma_ops->dma_init) { in dw_spi_add_host()
504 ret = dws->dma_ops->dma_init(dws); in dw_spi_add_host()
507 dws->dma_inited = 0; in dw_spi_add_host()
509 master->can_dma = dws->dma_ops->can_dma; in dw_spi_add_host()
515 dev_err(&master->dev, "problem registering spi master\n"); in dw_spi_add_host()
523 if (dws->dma_ops && dws->dma_ops->dma_exit) in dw_spi_add_host()
524 dws->dma_ops->dma_exit(dws); in dw_spi_add_host()
526 free_irq(dws->irq, master); in dw_spi_add_host()
537 if (dws->dma_ops && dws->dma_ops->dma_exit) in dw_spi_remove_host()
538 dws->dma_ops->dma_exit(dws); in dw_spi_remove_host()
542 free_irq(dws->irq, dws->master); in dw_spi_remove_host()
550 ret = spi_controller_suspend(dws->master); in dw_spi_suspend_host()
561 spi_hw_init(&dws->master->dev, dws); in dw_spi_resume_host()
562 return spi_controller_resume(dws->master); in dw_spi_resume_host()