diff options
author | Lukas Wunner <lukas@wunner.de> | 2019-09-11 06:15:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-09-11 10:56:30 -0400 |
commit | 571e31fa60b3697d5db26140e16d5c45c51c9815 (patch) | |
tree | 12c3905bb0ca9519a3e7156eaccf61f014e38181 | |
parent | c3ef8207833206f53b1ea433dc25c0c9b30d4424 (diff) |
spi: bcm2835: Cache CS register value for ->prepare_message()
The BCM2835 SPI driver needs to set up the clock polarity in its
->prepare_message() hook before spi_transfer_one_message() asserts chip
select to avoid a gratuitous clock signal edge (cf. commit acace73df2c1
("spi: bcm2835: set up spi-mode before asserting cs-gpio")).
Precalculate the CS register value (which selects the clock polarity)
once in ->setup() and use that cached value in ->prepare_message() and
->transfer_one(). This avoids one MMIO read per message and one per
transfer, yielding a small latency improvement. Additionally, a
forthcoming commit will use the precalculated value to derive the
register value for clearing the RX FIFO, which will eliminate the need
for an RX dummy buffer when performing TX-only DMA transfers.
Tested-by: Nuno Sá <nuno.sa@analog.com>
Tested-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Stefan Wahren <wahrenst@gmx.net>
Acked-by: Martin Sperl <kernel@martin.sperl.org>
Link: https://lore.kernel.org/r/d17c1d7fcdc97fffa961b8737cfd80eeb14f9416.1568187525.git.lukas@wunner.de
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/spi/spi-bcm2835.c | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 60255ac837f5..f01d18d521f2 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #define BCM2835_SPI_FIFO_SIZE 64 | 68 | #define BCM2835_SPI_FIFO_SIZE 64 |
69 | #define BCM2835_SPI_FIFO_SIZE_3_4 48 | 69 | #define BCM2835_SPI_FIFO_SIZE_3_4 48 |
70 | #define BCM2835_SPI_DMA_MIN_LENGTH 96 | 70 | #define BCM2835_SPI_DMA_MIN_LENGTH 96 |
71 | #define BCM2835_SPI_NUM_CS 3 /* raise as necessary */ | ||
71 | #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ | 72 | #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ |
72 | | SPI_NO_CS | SPI_3WIRE) | 73 | | SPI_NO_CS | SPI_3WIRE) |
73 | 74 | ||
@@ -94,6 +95,8 @@ MODULE_PARM_DESC(polling_limit_us, | |||
94 | * @rx_prologue: bytes received without DMA if first RX sglist entry's | 95 | * @rx_prologue: bytes received without DMA if first RX sglist entry's |
95 | * length is not a multiple of 4 (to overcome hardware limitation) | 96 | * length is not a multiple of 4 (to overcome hardware limitation) |
96 | * @tx_spillover: whether @tx_prologue spills over to second TX sglist entry | 97 | * @tx_spillover: whether @tx_prologue spills over to second TX sglist entry |
98 | * @prepare_cs: precalculated CS register value for ->prepare_message() | ||
99 | * (uses slave-specific clock polarity and phase settings) | ||
97 | * @debugfs_dir: the debugfs directory - neede to remove debugfs when | 100 | * @debugfs_dir: the debugfs directory - neede to remove debugfs when |
98 | * unloading the module | 101 | * unloading the module |
99 | * @count_transfer_polling: count of how often polling mode is used | 102 | * @count_transfer_polling: count of how often polling mode is used |
@@ -116,6 +119,7 @@ struct bcm2835_spi { | |||
116 | int tx_prologue; | 119 | int tx_prologue; |
117 | int rx_prologue; | 120 | int rx_prologue; |
118 | unsigned int tx_spillover; | 121 | unsigned int tx_spillover; |
122 | u32 prepare_cs[BCM2835_SPI_NUM_CS]; | ||
119 | 123 | ||
120 | struct dentry *debugfs_dir; | 124 | struct dentry *debugfs_dir; |
121 | u64 count_transfer_polling; | 125 | u64 count_transfer_polling; |
@@ -808,7 +812,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, | |||
808 | struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); | 812 | struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); |
809 | unsigned long spi_hz, clk_hz, cdiv, spi_used_hz; | 813 | unsigned long spi_hz, clk_hz, cdiv, spi_used_hz; |
810 | unsigned long hz_per_byte, byte_limit; | 814 | unsigned long hz_per_byte, byte_limit; |
811 | u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); | 815 | u32 cs = bs->prepare_cs[spi->chip_select]; |
812 | 816 | ||
813 | /* set clock */ | 817 | /* set clock */ |
814 | spi_hz = tfr->speed_hz; | 818 | spi_hz = tfr->speed_hz; |
@@ -833,15 +837,6 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, | |||
833 | if (spi->mode & SPI_3WIRE && tfr->rx_buf && | 837 | if (spi->mode & SPI_3WIRE && tfr->rx_buf && |
834 | tfr->rx_buf != ctlr->dummy_rx) | 838 | tfr->rx_buf != ctlr->dummy_rx) |
835 | cs |= BCM2835_SPI_CS_REN; | 839 | cs |= BCM2835_SPI_CS_REN; |
836 | else | ||
837 | cs &= ~BCM2835_SPI_CS_REN; | ||
838 | |||
839 | /* | ||
840 | * The driver always uses software-controlled GPIO Chip Select. | ||
841 | * Set the hardware-controlled native Chip Select to an invalid | ||
842 | * value to prevent it from interfering. | ||
843 | */ | ||
844 | cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; | ||
845 | 840 | ||
846 | /* set transmit buffers and length */ | 841 | /* set transmit buffers and length */ |
847 | bs->tx_buf = tfr->tx_buf; | 842 | bs->tx_buf = tfr->tx_buf; |
@@ -878,7 +873,6 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr, | |||
878 | { | 873 | { |
879 | struct spi_device *spi = msg->spi; | 874 | struct spi_device *spi = msg->spi; |
880 | struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); | 875 | struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); |
881 | u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); | ||
882 | int ret; | 876 | int ret; |
883 | 877 | ||
884 | if (ctlr->can_dma) { | 878 | if (ctlr->can_dma) { |
@@ -893,14 +887,11 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr, | |||
893 | return ret; | 887 | return ret; |
894 | } | 888 | } |
895 | 889 | ||
896 | cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA); | 890 | /* |
897 | 891 | * Set up clock polarity before spi_transfer_one_message() asserts | |
898 | if (spi->mode & SPI_CPOL) | 892 | * chip select to avoid a gratuitous clock signal edge. |
899 | cs |= BCM2835_SPI_CS_CPOL; | 893 | */ |
900 | if (spi->mode & SPI_CPHA) | 894 | bcm2835_wr(bs, BCM2835_SPI_CS, bs->prepare_cs[spi->chip_select]); |
901 | cs |= BCM2835_SPI_CS_CPHA; | ||
902 | |||
903 | bcm2835_wr(bs, BCM2835_SPI_CS, cs); | ||
904 | 895 | ||
905 | return 0; | 896 | return 0; |
906 | } | 897 | } |
@@ -926,8 +917,23 @@ static int chip_match_name(struct gpio_chip *chip, void *data) | |||
926 | 917 | ||
927 | static int bcm2835_spi_setup(struct spi_device *spi) | 918 | static int bcm2835_spi_setup(struct spi_device *spi) |
928 | { | 919 | { |
920 | struct bcm2835_spi *bs = spi_controller_get_devdata(spi->controller); | ||
929 | struct gpio_chip *chip; | 921 | struct gpio_chip *chip; |
930 | enum gpio_lookup_flags lflags; | 922 | enum gpio_lookup_flags lflags; |
923 | u32 cs; | ||
924 | |||
925 | /* | ||
926 | * Precalculate SPI slave's CS register value for ->prepare_message(): | ||
927 | * The driver always uses software-controlled GPIO chip select, hence | ||
928 | * set the hardware-controlled native chip select to an invalid value | ||
929 | * to prevent it from interfering. | ||
930 | */ | ||
931 | cs = BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; | ||
932 | if (spi->mode & SPI_CPOL) | ||
933 | cs |= BCM2835_SPI_CS_CPOL; | ||
934 | if (spi->mode & SPI_CPHA) | ||
935 | cs |= BCM2835_SPI_CS_CPHA; | ||
936 | bs->prepare_cs[spi->chip_select] = cs; | ||
931 | 937 | ||
932 | /* | 938 | /* |
933 | * sanity checking the native-chipselects | 939 | * sanity checking the native-chipselects |
@@ -1005,7 +1011,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) | |||
1005 | ctlr->use_gpio_descriptors = true; | 1011 | ctlr->use_gpio_descriptors = true; |
1006 | ctlr->mode_bits = BCM2835_SPI_MODE_BITS; | 1012 | ctlr->mode_bits = BCM2835_SPI_MODE_BITS; |
1007 | ctlr->bits_per_word_mask = SPI_BPW_MASK(8); | 1013 | ctlr->bits_per_word_mask = SPI_BPW_MASK(8); |
1008 | ctlr->num_chipselect = 3; | 1014 | ctlr->num_chipselect = BCM2835_SPI_NUM_CS; |
1009 | ctlr->setup = bcm2835_spi_setup; | 1015 | ctlr->setup = bcm2835_spi_setup; |
1010 | ctlr->transfer_one = bcm2835_spi_transfer_one; | 1016 | ctlr->transfer_one = bcm2835_spi_transfer_one; |
1011 | ctlr->handle_err = bcm2835_spi_handle_err; | 1017 | ctlr->handle_err = bcm2835_spi_handle_err; |