spi: omap2-mcspi: Revert FIFO support without DMA
MCSPI controller have few limitations regarding the transaction
size when the FIFO buffer is enabled and the WCNT feature is used
to find the end of word, in this case if WCNT is not a multiple of
the FIFO Almost Empty Level (AEL), then the FIFO empty event is not
generated correctly. In addition to this limitation, few other unknown
sequence of events that causes the FIFO empty status to not reflect the
exact status were found when FIFO is being used without DMA enabled
during extended testing in AM65x platform. Till the exact root cause
is found and fixed, revert the FIFO support without DMA.
See J721E Technical Reference Manual (SPRUI1C), section 12.1.5
for further details: http://www.ti.com/lit/pdf/spruil1
This reverts commit 75223bbea8
("spi: omap2-mcspi: Add FIFO support
without DMA")
Signed-off-by: Vaishnav Achath <vaishnav.a@ti.com>
Link: https://msgid.link/r/20240212120049.438495-1-vaishnav.a@ti.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
b3aa619a8b
commit
e56c671c22
|
@ -53,8 +53,6 @@
|
|||
|
||||
/* per-register bitmasks: */
|
||||
#define OMAP2_MCSPI_IRQSTATUS_EOW BIT(17)
|
||||
#define OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY BIT(0)
|
||||
#define OMAP2_MCSPI_IRQSTATUS_RX0_FULL BIT(2)
|
||||
|
||||
#define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0)
|
||||
#define OMAP2_MCSPI_MODULCTRL_MS BIT(2)
|
||||
|
@ -293,7 +291,7 @@ static void omap2_mcspi_set_mode(struct spi_controller *ctlr)
|
|||
}
|
||||
|
||||
static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
||||
struct spi_transfer *t, int enable, int dma_enabled)
|
||||
struct spi_transfer *t, int enable)
|
||||
{
|
||||
struct spi_controller *ctlr = spi->controller;
|
||||
struct omap2_mcspi_cs *cs = spi->controller_state;
|
||||
|
@ -314,28 +312,20 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
|||
max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH / 2;
|
||||
else
|
||||
max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH;
|
||||
if (dma_enabled)
|
||||
wcnt = t->len / bytes_per_word;
|
||||
else
|
||||
wcnt = 0;
|
||||
|
||||
wcnt = t->len / bytes_per_word;
|
||||
if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT)
|
||||
goto disable_fifo;
|
||||
|
||||
xferlevel = wcnt << 16;
|
||||
if (t->rx_buf != NULL) {
|
||||
chconf |= OMAP2_MCSPI_CHCONF_FFER;
|
||||
if (dma_enabled)
|
||||
xferlevel |= (bytes_per_word - 1) << 8;
|
||||
else
|
||||
xferlevel |= (max_fifo_depth - 1) << 8;
|
||||
xferlevel |= (bytes_per_word - 1) << 8;
|
||||
}
|
||||
|
||||
if (t->tx_buf != NULL) {
|
||||
chconf |= OMAP2_MCSPI_CHCONF_FFET;
|
||||
if (dma_enabled)
|
||||
xferlevel |= bytes_per_word - 1;
|
||||
else
|
||||
xferlevel |= (max_fifo_depth - 1);
|
||||
xferlevel |= bytes_per_word - 1;
|
||||
}
|
||||
|
||||
mcspi_write_reg(ctlr, OMAP2_MCSPI_XFERLEVEL, xferlevel);
|
||||
|
@ -892,113 +882,6 @@ out:
|
|||
return count - c;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
omap2_mcspi_txrx_piofifo(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
{
|
||||
struct omap2_mcspi_cs *cs = spi->controller_state;
|
||||
struct omap2_mcspi *mcspi;
|
||||
unsigned int count, c;
|
||||
unsigned int iter, cwc;
|
||||
int last_request;
|
||||
void __iomem *base = cs->base;
|
||||
void __iomem *tx_reg;
|
||||
void __iomem *rx_reg;
|
||||
void __iomem *chstat_reg;
|
||||
void __iomem *irqstat_reg;
|
||||
int word_len, bytes_per_word;
|
||||
u8 *rx;
|
||||
const u8 *tx;
|
||||
|
||||
mcspi = spi_controller_get_devdata(spi->controller);
|
||||
count = xfer->len;
|
||||
c = count;
|
||||
word_len = cs->word_len;
|
||||
bytes_per_word = mcspi_bytes_per_word(word_len);
|
||||
|
||||
/*
|
||||
* We store the pre-calculated register addresses on stack to speed
|
||||
* up the transfer loop.
|
||||
*/
|
||||
tx_reg = base + OMAP2_MCSPI_TX0;
|
||||
rx_reg = base + OMAP2_MCSPI_RX0;
|
||||
chstat_reg = base + OMAP2_MCSPI_CHSTAT0;
|
||||
irqstat_reg = base + OMAP2_MCSPI_IRQSTATUS;
|
||||
|
||||
if (c < (word_len >> 3))
|
||||
return 0;
|
||||
|
||||
rx = xfer->rx_buf;
|
||||
tx = xfer->tx_buf;
|
||||
|
||||
do {
|
||||
/* calculate number of words in current iteration */
|
||||
cwc = min((unsigned int)mcspi->fifo_depth / bytes_per_word,
|
||||
c / bytes_per_word);
|
||||
last_request = cwc != (mcspi->fifo_depth / bytes_per_word);
|
||||
if (tx) {
|
||||
if (mcspi_wait_for_reg_bit(irqstat_reg,
|
||||
OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY) < 0) {
|
||||
dev_err(&spi->dev, "TX Empty timed out\n");
|
||||
goto out;
|
||||
}
|
||||
writel_relaxed(OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY, irqstat_reg);
|
||||
|
||||
for (iter = 0; iter < cwc; iter++, tx += bytes_per_word) {
|
||||
if (bytes_per_word == 1)
|
||||
writel_relaxed(*tx, tx_reg);
|
||||
else if (bytes_per_word == 2)
|
||||
writel_relaxed(*((u16 *)tx), tx_reg);
|
||||
else if (bytes_per_word == 4)
|
||||
writel_relaxed(*((u32 *)tx), tx_reg);
|
||||
}
|
||||
}
|
||||
|
||||
if (rx) {
|
||||
if (!last_request &&
|
||||
mcspi_wait_for_reg_bit(irqstat_reg,
|
||||
OMAP2_MCSPI_IRQSTATUS_RX0_FULL) < 0) {
|
||||
dev_err(&spi->dev, "RX_FULL timed out\n");
|
||||
goto out;
|
||||
}
|
||||
writel_relaxed(OMAP2_MCSPI_IRQSTATUS_RX0_FULL, irqstat_reg);
|
||||
|
||||
for (iter = 0; iter < cwc; iter++, rx += bytes_per_word) {
|
||||
if (last_request &&
|
||||
mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_RXS) < 0) {
|
||||
dev_err(&spi->dev, "RXS timed out\n");
|
||||
goto out;
|
||||
}
|
||||
if (bytes_per_word == 1)
|
||||
*rx = readl_relaxed(rx_reg);
|
||||
else if (bytes_per_word == 2)
|
||||
*((u16 *)rx) = readl_relaxed(rx_reg);
|
||||
else if (bytes_per_word == 4)
|
||||
*((u32 *)rx) = readl_relaxed(rx_reg);
|
||||
}
|
||||
}
|
||||
|
||||
if (last_request) {
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_EOT) < 0) {
|
||||
dev_err(&spi->dev, "EOT timed out\n");
|
||||
goto out;
|
||||
}
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_TXFFE) < 0) {
|
||||
dev_err(&spi->dev, "TXFFE timed out\n");
|
||||
goto out;
|
||||
}
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
}
|
||||
c -= cwc * bytes_per_word;
|
||||
} while (c >= bytes_per_word);
|
||||
|
||||
out:
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
return count - c;
|
||||
}
|
||||
|
||||
static u32 omap2_mcspi_calc_divisor(u32 speed_hz, u32 ref_clk_hz)
|
||||
{
|
||||
u32 div;
|
||||
|
@ -1323,9 +1206,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
|||
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
|
||||
ctlr->cur_msg_mapped &&
|
||||
ctlr->can_dma(ctlr, spi, t))
|
||||
omap2_mcspi_set_fifo(spi, t, 1, 1);
|
||||
else if (t->len > OMAP2_MCSPI_MAX_FIFODEPTH)
|
||||
omap2_mcspi_set_fifo(spi, t, 1, 0);
|
||||
omap2_mcspi_set_fifo(spi, t, 1);
|
||||
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
|
||||
|
@ -1338,8 +1219,6 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
|||
ctlr->cur_msg_mapped &&
|
||||
ctlr->can_dma(ctlr, spi, t))
|
||||
count = omap2_mcspi_txrx_dma(spi, t);
|
||||
else if (mcspi->fifo_depth > 0)
|
||||
count = omap2_mcspi_txrx_piofifo(spi, t);
|
||||
else
|
||||
count = omap2_mcspi_txrx_pio(spi, t);
|
||||
|
||||
|
@ -1352,7 +1231,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
|||
omap2_mcspi_set_enable(spi, 0);
|
||||
|
||||
if (mcspi->fifo_depth > 0)
|
||||
omap2_mcspi_set_fifo(spi, t, 0, 0);
|
||||
omap2_mcspi_set_fifo(spi, t, 0);
|
||||
|
||||
out:
|
||||
/* Restore defaults if they were overriden */
|
||||
|
@ -1375,7 +1254,7 @@ out:
|
|||
omap2_mcspi_set_cs(spi, !(spi->mode & SPI_CS_HIGH));
|
||||
|
||||
if (mcspi->fifo_depth > 0 && t)
|
||||
omap2_mcspi_set_fifo(spi, t, 0, 0);
|
||||
omap2_mcspi_set_fifo(spi, t, 0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue