diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2011-01-21 10:56:42 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-01-21 12:02:35 -0500 |
commit | 9dabb3f3269d042908bf1f4e685413c39cc8c373 (patch) | |
tree | a6913470397af37729670966b9683aec48edb525 /drivers/spi | |
parent | e2dbf5ebcc983b0349ab507bf7dd5562cf88dd24 (diff) |
spi/spi_sh_msiof: consolidate data in 8-bit mode into 32-bit words
Instead of sending data 8 bits at a time in 8-bit SPI mode, swap bytes
and send and receive them 32 bits at a time. Tested with an SD-card,
with which this patch reduced the number of interrupts by 50%, when
reading 5MiB of data (there are also small service packets, the number
of interrupts, produced by 512-byte sectors should, of course, drop by
75%), and improved throughput by more than 40%.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi_sh_msiof.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi_sh_msiof.c index d220cb287874..da6e42ec856e 100644 --- a/drivers/spi/spi_sh_msiof.c +++ b/drivers/spi/spi_sh_msiof.c | |||
@@ -267,6 +267,26 @@ static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p, | |||
267 | sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs); | 267 | sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs); |
268 | } | 268 | } |
269 | 269 | ||
270 | static void sh_msiof_spi_write_fifo_s32(struct sh_msiof_spi_priv *p, | ||
271 | const void *tx_buf, int words, int fs) | ||
272 | { | ||
273 | const u32 *buf_32 = tx_buf; | ||
274 | int k; | ||
275 | |||
276 | for (k = 0; k < words; k++) | ||
277 | sh_msiof_write(p, TFDR, swab32(buf_32[k] << fs)); | ||
278 | } | ||
279 | |||
280 | static void sh_msiof_spi_write_fifo_s32u(struct sh_msiof_spi_priv *p, | ||
281 | const void *tx_buf, int words, int fs) | ||
282 | { | ||
283 | const u32 *buf_32 = tx_buf; | ||
284 | int k; | ||
285 | |||
286 | for (k = 0; k < words; k++) | ||
287 | sh_msiof_write(p, TFDR, swab32(get_unaligned(&buf_32[k]) << fs)); | ||
288 | } | ||
289 | |||
270 | static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p, | 290 | static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p, |
271 | void *rx_buf, int words, int fs) | 291 | void *rx_buf, int words, int fs) |
272 | { | 292 | { |
@@ -317,6 +337,26 @@ static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p, | |||
317 | put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]); | 337 | put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]); |
318 | } | 338 | } |
319 | 339 | ||
340 | static void sh_msiof_spi_read_fifo_s32(struct sh_msiof_spi_priv *p, | ||
341 | void *rx_buf, int words, int fs) | ||
342 | { | ||
343 | u32 *buf_32 = rx_buf; | ||
344 | int k; | ||
345 | |||
346 | for (k = 0; k < words; k++) | ||
347 | buf_32[k] = swab32(sh_msiof_read(p, RFDR) >> fs); | ||
348 | } | ||
349 | |||
350 | static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p, | ||
351 | void *rx_buf, int words, int fs) | ||
352 | { | ||
353 | u32 *buf_32 = rx_buf; | ||
354 | int k; | ||
355 | |||
356 | for (k = 0; k < words; k++) | ||
357 | put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]); | ||
358 | } | ||
359 | |||
320 | static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t) | 360 | static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t) |
321 | { | 361 | { |
322 | int bits; | 362 | int bits; |
@@ -468,9 +508,17 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t) | |||
468 | int bytes_done; | 508 | int bytes_done; |
469 | int words; | 509 | int words; |
470 | int n; | 510 | int n; |
511 | bool swab; | ||
471 | 512 | ||
472 | bits = sh_msiof_spi_bits(spi, t); | 513 | bits = sh_msiof_spi_bits(spi, t); |
473 | 514 | ||
515 | if (bits <= 8 && t->len > 15 && !(t->len & 3)) { | ||
516 | bits = 32; | ||
517 | swab = true; | ||
518 | } else { | ||
519 | swab = false; | ||
520 | } | ||
521 | |||
474 | /* setup bytes per word and fifo read/write functions */ | 522 | /* setup bytes per word and fifo read/write functions */ |
475 | if (bits <= 8) { | 523 | if (bits <= 8) { |
476 | bytes_per_word = 1; | 524 | bytes_per_word = 1; |
@@ -487,6 +535,17 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t) | |||
487 | rx_fifo = sh_msiof_spi_read_fifo_16u; | 535 | rx_fifo = sh_msiof_spi_read_fifo_16u; |
488 | else | 536 | else |
489 | rx_fifo = sh_msiof_spi_read_fifo_16; | 537 | rx_fifo = sh_msiof_spi_read_fifo_16; |
538 | } else if (swab) { | ||
539 | bytes_per_word = 4; | ||
540 | if ((unsigned long)t->tx_buf & 0x03) | ||
541 | tx_fifo = sh_msiof_spi_write_fifo_s32u; | ||
542 | else | ||
543 | tx_fifo = sh_msiof_spi_write_fifo_s32; | ||
544 | |||
545 | if ((unsigned long)t->rx_buf & 0x03) | ||
546 | rx_fifo = sh_msiof_spi_read_fifo_s32u; | ||
547 | else | ||
548 | rx_fifo = sh_msiof_spi_read_fifo_s32; | ||
490 | } else { | 549 | } else { |
491 | bytes_per_word = 4; | 550 | bytes_per_word = 4; |
492 | if ((unsigned long)t->tx_buf & 0x03) | 551 | if ((unsigned long)t->tx_buf & 0x03) |