Skip to content

Commit 1673c81

Browse files
jiada-wangbroonie
authored andcommitted
spi: imx: dynamic burst length adjust for PIO mode
previously burst length (BURST_LENGTH) is always set to equal to bits_per_word, causes a 10us gap between each word in transfer, which significantly affects performance. This patch uses 32 bits transfer to simulate lower bits transfer, and adjusts burst length runtimely to use biggeest burst length as possible to reduce the gaps in transfer for PIO mode. Signed-off-by: Jiada Wang <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent ab2f357 commit 1673c81

File tree

1 file changed

+141
-9
lines changed

1 file changed

+141
-9
lines changed

drivers/spi/spi-imx.c

Lines changed: 141 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656

5757
/* The maximum bytes that a sdma BD can transfer.*/
5858
#define MAX_SDMA_BD_BYTES (1 << 15)
59+
#define MX51_ECSPI_CTRL_MAX_BURST 512
5960

6061
enum spi_imx_devtype {
6162
IMX1_CSPI,
@@ -77,6 +78,7 @@ struct spi_imx_devtype_data {
7778
void (*reset)(struct spi_imx_data *);
7879
bool has_dmamode;
7980
unsigned int fifo_size;
81+
bool dynamic_burst;
8082
enum spi_imx_devtype devtype;
8183
};
8284

@@ -97,12 +99,14 @@ struct spi_imx_data {
9799
unsigned int bits_per_word;
98100
unsigned int spi_drctl;
99101

100-
unsigned int count;
102+
unsigned int count, remainder;
101103
void (*tx)(struct spi_imx_data *);
102104
void (*rx)(struct spi_imx_data *);
103105
void *rx_buf;
104106
const void *tx_buf;
105107
unsigned int txfifo; /* number of words pushed in tx FIFO */
108+
unsigned int dynamic_burst, read_u32;
109+
unsigned int word_mask;
106110

107111
/* DMA */
108112
bool usedma;
@@ -231,6 +235,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
231235
return false;
232236

233237
spi_imx->wml = i;
238+
spi_imx->dynamic_burst = 0;
234239

235240
return true;
236241
}
@@ -245,6 +250,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
245250
#define MX51_ECSPI_CTRL_PREDIV_OFFSET 12
246251
#define MX51_ECSPI_CTRL_CS(cs) ((cs) << 18)
247252
#define MX51_ECSPI_CTRL_BL_OFFSET 20
253+
#define MX51_ECSPI_CTRL_BL_MASK (0xfff << 20)
248254

249255
#define MX51_ECSPI_CONFIG 0x0c
250256
#define MX51_ECSPI_CONFIG_SCLKPHA(cs) (1 << ((cs) + 0))
@@ -272,6 +278,102 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
272278
#define MX51_ECSPI_TESTREG 0x20
273279
#define MX51_ECSPI_TESTREG_LBC BIT(31)
274280

281+
static void spi_imx_buf_rx_swap_u32(struct spi_imx_data *spi_imx)
282+
{
283+
unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA);
284+
unsigned int bytes_per_word;
285+
286+
if (spi_imx->rx_buf) {
287+
#ifdef __LITTLE_ENDIAN
288+
bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
289+
if (bytes_per_word == 1)
290+
val = cpu_to_be32(val);
291+
else if (bytes_per_word == 2)
292+
val = (val << 16) | (val >> 16);
293+
#endif
294+
val &= spi_imx->word_mask;
295+
*(u32 *)spi_imx->rx_buf = val;
296+
spi_imx->rx_buf += sizeof(u32);
297+
}
298+
}
299+
300+
static void spi_imx_buf_rx_swap(struct spi_imx_data *spi_imx)
301+
{
302+
unsigned int bytes_per_word;
303+
304+
bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
305+
if (spi_imx->read_u32) {
306+
spi_imx_buf_rx_swap_u32(spi_imx);
307+
return;
308+
}
309+
310+
if (bytes_per_word == 1)
311+
spi_imx_buf_rx_u8(spi_imx);
312+
else if (bytes_per_word == 2)
313+
spi_imx_buf_rx_u16(spi_imx);
314+
}
315+
316+
static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
317+
{
318+
u32 val = 0;
319+
unsigned int bytes_per_word;
320+
321+
if (spi_imx->tx_buf) {
322+
val = *(u32 *)spi_imx->tx_buf;
323+
val &= spi_imx->word_mask;
324+
spi_imx->tx_buf += sizeof(u32);
325+
}
326+
327+
spi_imx->count -= sizeof(u32);
328+
#ifdef __LITTLE_ENDIAN
329+
bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
330+
331+
if (bytes_per_word == 1)
332+
val = cpu_to_be32(val);
333+
else if (bytes_per_word == 2)
334+
val = (val << 16) | (val >> 16);
335+
#endif
336+
writel(val, spi_imx->base + MXC_CSPITXDATA);
337+
}
338+
339+
static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx)
340+
{
341+
u32 ctrl, val;
342+
unsigned int bytes_per_word;
343+
344+
if (spi_imx->count == spi_imx->remainder) {
345+
ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL);
346+
ctrl &= ~MX51_ECSPI_CTRL_BL_MASK;
347+
if (spi_imx->count > MX51_ECSPI_CTRL_MAX_BURST) {
348+
spi_imx->remainder = spi_imx->count %
349+
MX51_ECSPI_CTRL_MAX_BURST;
350+
val = MX51_ECSPI_CTRL_MAX_BURST * 8 - 1;
351+
} else if (spi_imx->count >= sizeof(u32)) {
352+
spi_imx->remainder = spi_imx->count % sizeof(u32);
353+
val = (spi_imx->count - spi_imx->remainder) * 8 - 1;
354+
} else {
355+
spi_imx->remainder = 0;
356+
val = spi_imx->bits_per_word - 1;
357+
spi_imx->read_u32 = 0;
358+
}
359+
360+
ctrl |= (val << MX51_ECSPI_CTRL_BL_OFFSET);
361+
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
362+
}
363+
364+
if (spi_imx->count >= sizeof(u32)) {
365+
spi_imx_buf_tx_swap_u32(spi_imx);
366+
return;
367+
}
368+
369+
bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
370+
371+
if (bytes_per_word == 1)
372+
spi_imx_buf_tx_u8(spi_imx);
373+
else if (bytes_per_word == 2)
374+
spi_imx_buf_tx_u16(spi_imx);
375+
}
376+
275377
/* MX51 eCSPI */
276378
static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx,
277379
unsigned int fspi, unsigned int *fres)
@@ -698,6 +800,7 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
698800
.reset = mx1_reset,
699801
.fifo_size = 8,
700802
.has_dmamode = false,
803+
.dynamic_burst = false,
701804
.devtype = IMX1_CSPI,
702805
};
703806

