diff options
author | Lukas Wunner <lukas@wunner.de> | 2018-11-29 10:45:24 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-12-04 11:51:12 -0500 |
commit | b31a9299bca66c42583ef2e2f685369780cdf350 (patch) | |
tree | cbf55606c5fd9e083df02bb205e87d0cc332e0e9 /drivers/spi | |
parent | b12a084c8729ef423089bb9a5a143eed39cd94e7 (diff) |
spi: bcm2835: Polish transfer of DMA prologue
Commit 3bd7f6589f67 ("spi: bcm2835: Overcome sglist entry length
limitation") was unfortunately merged even though submission of a
refined version was imminent. Apply those refinements as an amendment:
* Drop no longer needed #include <asm/page.h>. The lines requiring
its inclusion were removed by the commit.
* Change type of tx_spillover flag from bool to unsigned int for
consistency with dma_pending flag and pursuant to Linus' dictum:
https://lkml.org/lkml/2017/11/21/384
* In bcm2835_rd_fifo_count() do not check for bs->rx_buf != NULL.
The function will never be called if that's the case.
* Amend kerneldoc of bcm2835_wait_tx_fifo_empty() to prevent its use in
situations where the function might spin forever. (In response to a
review comment by Stefan Wahren.)
* Sync only the cacheline containing the RX prologue back to memory,
not the full first sglist entry.
* Use sg_dma_address() and sg_dma_len() instead of referencing the
sglist entry members directly. Seems to be the more common syntax in
the tree, even for lvalues.
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Frank Pavlic <f.pavlic@kunbus.de>
Cc: Martin Sperl <kernel@martin.sperl.org>
Cc: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-bcm2835.c | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 5cbdc94bb4cf..8c121b3374dd 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c | |||
@@ -20,7 +20,6 @@ | |||
20 | * GNU General Public License for more details. | 20 | * GNU General Public License for more details. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <asm/page.h> | ||
24 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
25 | #include <linux/completion.h> | 24 | #include <linux/completion.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
@@ -108,7 +107,7 @@ struct bcm2835_spi { | |||
108 | int rx_len; | 107 | int rx_len; |
109 | int tx_prologue; | 108 | int tx_prologue; |
110 | int rx_prologue; | 109 | int rx_prologue; |
111 | bool tx_spillover; | 110 | unsigned int tx_spillover; |
112 | unsigned int dma_pending; | 111 | unsigned int dma_pending; |
113 | }; | 112 | }; |
114 | 113 | ||
@@ -155,21 +154,20 @@ static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) | |||
155 | * The caller must ensure that @bs->rx_len is greater than or equal to @count, | 154 | * The caller must ensure that @bs->rx_len is greater than or equal to @count, |
156 | * that the RX FIFO contains at least @count bytes and that the DMA Enable flag | 155 | * that the RX FIFO contains at least @count bytes and that the DMA Enable flag |
157 | * in the CS register is set (such that a read from the FIFO register receives | 156 | * in the CS register is set (such that a read from the FIFO register receives |
158 | * 32-bit instead of just 8-bit). | 157 | * 32-bit instead of just 8-bit). Moreover @bs->rx_buf must not be %NULL. |
159 | */ | 158 | */ |
160 | static inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count) | 159 | static inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count) |
161 | { | 160 | { |
162 | u32 val; | 161 | u32 val; |
162 | int len; | ||
163 | 163 | ||
164 | bs->rx_len -= count; | 164 | bs->rx_len -= count; |
165 | 165 | ||
166 | while (count > 0) { | 166 | while (count > 0) { |
167 | val = bcm2835_rd(bs, BCM2835_SPI_FIFO); | 167 | val = bcm2835_rd(bs, BCM2835_SPI_FIFO); |
168 | if (bs->rx_buf) { | 168 | len = min(count, 4); |
169 | int len = min(count, 4); | 169 | memcpy(bs->rx_buf, &val, len); |
170 | memcpy(bs->rx_buf, &val, len); | 170 | bs->rx_buf += len; |
171 | bs->rx_buf += len; | ||
172 | } | ||
173 | count -= 4; | 171 | count -= 4; |
174 | } | 172 | } |
175 | } | 173 | } |
@@ -187,12 +185,13 @@ static inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count) | |||
187 | static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) | 185 | static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) |
188 | { | 186 | { |
189 | u32 val; | 187 | u32 val; |
188 | int len; | ||
190 | 189 | ||
191 | bs->tx_len -= count; | 190 | bs->tx_len -= count; |
192 | 191 | ||
193 | while (count > 0) { | 192 | while (count > 0) { |
194 | if (bs->tx_buf) { | 193 | if (bs->tx_buf) { |
195 | int len = min(count, 4); | 194 | len = min(count, 4); |
196 | memcpy(&val, bs->tx_buf, len); | 195 | memcpy(&val, bs->tx_buf, len); |
197 | bs->tx_buf += len; | 196 | bs->tx_buf += len; |
198 | } else { | 197 | } else { |
@@ -206,6 +205,10 @@ static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) | |||
206 | /** | 205 | /** |
207 | * bcm2835_wait_tx_fifo_empty() - busy-wait for TX FIFO to empty | 206 | * bcm2835_wait_tx_fifo_empty() - busy-wait for TX FIFO to empty |
208 | * @bs: BCM2835 SPI controller | 207 | * @bs: BCM2835 SPI controller |
208 | * | ||
209 | * The caller must ensure that the RX FIFO can accommodate as many bytes | ||
210 | * as have been written to the TX FIFO: Transmission is halted once the | ||
211 | * RX FIFO is full, causing this function to spin forever. | ||
209 | */ | 212 | */ |
210 | static inline void bcm2835_wait_tx_fifo_empty(struct bcm2835_spi *bs) | 213 | static inline void bcm2835_wait_tx_fifo_empty(struct bcm2835_spi *bs) |
211 | { | 214 | { |
@@ -379,11 +382,12 @@ static void bcm2835_spi_transfer_prologue(struct spi_master *master, | |||
379 | bcm2835_rd_fifo_count(bs, bs->rx_prologue); | 382 | bcm2835_rd_fifo_count(bs, bs->rx_prologue); |
380 | bcm2835_spi_reset_hw(master); | 383 | bcm2835_spi_reset_hw(master); |
381 | 384 | ||
382 | dma_sync_sg_for_device(master->dma_rx->device->dev, | 385 | dma_sync_single_for_device(master->dma_rx->device->dev, |
383 | tfr->rx_sg.sgl, 1, DMA_FROM_DEVICE); | 386 | sg_dma_address(&tfr->rx_sg.sgl[0]), |
387 | bs->rx_prologue, DMA_FROM_DEVICE); | ||
384 | 388 | ||
385 | tfr->rx_sg.sgl[0].dma_address += bs->rx_prologue; | 389 | sg_dma_address(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; |
386 | tfr->rx_sg.sgl[0].length -= bs->rx_prologue; | 390 | sg_dma_len(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; |
387 | } | 391 | } |
388 | 392 | ||
389 | /* | 393 | /* |
@@ -401,12 +405,12 @@ static void bcm2835_spi_transfer_prologue(struct spi_master *master, | |||
401 | } | 405 | } |
402 | 406 | ||
403 | if (likely(!bs->tx_spillover)) { | 407 | if (likely(!bs->tx_spillover)) { |
404 | tfr->tx_sg.sgl[0].dma_address += bs->tx_prologue; | 408 | sg_dma_address(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; |
405 | tfr->tx_sg.sgl[0].length -= bs->tx_prologue; | 409 | sg_dma_len(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; |
406 | } else { | 410 | } else { |
407 | tfr->tx_sg.sgl[0].length = 0; | 411 | sg_dma_len(&tfr->tx_sg.sgl[0]) = 0; |
408 | tfr->tx_sg.sgl[1].dma_address += 4; | 412 | sg_dma_address(&tfr->tx_sg.sgl[1]) += 4; |
409 | tfr->tx_sg.sgl[1].length -= 4; | 413 | sg_dma_len(&tfr->tx_sg.sgl[1]) -= 4; |
410 | } | 414 | } |
411 | } | 415 | } |
412 | 416 | ||
@@ -426,17 +430,17 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) | |||
426 | return; | 430 | return; |
427 | 431 | ||
428 | if (bs->rx_prologue) { | 432 | if (bs->rx_prologue) { |
429 | tfr->rx_sg.sgl[0].dma_address -= bs->rx_prologue; | 433 | sg_dma_address(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; |
430 | tfr->rx_sg.sgl[0].length += bs->rx_prologue; | 434 | sg_dma_len(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; |
431 | } | 435 | } |
432 | 436 | ||
433 | if (likely(!bs->tx_spillover)) { | 437 | if (likely(!bs->tx_spillover)) { |
434 | tfr->tx_sg.sgl[0].dma_address -= bs->tx_prologue; | 438 | sg_dma_address(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; |
435 | tfr->tx_sg.sgl[0].length += bs->tx_prologue; | 439 | sg_dma_len(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; |
436 | } else { | 440 | } else { |
437 | tfr->tx_sg.sgl[0].length = bs->tx_prologue - 4; | 441 | sg_dma_len(&tfr->tx_sg.sgl[0]) = bs->tx_prologue - 4; |
438 | tfr->tx_sg.sgl[1].dma_address -= 4; | 442 | sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4; |
439 | tfr->tx_sg.sgl[1].length += 4; | 443 | sg_dma_len(&tfr->tx_sg.sgl[1]) += 4; |
440 | } | 444 | } |
441 | } | 445 | } |
442 | 446 | ||