Commit 933174ae authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-fix-v6.4-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi fixes from Mark Brown:
 "A collection of fixes that came in since the merge window, plus an
  update to MAINTAINERS.

  The Cadence fixes are coming from the addition of device mode support,
  they required a couple of incremental updates in order to get
  something that works robustly for both device and controller modes"

* tag 'spi-fix-v6.4-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: spi-cadence: Interleave write of TX and read of RX FIFO
  spi: dw: Replace spi->chip_select references with function calls
  spi: MAINTAINERS: drop Krzysztof Kozlowski from Samsung SPI
  spi: spi-cadence: Only overlap FIFO transactions in slave mode
  spi: spi-cadence: Avoid read of RX FIFO before its ready
  spi: spi-geni-qcom: Select FIFO mode for chip select
parents f767b330 6afe2ae8
......@@ -18703,7 +18703,6 @@ F: include/dt-bindings/clock/samsung,*.h
F: include/linux/clk/samsung.h
SAMSUNG SPI DRIVERS
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
M: Andi Shyti <andi.shyti@kernel.org>
L: linux-spi@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
......
......@@ -12,6 +12,7 @@
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
......@@ -301,49 +302,43 @@ static int cdns_spi_setup_transfer(struct spi_device *spi,
}
/**
* cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
* cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO
* @xspi: Pointer to the cdns_spi structure
* @ntx: Number of bytes to pack into the TX FIFO
* @nrx: Number of bytes to drain from the RX FIFO
*/
static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)
{
unsigned long trans_cnt = 0;
ntx = clamp(ntx, 0, xspi->tx_bytes);
nrx = clamp(nrx, 0, xspi->rx_bytes);
while ((trans_cnt < xspi->tx_fifo_depth) &&
(xspi->tx_bytes > 0)) {
xspi->tx_bytes -= ntx;
xspi->rx_bytes -= nrx;
while (ntx || nrx) {
/* When xspi in busy condition, bytes may send failed,
* then spi control did't work thoroughly, add one byte delay
*/
if (cdns_spi_read(xspi, CDNS_SPI_ISR) &
CDNS_SPI_IXR_TXFULL)
if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
udelay(10);
if (ntx) {
if (xspi->txbuf)
cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
else
cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
xspi->tx_bytes--;
trans_cnt++;
ntx--;
}
}
/**
* cdns_spi_read_rx_fifo - Reads the RX FIFO with as many bytes as possible
* @xspi: Pointer to the cdns_spi structure
* @count: Read byte count
*/
static void cdns_spi_read_rx_fifo(struct cdns_spi *xspi, unsigned long count)
{
u8 data;
if (nrx) {
u8 data = cdns_spi_read(xspi, CDNS_SPI_RXD);
/* Read out the data from the RX FIFO */
while (count > 0) {
data = cdns_spi_read(xspi, CDNS_SPI_RXD);
if (xspi->rxbuf)
*xspi->rxbuf++ = data;
xspi->rx_bytes--;
count--;
nrx--;
}
}
}
......@@ -381,33 +376,22 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
spi_finalize_current_transfer(ctlr);
status = IRQ_HANDLED;
} else if (intr_status & CDNS_SPI_IXR_TXOW) {
int trans_cnt = cdns_spi_read(xspi, CDNS_SPI_THLD);
int threshold = cdns_spi_read(xspi, CDNS_SPI_THLD);
int trans_cnt = xspi->rx_bytes - xspi->tx_bytes;
if (threshold > 1)
trans_cnt -= threshold;
/* Set threshold to one if number of pending are
* less than half fifo
*/
if (xspi->tx_bytes < xspi->tx_fifo_depth >> 1)
cdns_spi_write(xspi, CDNS_SPI_THLD, 1);
while (trans_cnt) {
cdns_spi_read_rx_fifo(xspi, 1);
if (xspi->tx_bytes) {
if (xspi->txbuf)
cdns_spi_write(xspi, CDNS_SPI_TXD,
*xspi->txbuf++);
else
cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
xspi->tx_bytes--;
}
trans_cnt--;
}
if (!xspi->tx_bytes) {
/* Fixed delay due to controller limitation with
* RX_NEMPTY incorrect status
* Xilinx AR:65885 contains more details
*/
udelay(10);
cdns_spi_read_rx_fifo(xspi, xspi->rx_bytes);
cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt);
} else {
cdns_spi_process_fifo(xspi, 0, trans_cnt);
cdns_spi_write(xspi, CDNS_SPI_IDR,
CDNS_SPI_IXR_DEFAULT);
spi_finalize_current_transfer(ctlr);
......@@ -450,16 +434,17 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
xspi->tx_bytes = transfer->len;
xspi->rx_bytes = transfer->len;
if (!spi_controller_is_slave(ctlr))
if (!spi_controller_is_slave(ctlr)) {
cdns_spi_setup_transfer(spi, transfer);
} else {
/* Set TX empty threshold to half of FIFO depth
* only if TX bytes are more than half FIFO depth.
*/
if (xspi->tx_bytes > (xspi->tx_fifo_depth >> 1))
if (xspi->tx_bytes > xspi->tx_fifo_depth)
cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
}
cdns_spi_fill_tx_fifo(xspi);
cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0);
spi_transfer_delay_exec(transfer);
cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT);
......
......@@ -264,17 +264,17 @@ static void dw_spi_elba_set_cs(struct spi_device *spi, bool enable)
struct regmap *syscon = dwsmmio->priv;
u8 cs;
cs = spi->chip_select;
cs = spi_get_chipselect(spi, 0);
if (cs < 2)
dw_spi_elba_override_cs(syscon, spi->chip_select, enable);
dw_spi_elba_override_cs(syscon, spi_get_chipselect(spi, 0), enable);
/*
* The DW SPI controller needs a native CS bit selected to start
* the serial engine.
*/
spi->chip_select = 0;
spi_set_chipselect(spi, 0, 0);
dw_spi_set_cs(spi, enable);
spi->chip_select = cs;
spi_get_chipselect(spi, cs);
}
static int dw_spi_elba_init(struct platform_device *pdev,
......
......@@ -294,6 +294,8 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
mas->cs_flag = set_flag;
/* set xfer_mode to FIFO to complete cs_done in isr */
mas->cur_xfer_mode = GENI_SE_FIFO;
geni_se_select_mode(se, mas->cur_xfer_mode);
reinit_completion(&mas->cs_done);
if (set_flag)
geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment