Skip to content

Commit

Permalink
Merge tag 'spi-fix-v6.4-rc3' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/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
  • Loading branch information
Linus Torvalds committed May 24, 2023
2 parents f767b33 + 6afe2ae commit 933174a
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 65 deletions.
1 change: 0 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
105 changes: 45 additions & 60 deletions drivers/spi/spi-cadence.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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 (xspi->txbuf)
cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
else
cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
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;

/* 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--;
if (nrx) {
u8 data = cdns_spi_read(xspi, CDNS_SPI_RXD);

if (xspi->rxbuf)
*xspi->rxbuf++ = data;

nrx--;
}
}
}

Expand Down Expand Up @@ -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);
if (xspi->tx_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);
Expand Down Expand Up @@ -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)
cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
}

/* 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))
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);
Expand Down
8 changes: 4 additions & 4 deletions drivers/spi/spi-dw-mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions drivers/spi/spi-geni-qcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 933174a

Please sign in to comment.