Skip to content

Commit 571e31f

Browse files
l1kbroonie
authored andcommitted
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 acace73 ("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á <[email protected]> Tested-by: Noralf Trønnes <[email protected]> Signed-off-by: Lukas Wunner <[email protected]> Acked-by: Stefan Wahren <[email protected]> Acked-by: Martin Sperl <[email protected]> Link: https://lore.kernel.org/r/d17c1d7fcdc97fffa961b8737cfd80eeb14f9416.1568187525.git.lukas@wunner.de Signed-off-by: Mark Brown <[email protected]>
1 parent c3ef820 commit 571e31f

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

drivers/spi/spi-bcm2835.c

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#define BCM2835_SPI_FIFO_SIZE 64
6969
#define BCM2835_SPI_FIFO_SIZE_3_4 48
7070
#define BCM2835_SPI_DMA_MIN_LENGTH 96
71+
#define BCM2835_SPI_NUM_CS 3 /* raise as necessary */
7172
#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
7273
| SPI_NO_CS | SPI_3WIRE)
7374

@@ -94,6 +95,8 @@ MODULE_PARM_DESC(polling_limit_us,
9495
* @rx_prologue: bytes received without DMA if first RX sglist entry's
9596
* length is not a multiple of 4 (to overcome hardware limitation)
9697
* @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)
97100
* @debugfs_dir: the debugfs directory - neede to remove debugfs when
98101
* unloading the module
99102
* @count_transfer_polling: count of how often polling mode is used
@@ -116,6 +119,7 @@ struct bcm2835_spi {
116119
int tx_prologue;
117120
int rx_prologue;
118121
unsigned int tx_spillover;
122+
u32 prepare_cs[BCM2835_SPI_NUM_CS];
119123

120124
struct dentry *debugfs_dir;
121125
u64 count_transfer_polling;
@@ -808,7 +812,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
808812
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
809813
unsigned long spi_hz, clk_hz, cdiv, spi_used_hz;
810814
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];
812816

813817
/* set clock */
814818
spi_hz = tfr->speed_hz;
@@ -833,15 +837,6 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
833837
if (spi->mode & SPI_3WIRE && tfr->rx_buf &&
834838
tfr->rx_buf != ctlr->dummy_rx)
835839
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;
845840

846841
/* set transmit buffers and length */
847842
bs->tx_buf = tfr->tx_buf;
@@ -878,7 +873,6 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr,
878873
{
879874
struct spi_device *spi = msg->spi;
880875
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
881-
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
882876
int ret;
883877

884878
if (ctlr->can_dma) {
@@ -893,14 +887,11 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr,
893887
return ret;
894888
}
895889

896-
cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
897-
898-
if (spi->mode & SPI_CPOL)
899-
cs |= BCM2835_SPI_CS_CPOL;
900-
if (spi->mode & SPI_CPHA)
901-
cs |= BCM2835_SPI_CS_CPHA;
902-
903-
bcm2835_wr(bs, BCM2835_SPI_CS, cs);
890+
/*
891+
* Set up clock polarity before spi_transfer_one_message() asserts
892+
* chip select to avoid a gratuitous clock signal edge.
893+
*/
894+
bcm2835_wr(bs, BCM2835_SPI_CS, bs->prepare_cs[spi->chip_select]);
904895

905896
return 0;
906897
}
@@ -926,8 +917,23 @@ static int chip_match_name(struct gpio_chip *chip, void *data)
926917

927918
static int bcm2835_spi_setup(struct spi_device *spi)
928919
{
920+
struct bcm2835_spi *bs = spi_controller_get_devdata(spi->controller);
929921
struct gpio_chip *chip;
930922
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;
931937

932938
/*
933939
* sanity checking the native-chipselects
@@ -1005,7 +1011,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
10051011
ctlr->use_gpio_descriptors = true;
10061012
ctlr->mode_bits = BCM2835_SPI_MODE_BITS;
10071013
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
1008-
ctlr->num_chipselect = 3;
1014+
ctlr->num_chipselect = BCM2835_SPI_NUM_CS;
10091015
ctlr->setup = bcm2835_spi_setup;
10101016
ctlr->transfer_one = bcm2835_spi_transfer_one;
10111017
ctlr->handle_err = bcm2835_spi_handle_err;

0 commit comments

Comments
 (0)