aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Sperl <kernel@martin.sperl.org>2015-03-23 10:11:53 -0400
committerMark Brown <broonie@kernel.org>2015-03-23 14:48:58 -0400
commit4adf312976ef2b72830b83f212fef3f6a36513a6 (patch)
treec3532ec523a70e1127abb8e3134d58c8e4c1979e
parent342f948a166c2a17b0e187e3fc2618dc561842f3 (diff)
spi: bcm2835: fill/drain SPI-fifo as much as possible during interrupt
Implement the recommendation from the BCM2835 data-sheet with regards to polling drivers to fill/drain the FIFO as much data as possible also for the interrupt-driven case (which this driver is making use of). This means that for long transfers (>64bytes) we need one interrupt every 64 bytes instead of every 12 bytes, as the FIFO is 16 words (not bytes) wide. Tested with mcp251x (can bus), fb_st7735 (TFT framebuffer device) and enc28j60 (ethernet) drivers. Signed-off-by: Martin Sperl <kernel@martin.sperl.org> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-bcm2835.c78
1 files changed, 17 insertions, 61 deletions
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 779d3a86c3cb..960dcce607c2 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -91,25 +91,23 @@ static inline void bcm2835_wr(struct bcm2835_spi *bs, unsigned reg, u32 val)
91 writel(val, bs->regs + reg); 91 writel(val, bs->regs + reg);
92} 92}
93 93
94static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs, int len) 94static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs)
95{ 95{
96 u8 byte; 96 u8 byte;
97 97
98 while (len--) { 98 while (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD) {
99 byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); 99 byte = bcm2835_rd(bs, BCM2835_SPI_FIFO);
100 if (bs->rx_buf) 100 if (bs->rx_buf)
101 *bs->rx_buf++ = byte; 101 *bs->rx_buf++ = byte;
102 } 102 }
103} 103}
104 104
105static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs, int len) 105static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs)
106{ 106{
107 u8 byte; 107 u8 byte;
108 108
109 if (len > bs->len) 109 while ((bs->len) &&
110 len = bs->len; 110 (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) {
111
112 while (len--) {
113 byte = bs->tx_buf ? *bs->tx_buf++ : 0; 111 byte = bs->tx_buf ? *bs->tx_buf++ : 0;
114 bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); 112 bcm2835_wr(bs, BCM2835_SPI_FIFO, byte);
115 bs->len--; 113 bs->len--;
@@ -122,60 +120,24 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
122 struct bcm2835_spi *bs = spi_master_get_devdata(master); 120 struct bcm2835_spi *bs = spi_master_get_devdata(master);
123 u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); 121 u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
124 122
125 /* 123 /* Read as many bytes as possible from FIFO */
126 * RXR - RX needs Reading. This means 12 (or more) bytes have been 124 bcm2835_rd_fifo(bs);
127 * transmitted and hence 12 (or more) bytes have been received.
128 *
129 * The FIFO is 16-bytes deep. We check for this interrupt to keep the
130 * FIFO full; we have a 4-byte-time buffer for IRQ latency. We check
131 * this before DONE (TX empty) just in case we delayed processing this
132 * interrupt for some reason.
133 *
134 * We only check for this case if we have more bytes to TX; at the end
135 * of the transfer, we ignore this pipelining optimization, and let
136 * bcm2835_spi_finish_transfer() drain the RX FIFO.
137 */
138 if (bs->len && (cs & BCM2835_SPI_CS_RXR)) {
139 /* Read 12 bytes of data */
140 bcm2835_rd_fifo(bs, 12);
141 125
142 /* Write up to 12 bytes */ 126 if (bs->len) { /* there is more data to transmit */
143 bcm2835_wr_fifo(bs, 12); 127 bcm2835_wr_fifo(bs);
128 } else { /* Transfer complete */
129 /* Disable SPI interrupts */
130 cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD);
131 bcm2835_wr(bs, BCM2835_SPI_CS, cs);
144 132
145 /* 133 /*
146 * We must have written something to the TX FIFO due to the 134 * Wake up bcm2835_spi_transfer_one(), which will call
147 * bs->len check above, so cannot be DONE. Hence, return 135 * bcm2835_spi_finish_transfer(), to drain the RX FIFO.
148 * early. Note that DONE could also be set if we serviced an
149 * RXR interrupt really late.
150 */ 136 */
151 return IRQ_HANDLED; 137 complete(&bs->done);
152 } 138 }
153 139
154 /* 140 return IRQ_HANDLED;
155 * DONE - TX empty. This occurs when we first enable the transfer
156 * since we do not pre-fill the TX FIFO. At any other time, given that
157 * we refill the TX FIFO above based on RXR, and hence ignore DONE if
158 * RXR is set, DONE really does mean end-of-transfer.
159 */
160 if (cs & BCM2835_SPI_CS_DONE) {
161 if (bs->len) { /* First interrupt in a transfer */
162 bcm2835_wr_fifo(bs, 16);
163 } else { /* Transfer complete */
164 /* Disable SPI interrupts */
165 cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD);
166 bcm2835_wr(bs, BCM2835_SPI_CS, cs);
167
168 /*
169 * Wake up bcm2835_spi_transfer_one(), which will call
170 * bcm2835_spi_finish_transfer(), to drain the RX FIFO.
171 */
172 complete(&bs->done);
173 }
174
175 return IRQ_HANDLED;
176 }
177
178 return IRQ_NONE;
179} 141}
180 142
181static int bcm2835_spi_start_transfer(struct spi_device *spi, 143static int bcm2835_spi_start_transfer(struct spi_device *spi,
@@ -238,12 +200,6 @@ static int bcm2835_spi_finish_transfer(struct spi_device *spi,
238 struct bcm2835_spi *bs = spi_master_get_devdata(spi->master); 200 struct bcm2835_spi *bs = spi_master_get_devdata(spi->master);
239 u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); 201 u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
240 202
241 /* Drain RX FIFO */
242 while (cs & BCM2835_SPI_CS_RXD) {
243 bcm2835_rd_fifo(bs, 1);
244 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
245 }
246
247 if (tfr->delay_usecs) 203 if (tfr->delay_usecs)
248 udelay(tfr->delay_usecs); 204 udelay(tfr->delay_usecs);
249 205