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

1 // SPDX-License-Identifier: GPL-2.0
8 * drivers/spi/spi-dw.c, which is:
13 #include <asm-generic/gpio.h>
91 s32 frequency; /* Default clock frequency, -1 for none */
102 struct gpio_desc cs_gpio; /* External chip-select gpio */
110 u32 fifo_len; /* depth of the FIFO buffer */
111 void *tx; member
121 return __raw_readl(priv->regs + offset); in dw_read()
126 __raw_writel(val, priv->regs + offset); in dw_write()
136 ret = gpio_request_by_name(bus, "cs-gpio", 0, &priv->cs_gpio, 0); in request_gpio_cs()
137 if (ret == -ENOENT) in request_gpio_cs()
141 printf("Error: %d: Can't get %s gpio!\n", ret, bus->name); in request_gpio_cs()
145 if (dm_gpio_is_valid(&priv->cs_gpio)) { in request_gpio_cs()
146 dm_gpio_set_dir_flags(&priv->cs_gpio, in request_gpio_cs()
157 struct dw_spi_platdata *plat = bus->platdata; in dw_spi_ofdata_to_platdata()
158 const void *blob = gd->fdt_blob; in dw_spi_ofdata_to_platdata()
161 plat->regs = (struct dw_spi *)devfdt_get_addr(bus); in dw_spi_ofdata_to_platdata()
164 plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", in dw_spi_ofdata_to_platdata()
166 debug("%s: regs=%p max-frequency=%d\n", __func__, plat->regs, in dw_spi_ofdata_to_platdata()
167 plat->frequency); in dw_spi_ofdata_to_platdata()
177 /* Restart the controller, disable all interrupts, clean rx fifo */
185 * Try to detect the FIFO depth if not set by interface driver, in spi_hw_init()
186 * the depth could be from 2 to 256 from HW spec in spi_hw_init()
188 if (!priv->fifo_len) { in spi_hw_init()
189 u32 fifo; in spi_hw_init() local
191 for (fifo = 1; fifo < 256; fifo++) { in spi_hw_init()
192 dw_write(priv, DW_SPI_TXFLTR, fifo); in spi_hw_init()
193 if (fifo != dw_read(priv, DW_SPI_TXFLTR)) in spi_hw_init()
197 priv->fifo_len = (fifo == 1) ? 0 : fifo; in spi_hw_init()
200 debug("%s: fifo_len=%d\n", __func__, priv->fifo_len); in spi_hw_init()
213 ret = clk_get_by_index(bus, 0, &priv->clk); in dw_spi_get_clk()
217 ret = clk_enable(&priv->clk); in dw_spi_get_clk()
218 if (ret && ret != -ENOSYS && ret != -ENOTSUPP) in dw_spi_get_clk()
221 *rate = clk_get_rate(&priv->clk); in dw_spi_get_clk()
231 clk_disable(&priv->clk); in dw_spi_get_clk()
232 clk_free(&priv->clk); in dw_spi_get_clk()
234 return -EINVAL; in dw_spi_get_clk()
242 ret = reset_get_bulk(bus, &priv->resets); in dw_spi_reset()
248 if (ret == -ENOENT || ret == -ENOTSUPP) in dw_spi_reset()
255 ret = reset_deassert_bulk(&priv->resets); in dw_spi_reset()
257 reset_release_bulk(&priv->resets); in dw_spi_reset()
271 priv->regs = plat->regs; in dw_spi_probe()
272 priv->freq = plat->frequency; in dw_spi_probe()
274 ret = dw_spi_get_clk(bus, &priv->bus_clk_rate); in dw_spi_probe()
283 priv->bits_per_word = 8; in dw_spi_probe()
285 priv->tmode = 0; /* Tx & Rx */ in dw_spi_probe()
293 /* Return the max entries we can fill into tx fifo */
298 tx_left = (priv->tx_end - priv->tx) / (priv->bits_per_word >> 3); in tx_max()
299 tx_room = priv->fifo_len - dw_read(priv, DW_SPI_TXFLR); in tx_max()
302 * Another concern is about the tx/rx mismatch, we in tx_max()
303 * thought about using (priv->fifo_len - rxflr - txflr) as in tx_max()
304 * one maximum value for tx, but it doesn't cover the in tx_max()
305 * data which is out of tx/rx fifo and inside the in tx_max()
309 rxtx_gap = ((priv->rx_end - priv->rx) - (priv->tx_end - priv->tx)) / in tx_max()
310 (priv->bits_per_word >> 3); in tx_max()
312 return min3(tx_left, tx_room, (u32)(priv->fifo_len - rxtx_gap)); in tx_max()
315 /* Return the max entries we should read out of rx fifo */
318 u32 rx_left = (priv->rx_end - priv->rx) / (priv->bits_per_word >> 3); in rx_max()
328 while (max--) { in dw_writer()
329 /* Set the tx word if the transfer's original "tx" is not null */ in dw_writer()
330 if (priv->tx_end - priv->len) { in dw_writer()
331 if (priv->bits_per_word == 8) in dw_writer()
332 txw = *(u8 *)(priv->tx); in dw_writer()
334 txw = *(u16 *)(priv->tx); in dw_writer()
337 debug("%s: tx=0x%02x\n", __func__, txw); in dw_writer()
338 priv->tx += priv->bits_per_word >> 3; in dw_writer()
347 while (max--) { in dw_reader()
352 if (priv->rx_end - priv->len) { in dw_reader()
353 if (priv->bits_per_word == 8) in dw_reader()
354 *(u8 *)(priv->rx) = rxw; in dw_reader()
356 *(u16 *)(priv->rx) = rxw; in dw_reader()
358 priv->rx += priv->bits_per_word >> 3; in dw_reader()
367 } while (priv->rx_end > priv->rx); in poll_transfer()
381 struct dw_spi_priv *priv = dev_get_priv(dev->parent); in external_cs_manage()
383 if (!dm_gpio_is_valid(&priv->cs_gpio)) in external_cs_manage()
386 dm_gpio_set_value(&priv->cs_gpio, on ? 1 : 0); in external_cs_manage()
393 struct udevice *bus = dev->parent; in dw_spi_xfer()
395 const u8 *tx = dout; in dw_spi_xfer() local
405 return -1; in dw_spi_xfer()
412 cr0 = (priv->bits_per_word - 1) | (priv->type << SPI_FRF_OFFSET) | in dw_spi_xfer()
413 (priv->mode << SPI_MODE_OFFSET) | in dw_spi_xfer()
414 (priv->tmode << SPI_TMOD_OFFSET); in dw_spi_xfer()
416 if (rx && tx) in dw_spi_xfer()
417 priv->tmode = SPI_TMOD_TR; in dw_spi_xfer()
419 priv->tmode = SPI_TMOD_RO; in dw_spi_xfer()
422 * In transmit only mode (SPI_TMOD_TO) input FIFO never gets in dw_spi_xfer()
425 priv->tmode = SPI_TMOD_TR; in dw_spi_xfer()
428 cr0 |= (priv->tmode << SPI_TMOD_OFFSET); in dw_spi_xfer()
430 priv->len = bitlen >> 3; in dw_spi_xfer()
431 debug("%s: rx=%p tx=%p len=%d [bytes]\n", __func__, rx, tx, priv->len); in dw_spi_xfer()
433 priv->tx = (void *)tx; in dw_spi_xfer()
434 priv->tx_end = priv->tx + priv->len; in dw_spi_xfer()
435 priv->rx = rx; in dw_spi_xfer()
436 priv->rx_end = priv->rx + priv->len; in dw_spi_xfer()
462 * Otherwise if some data still exists in Tx FIFO it can be in dw_spi_xfer()
467 if (readl_poll_timeout(priv->regs + DW_SPI_SR, val, in dw_spi_xfer()
470 ret = -ETIMEDOUT; in dw_spi_xfer()
482 struct dw_spi_platdata *plat = bus->platdata; in dw_spi_set_speed()
486 if (speed > plat->frequency) in dw_spi_set_speed()
487 speed = plat->frequency; in dw_spi_set_speed()
493 clk_div = priv->bus_clk_rate / speed; in dw_spi_set_speed()
500 priv->freq = speed; in dw_spi_set_speed()
501 debug("%s: regs=%p speed=%d clk_div=%d\n", __func__, priv->regs, in dw_spi_set_speed()
502 priv->freq, clk_div); in dw_spi_set_speed()
512 * Can't set mode yet. Since this depends on if rx, tx, or in dw_spi_set_mode()
513 * rx & tx is requested. So we have to defer this to the in dw_spi_set_mode()
516 priv->mode = mode; in dw_spi_set_mode()
517 debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode); in dw_spi_set_mode()
526 return reset_release_bulk(&priv->resets); in dw_spi_remove()
540 { .compatible = "snps,dw-apb-ssi" },