Skip to content

Commit 75223bb

Browse files
vaishnavachathbroonie
authored andcommitted
spi: omap2-mcspi: Add FIFO support without DMA
Currently, the built-in 64-byte FIFO on the MCSPI controller is not enabled in PIO mode and is used only when DMA is enabled. Enable the FIFO in PIO mode by default for transactions larger than the FIFO depth and fallback only if FIFO is not available. When DMA is not enabled, it is efficient to enable the RX FIFO almost full and TX FIFO almost empty events after each FIFO fill instead of each word. Update omap2_mcspi_set_fifo() to enable the events accordingly and also rely on OMAP2_MCSPI_CHSTAT_RXS for the last transfer instead of the FIFO events to handle the case when the transfer size is not a multiple of FIFO depth. See J721E Technical Reference Manual (SPRUI1C), section 12.1.5 for further details: http://www.ti.com/lit/pdf/spruil1 Signed-off-by: Vaishnav Achath <vaishnav.a@ti.com> Link: https://lore.kernel.org/r/20231013092629.19005-1-vaishnav.a@ti.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 6922250 commit 75223bb

File tree

1 file changed

+129
-8
lines changed

1 file changed

+129
-8
lines changed

drivers/spi/spi-omap2-mcspi.c

Lines changed: 129 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353

5454
/* per-register bitmasks: */
5555
#define OMAP2_MCSPI_IRQSTATUS_EOW BIT(17)
56+
#define OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY BIT(0)
57+
#define OMAP2_MCSPI_IRQSTATUS_RX0_FULL BIT(2)
5658

5759
#define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0)
5860
#define OMAP2_MCSPI_MODULCTRL_MS BIT(2)
@@ -291,7 +293,7 @@ static void omap2_mcspi_set_mode(struct spi_controller *ctlr)
291293
}
292294

293295
static void omap2_mcspi_set_fifo(const struct spi_device *spi,
294-
struct spi_transfer *t, int enable)
296+
struct spi_transfer *t, int enable, int dma_enabled)
295297
{
296298
struct spi_controller *ctlr = spi->controller;
297299
struct omap2_mcspi_cs *cs = spi->controller_state;
@@ -312,20 +314,28 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi,
312314
max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH / 2;
313315
else
314316
max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH;
315-
316-
wcnt = t->len / bytes_per_word;
317+
if (dma_enabled)
318+
wcnt = t->len / bytes_per_word;
319+
else
320+
wcnt = 0;
317321
if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT)
318322
goto disable_fifo;
319323

320324
xferlevel = wcnt << 16;
321325
if (t->rx_buf != NULL) {
322326
chconf |= OMAP2_MCSPI_CHCONF_FFER;
323-
xferlevel |= (bytes_per_word - 1) << 8;
327+
if (dma_enabled)
328+
xferlevel |= (bytes_per_word - 1) << 8;
329+
else
330+
xferlevel |= (max_fifo_depth - 1) << 8;
324331
}
325332

326333
if (t->tx_buf != NULL) {
327334
chconf |= OMAP2_MCSPI_CHCONF_FFET;
328-
xferlevel |= bytes_per_word - 1;
335+
if (dma_enabled)
336+
xferlevel |= bytes_per_word - 1;
337+
else
338+
xferlevel |= (max_fifo_depth - 1);
329339
}
330340

331341
mcspi_write_reg(ctlr, OMAP2_MCSPI_XFERLEVEL, xferlevel);
@@ -882,6 +892,113 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
882892
return count - c;
883893
}
884894

