diff options
author | Hiep Cao Minh <cm-hiep@jinso.co.jp> | 2014-10-22 23:14:13 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-03-30 00:29:35 -0400 |
commit | 4b6fe3edcbbaa3d0e5513adcb9577c7e184ad1b5 (patch) | |
tree | dae20d850e5977c1f6a5d8ac103494f99a31c846 /drivers/spi/spi-rspi.c | |
parent | c517d838eb7d07bbe9507871fab3931deccff539 (diff) |
spi: Using Trigger number to transmit/receive data
In order to transmit and receive data when have 32 bytes of data that
ready has prepared on Transmit/Receive Buffer to transmit or receive.
Instead transmits/receives a byte data using Transmit/Receive Buffer
Data Triggering Number will improve the speed of transfer data.
Signed-off-by: Hiep Cao Minh <cm-hiep@jinso.co.jp>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-rspi.c')
-rw-r--r-- | drivers/spi/spi-rspi.c | 124 |
1 files changed, 117 insertions, 7 deletions
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 46ce47076e63..fd276f990d4d 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c | |||
@@ -177,6 +177,13 @@ | |||
177 | #define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset */ | 177 | #define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset */ |
178 | #define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ | 178 | #define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ |
179 | #define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ | 179 | #define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ |
180 | /* QSPI on R-Car Gen2 */ | ||
181 | #define SPBFCR_TXTRG_1B 0x00 /* 31 bytes (1 byte available) */ | ||
182 | #define SPBFCR_TXTRG_32B 0x30 /* 0 byte (32 bytes available) */ | ||
183 | #define SPBFCR_RXTRG_1B 0x00 /* 1 byte (31 bytes available) */ | ||
184 | #define SPBFCR_RXTRG_32B 0x07 /* 32 bytes (0 byte available) */ | ||
185 | |||
186 | #define QSPI_BUFFER_SIZE 32u | ||
180 | 187 | ||
181 | struct rspi_data { | 188 | struct rspi_data { |
182 | void __iomem *addr; | 189 | void __iomem *addr; |
@@ -366,6 +373,52 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size) | |||
366 | return 0; | 373 | return 0; |
367 | } | 374 | } |
368 | 375 | ||
376 | static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg) | ||
377 | { | ||
378 | u8 data; | ||
379 | |||
380 | data = rspi_read8(rspi, reg); | ||
381 | data &= ~mask; | ||
382 | data |= (val & mask); | ||
383 | rspi_write8(rspi, data, reg); | ||
384 | } | ||
385 | |||
386 | static int qspi_set_send_trigger(struct rspi_data *rspi, unsigned int len) | ||
387 | { | ||
388 | unsigned int n; | ||
389 | |||
390 | n = min(len, QSPI_BUFFER_SIZE); | ||
391 | |||
392 | if (len >= QSPI_BUFFER_SIZE) { | ||
393 | /* sets triggering number to 32 bytes */ | ||
394 | qspi_update(rspi, SPBFCR_TXTRG_MASK, | ||
395 | SPBFCR_TXTRG_32B, QSPI_SPBFCR); | ||
396 | } else { | ||
397 | /* sets triggering number to 1 byte */ | ||
398 | qspi_update(rspi, SPBFCR_TXTRG_MASK, | ||
399 | SPBFCR_TXTRG_1B, QSPI_SPBFCR); | ||
400 | } | ||
401 | |||
402 | return n; | ||
403 | } | ||
404 | |||
405 | static void qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) | ||
406 | { | ||
407 | unsigned int n; | ||
408 | |||
409 | n = min(len, QSPI_BUFFER_SIZE); | ||
410 | |||
411 | if (len >= QSPI_BUFFER_SIZE) { | ||
412 | /* sets triggering number to 32 bytes */ | ||
413 | qspi_update(rspi, SPBFCR_RXTRG_MASK, | ||
414 | SPBFCR_RXTRG_32B, QSPI_SPBFCR); | ||
415 | } else { | ||
416 | /* sets triggering number to 1 byte */ | ||
417 | qspi_update(rspi, SPBFCR_RXTRG_MASK, | ||
418 | SPBFCR_RXTRG_1B, QSPI_SPBFCR); | ||
419 | } | ||
420 | } | ||
421 | |||
369 | #define set_config_register(spi, n) spi->ops->set_config_register(spi, n) | 422 | #define set_config_register(spi, n) spi->ops->set_config_register(spi, n) |
370 | 423 | ||
371 | static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable) | 424 | static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable) |
@@ -609,19 +662,29 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi, | |||
609 | return __rspi_can_dma(rspi, xfer); | 662 | return __rspi_can_dma(rspi, xfer); |
610 | } | 663 | } |
611 | 664 | ||
612 | static int rspi_common_transfer(struct rspi_data *rspi, | 665 | static int rspi_dma_check_then_transfer(struct rspi_data *rspi, |
613 | struct spi_transfer *xfer) | 666 | struct spi_transfer *xfer) |
614 | { | 667 | { |
615 | int ret; | ||
616 | |||
617 | if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { | 668 | if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { |
618 | /* rx_buf can be NULL on RSPI on SH in TX-only Mode */ | 669 | /* rx_buf can be NULL on RSPI on SH in TX-only Mode */ |
619 | ret = rspi_dma_transfer(rspi, &xfer->tx_sg, | 670 | int ret = rspi_dma_transfer(rspi, &xfer->tx_sg, |
620 | xfer->rx_buf ? &xfer->rx_sg : NULL); | 671 | xfer->rx_buf ? &xfer->rx_sg : NULL); |
621 | if (ret != -EAGAIN) | 672 | if (ret != -EAGAIN) |
622 | return ret; | 673 | return 0; |
623 | } | 674 | } |
624 | 675 | ||
676 | return -EAGAIN; | ||
677 | } | ||
678 | |||
679 | static int rspi_common_transfer(struct rspi_data *rspi, | ||
680 | struct spi_transfer *xfer) | ||
681 | { | ||
682 | int ret; | ||
683 | |||
684 | ret = rspi_dma_check_then_transfer(rspi, xfer); | ||
685 | if (ret != -EAGAIN) | ||
686 | return ret; | ||
687 | |||
625 | ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); | 688 | ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); |
626 | if (ret < 0) | 689 | if (ret < 0) |
627 | return ret; | 690 | return ret; |
@@ -661,12 +724,59 @@ static int rspi_rz_transfer_one(struct spi_master *master, | |||
661 | return rspi_common_transfer(rspi, xfer); | 724 | return rspi_common_transfer(rspi, xfer); |
662 | } | 725 | } |
663 | 726 | ||
727 | static int qspi_trigger_transfer_out_int(struct rspi_data *rspi, const u8 *tx, | ||
728 | u8 *rx, unsigned int len) | ||
729 | { | ||
730 | unsigned int i, n, ret; | ||
731 | int error; | ||
732 | |||
733 | while (len > 0) { | ||
734 | n = qspi_set_send_trigger(rspi, len); | ||
735 | qspi_set_receive_trigger(rspi, len); | ||
736 | if (n == QSPI_BUFFER_SIZE) { | ||
737 | error = rspi_wait_for_tx_empty(rspi); | ||
738 | if (error < 0) { | ||
739 | dev_err(&rspi->master->dev, "transmit timeout\n"); | ||
740 | return error; | ||
741 | } | ||
742 | for (i = 0; i < n; i++) | ||
743 | rspi_write_data(rspi, *tx++); | ||
744 | |||
745 | error = rspi_wait_for_rx_full(rspi); | ||
746 | if (error < 0) { | ||
747 | dev_err(&rspi->master->dev, "receive timeout\n"); | ||
748 | return error; | ||
749 | } | ||
750 | for (i = 0; i < n; i++) | ||
751 | *rx++ = rspi_read_data(rspi); | ||
752 | } else { | ||
753 | ret = rspi_pio_transfer(rspi, tx, rx, n); | ||
754 | if (ret < 0) | ||
755 | return ret; | ||
756 | } | ||
757 | len -= n; | ||
758 | } | ||
759 | |||
760 | return 0; | ||
761 | } | ||
762 | |||
664 | static int qspi_transfer_out_in(struct rspi_data *rspi, | 763 | static int qspi_transfer_out_in(struct rspi_data *rspi, |
665 | struct spi_transfer *xfer) | 764 | struct spi_transfer *xfer) |
666 | { | 765 | { |
766 | int ret; | ||
767 | |||
667 | qspi_receive_init(rspi); | 768 | qspi_receive_init(rspi); |
668 | 769 | ||
669 | return rspi_common_transfer(rspi, xfer); | 770 | ret = rspi_dma_check_then_transfer(rspi, xfer); |
771 | if (ret != -EAGAIN) | ||
772 | return ret; | ||
773 | |||
774 | ret = qspi_trigger_transfer_out_int(rspi, xfer->tx_buf, | ||
775 | xfer->rx_buf, xfer->len); | ||
776 | if (ret < 0) | ||
777 | return ret; | ||
778 | |||
779 | return 0; | ||
670 | } | 780 | } |
671 | 781 | ||
672 | static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) | 782 | static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) |