Skip to content

Commit fc96ec8

Browse files
chleroybroonie
authored andcommitted
spi: fsl-cpm: Use 16 bit mode for large transfers with even size
On CPM, the RISC core is a lot more efficiant when doing transfers in 16-bits chunks than in 8-bits chunks, but unfortunately the words need to be byte swapped as seen in a previous commit. So, for large tranfers with an even size, allocate a temporary tx buffer and byte-swap data before and after transfer. This change allows setting higher speed for transfer. For instance on an MPC 8xx (CPM1 comms RISC processor), the documentation tells that transfer in byte mode at 1 kbit/s uses 0.200% of CPM load at 25 MHz while a word transfer at the same speed uses 0.032% of CPM load. This means the speed can be 6 times higher in word mode for the same CPM load. For the time being, only do it on CPM1 as there must be a trade-off between the CPM load reduction and the CPU load required to byte swap the data. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Link: https://lore.kernel.org/r/f2e981f20f92dd28983c3949702a09248c23845c.1680371809.git.christophe.leroy@csgroup.eu Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 8a5299a commit fc96ec8

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

drivers/spi/spi-fsl-cpm.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/spi/spi.h>
2222
#include <linux/types.h>
2323
#include <linux/platform_device.h>
24+
#include <linux/byteorder/generic.h>
2425

2526
#include "spi-fsl-cpm.h"
2627
#include "spi-fsl-lib.h"
@@ -120,6 +121,21 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
120121
mspi->rx_dma = mspi->dma_dummy_rx;
121122
mspi->map_rx_dma = 0;
122123
}
124+
if (t->bits_per_word == 16 && t->tx_buf) {
125+
const u16 *src = t->tx_buf;
126+
u16 *dst;
127+
int i;
128+
129+
dst = kmalloc(t->len, GFP_KERNEL);
130+
if (!dst)
131+
return -ENOMEM;
132+
133+
for (i = 0; i < t->len >> 1; i++)
134+
dst[i] = cpu_to_le16p(src + i);
135+
136+
mspi->tx = dst;
137+
mspi->map_tx_dma = 1;
138+
}
123139

124140
if (mspi->map_tx_dma) {
125141
void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
@@ -173,6 +189,13 @@ void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
173189
if (mspi->map_rx_dma)
174190
dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
175191
mspi->xfer_in_progress = NULL;
192+
193+
if (t->bits_per_word == 16 && t->rx_buf) {
194+
int i;
195+
196+
for (i = 0; i < t->len; i += 2)
197+
le16_to_cpus(t->rx_buf + i);
198+
}
176199
}
177200
EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs_complete);
178201

drivers/spi/spi-fsl-spi.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ static int fsl_spi_prepare_message(struct spi_controller *ctlr,
351351
return -EINVAL;
352352
if (t->bits_per_word == 16 || t->bits_per_word == 32)
353353
t->bits_per_word = 8; /* pretend its 8 bits */
354+
if (t->bits_per_word == 8 && t->len >= 256 &&
355+
(mpc8xxx_spi->flags & SPI_CPM1))
356+
t->bits_per_word = 16;
354357
}
355358
}
356359
return fsl_spi_setup_transfer(m->spi, first);

0 commit comments

Comments
 (0)