895+
static unsigned
896+
omap2_mcspi_txrx_piofifo(struct spi_device *spi, struct spi_transfer *xfer)
897+
{
898+
struct omap2_mcspi_cs *cs = spi->controller_state;
899+
struct omap2_mcspi *mcspi;
900+
unsigned int count, c;
901+
unsigned int iter, cwc;
902+
int last_request;
903+
void __iomem *base = cs->base;
904+
void __iomem *tx_reg;
905+
void __iomem *rx_reg;
906+
void __iomem *chstat_reg;
907+
void __iomem *irqstat_reg;
908+
int word_len, bytes_per_word;
909+
u8 *rx;
910+
const u8 *tx;
911+
912+
mcspi = spi_controller_get_devdata(spi->controller);
913+
count = xfer->len;
914+
c = count;
915+
word_len = cs->word_len;
916+
bytes_per_word = mcspi_bytes_per_word(word_len);
917+
918+
/*
919+
* We store the pre-calculated register addresses on stack to speed
920+
* up the transfer loop.
921+
*/
922+
tx_reg = base + OMAP2_MCSPI_TX0;
923+
rx_reg = base + OMAP2_MCSPI_RX0;
924+
chstat_reg = base + OMAP2_MCSPI_CHSTAT0;
925+
irqstat_reg = base + OMAP2_MCSPI_IRQSTATUS;
926+
927+
if (c < (word_len >> 3))
928+
return 0;
929+
930+
rx = xfer->rx_buf;
931+
tx = xfer->tx_buf;
932+
933+
do {
934+
/* calculate number of words in current iteration */
935+
cwc = min((unsigned int)mcspi->fifo_depth / bytes_per_word,
936+
c / bytes_per_word);
937+
last_request = cwc != (mcspi->fifo_depth / bytes_per_word);
938+
if (tx) {
939+
if (mcspi_wait_for_reg_bit(irqstat_reg,
940+
OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY) < 0) {
941+
dev_err(&spi->dev, "TX Empty timed out\n");
942+
goto out;
943+
}
944+
writel_relaxed(OMAP2_MCSPI_IRQSTATUS_TX0_EMPTY, irqstat_reg);
945+
946+
for (iter = 0; iter < cwc; iter++, tx += bytes_per_word) {
947+
if (bytes_per_word == 1)
948+
writel_relaxed(*tx, tx_reg);
949+
else if (bytes_per_word == 2)
950+
writel_relaxed(*((u16 *)tx), tx_reg);
951+
else if (bytes_per_word == 4)
952+
writel_relaxed(*((u32 *)tx), tx_reg);
953+
}
954+
}
955+
956+
if (rx) {
957+
if (!last_request &&
958+
mcspi_wait_for_reg_bit(irqstat_reg,
959+
OMAP2_MCSPI_IRQSTATUS_RX0_FULL) < 0) {
960+
dev_err(&spi->dev, "RX_FULL timed out\n");
961+
goto out;
962+
}
963+
writel_relaxed(OMAP2_MCSPI_IRQSTATUS_RX0_FULL, irqstat_reg);
964+
965+
for (iter = 0; iter < cwc; iter++, rx += bytes_per_word) {
966+
if (last_request &&
967+
mcspi_wait_for_reg_bit(chstat_reg,
968+
OMAP2_MCSPI_CHSTAT_RXS) < 0) {
969+
dev_err(&spi->dev, "RXS timed out\n");
970+
goto out;
971+
}
972+
if (bytes_per_word == 1)
973+
*rx = readl_relaxed(rx_reg);
974+
else if (bytes_per_word == 2)
975+
*((u16 *)rx) = readl_relaxed(rx_reg);
976+
else if (bytes_per_word == 4)
977+
*((u32 *)rx) = readl_relaxed(rx_reg);
978+
}
979+
}
980+
981+
if (last_request) {
982+
if (mcspi_wait_for_reg_bit(chstat_reg,
983+
OMAP2_MCSPI_CHSTAT_EOT) < 0) {
984+
dev_err(&spi->dev, "EOT timed out\n");
985+
goto out;
986+
}
987+
if (mcspi_wait_for_reg_bit(chstat_reg,
988+
OMAP2_MCSPI_CHSTAT_TXFFE) < 0) {
989+
dev_err(&spi->dev, "TXFFE timed out\n");
990+
goto out;
991+
}
992+
omap2_mcspi_set_enable(spi, 0);
993+
}
994+
c -= cwc * bytes_per_word;
995+
} while (c >= bytes_per_word);
996+
997+
out:
998+
omap2_mcspi_set_enable(spi, 1);
999+
return count - c;
1000+
}
1001+
8851002
static u32 omap2_mcspi_calc_divisor(u32 speed_hz, u32 ref_clk_hz)
8861003
{
8871004
u32 div;
@@ -1206,7 +1323,9 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
12061323
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
12071324
ctlr->cur_msg_mapped &&
12081325
ctlr->can_dma(ctlr, spi, t))
1209-
omap2_mcspi_set_fifo(spi, t, 1);
1326+
omap2_mcspi_set_fifo(spi, t, 1, 1);
1327+
else if (t->len > OMAP2_MCSPI_MAX_FIFODEPTH)
1328+
omap2_mcspi_set_fifo(spi, t, 1, 0);
12101329

12111330
omap2_mcspi_set_enable(spi, 1);
12121331

@@ -1219,6 +1338,8 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
12191338
ctlr->cur_msg_mapped &&
12201339
ctlr->can_dma(ctlr, spi, t))
12211340
count = omap2_mcspi_txrx_dma(spi, t);
1341+
else if (mcspi->fifo_depth > 0)
1342+
count = omap2_mcspi_txrx_piofifo(spi, t);
12221343
else
12231344
count = omap2_mcspi_txrx_pio(spi, t);
12241345

@@ -1231,7 +1352,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
12311352
omap2_mcspi_set_enable(spi, 0);
12321353

12331354
if (mcspi->fifo_depth > 0)
1234-
omap2_mcspi_set_fifo(spi, t, 0);
1355+
omap2_mcspi_set_fifo(spi, t, 0, 0);
12351356

12361357
out:
12371358
/* Restore defaults if they were overriden */
@@ -1254,7 +1375,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
12541375
omap2_mcspi_set_cs(spi, !(spi->mode & SPI_CS_HIGH));
12551376

12561377
if (mcspi->fifo_depth > 0 && t)
1257-
omap2_mcspi_set_fifo(spi, t, 0);
1378+
omap2_mcspi_set_fifo(spi, t, 0, 0);
12581379

12591380
return status;
12601381
}

0 commit comments

Comments
 (0)