@@ -709,6 +812,7 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
709812
.reset = mx21_reset,
710813
.fifo_size = 8,
711814
.has_dmamode = false,
815+
.dynamic_burst = false,
712816
.devtype = IMX21_CSPI,
713817
};
714818

@@ -721,6 +825,7 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
721825
.reset = mx21_reset,
722826
.fifo_size = 8,
723827
.has_dmamode = false,
828+
.dynamic_burst = false,
724829
.devtype = IMX27_CSPI,
725830
};
726831

@@ -732,6 +837,7 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
732837
.reset = mx31_reset,
733838
.fifo_size = 8,
734839
.has_dmamode = false,
840+
.dynamic_burst = false,
735841
.devtype = IMX31_CSPI,
736842
};
737843

@@ -744,6 +850,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
744850
.reset = mx31_reset,
745851
.fifo_size = 8,
746852
.has_dmamode = true,
853+
.dynamic_burst = false,
747854
.devtype = IMX35_CSPI,
748855
};
749856

@@ -755,6 +862,7 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
755862
.reset = mx51_ecspi_reset,
756863
.fifo_size = 64,
757864
.has_dmamode = true,
865+
.dynamic_burst = true,
758866
.devtype = IMX51_ECSPI,
759867
};
760868

@@ -827,6 +935,8 @@ static void spi_imx_push(struct spi_imx_data *spi_imx)
827935
while (spi_imx->txfifo < spi_imx->devtype_data->fifo_size) {
828936
if (!spi_imx->count)
829937
break;
938+
if (spi_imx->txfifo && (spi_imx->count == spi_imx->remainder))
939+
break;
830940
spi_imx->tx(spi_imx);
831941
spi_imx->txfifo++;
832942
}
@@ -920,15 +1030,37 @@ static int spi_imx_setupxfer(struct spi_device *spi,
9201030
spi_imx->speed_hz = t->speed_hz;
9211031

9221032
/* Initialize the functions for transfer */
923-
if (spi_imx->bits_per_word <= 8) {
924-
spi_imx->rx = spi_imx_buf_rx_u8;
925-
spi_imx->tx = spi_imx_buf_tx_u8;
926-
} else if (spi_imx->bits_per_word <= 16) {
927-
spi_imx->rx = spi_imx_buf_rx_u16;
928-
spi_imx->tx = spi_imx_buf_tx_u16;
1033+
if (spi_imx->devtype_data->dynamic_burst) {
1034+
u32 mask;
1035+
1036+
spi_imx->dynamic_burst = 0;
1037+
spi_imx->remainder = 0;
1038+
spi_imx->read_u32 = 1;
1039+
1040+
mask = (1 << spi_imx->bits_per_word) - 1;
1041+
spi_imx->rx = spi_imx_buf_rx_swap;
1042+
spi_imx->tx = spi_imx_buf_tx_swap;
1043+
spi_imx->dynamic_burst = 1;
1044+
spi_imx->remainder = t->len;
1045+
1046+
if (spi_imx->bits_per_word <= 8)
1047+
spi_imx->word_mask = mask << 24 | mask << 16
1048+
| mask << 8 | mask;
1049+
else if (spi_imx->bits_per_word <= 16)
1050+
spi_imx->word_mask = mask << 16 | mask;
1051+
else
1052+
spi_imx->word_mask = mask;
9291053
} else {
930-
spi_imx->rx = spi_imx_buf_rx_u32;
931-
spi_imx->tx = spi_imx_buf_tx_u32;
1054+
if (spi_imx->bits_per_word <= 8) {
1055+
spi_imx->rx = spi_imx_buf_rx_u8;
1056+
spi_imx->tx = spi_imx_buf_tx_u8;
1057+
} else if (spi_imx->bits_per_word <= 16) {
1058+
spi_imx->rx = spi_imx_buf_rx_u16;
1059+
spi_imx->tx = spi_imx_buf_tx_u16;
1060+
} else {
1061+
spi_imx->rx = spi_imx_buf_rx_u32;
1062+
spi_imx->tx = spi_imx_buf_tx_u32;
1063+
}
9321064
}
9331065

9341066
if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t))

0 commit comments

Comments
 (0)