summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2018-11-29 10:45:24 -0500
committerMark Brown <broonie@kernel.org>2018-12-04 11:51:12 -0500
commitb31a9299bca66c42583ef2e2f685369780cdf350 (patch)
treecbf55606c5fd9e083df02bb205e87d0cc332e0e9 /drivers/spi
parentb12a084c8729ef423089bb9a5a143eed39cd94e7 (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.c54
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 */
160static inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count) 159static 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)
187static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) 185static 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 */
210static inline void bcm2835_wait_tx_fifo_empty(struct bcm2835_spi *bs) 213static 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