aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Sperl <kernel@martin.sperl.org>2015-04-06 13:16:30 -0400
committerMark Brown <broonie@kernel.org>2015-04-10 14:50:52 -0400
commit704f32d48af221fd6d6ffcafe679f04ddcf5e7f6 (patch)
tree1c9854a3b250b9fe1783a3c7a866eba7a2d2185d
parenta30a555d7435a440fab06fe5960cf3448d8cedd3 (diff)
spi: bcm2835: enabling polling mode for transfers shorter than 30us
In cases of short transfer times the CPU is spending lots of time in the interrupt handler and scheduler to reschedule the worker thread. Measurements show that we have times where it takes 29.32us to between the last clock change and the time that the worker-thread is running again returning from wait_for_completion_timeout(). During this time the interrupt-handler is running calling complete() and then also the scheduler is rescheduling the worker thread. This time can vary depending on how much of the code is still in CPU-caches, when there is a burst of spi transfers the subsequent delays are in the order of 25us, so the value of 30us seems reasonable. With polling the whole transfer of 4 bytes at 10MHz finishes after 6.16us (CS down to up) with the real transfer (clock running) taking 3.56us. So the efficiency has much improved and is also freeing CPU cycles, reducing interrupts and context switches. Because of the above 30us seems to be a reasonable limit for polling. Signed-off-by: Martin Sperl <kernel@martin.sperl.org> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-bcm2835.c112
1 files changed, 86 insertions, 26 deletions
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 90064494e828..f63864a893c5 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -68,7 +68,8 @@
68#define BCM2835_SPI_CS_CS_10 0x00000002 68#define BCM2835_SPI_CS_CS_10 0x00000002
69#define BCM2835_SPI_CS_CS_01 0x00000001 69#define BCM2835_SPI_CS_CS_01 0x00000001
70 70
71#define BCM2835_SPI_TIMEOUT_MS 30000 71#define BCM2835_SPI_POLLING_LIMIT_US 30
72#define BCM2835_SPI_TIMEOUT_MS 30000
72#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ 73#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
73 | SPI_NO_CS | SPI_3WIRE) 74 | SPI_NO_CS | SPI_3WIRE)
74 75
@@ -156,12 +157,86 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
156 return IRQ_HANDLED; 157 return IRQ_HANDLED;
157} 158}
158 159
160static int bcm2835_spi_transfer_one_poll(struct spi_master *master,
161 struct spi_device *spi,
162 struct spi_transfer *tfr,
163 u32 cs,
164 unsigned long xfer_time_us)
165{
166 struct bcm2835_spi *bs = spi_master_get_devdata(master);
167 unsigned long timeout = jiffies +
168 max(4 * xfer_time_us * HZ / 1000000, 2uL);
169
170 /* enable HW block without interrupts */
171 bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA);
172
173 /* set timeout to 4x the expected time, or 2 jiffies */
174 /* loop until finished the transfer */
175 while (bs->rx_len) {
176 /* read from fifo as much as possible */
177 bcm2835_rd_fifo(bs);
178 /* fill in tx fifo as much as possible */
179 bcm2835_wr_fifo(bs);
180 /* if we still expect some data after the read,
181 * check for a possible timeout
182 */
183 if (bs->rx_len && time_after(jiffies, timeout)) {
184 /* Transfer complete - reset SPI HW */
185 bcm2835_spi_reset_hw(master);
186 /* and return timeout */
187 return -ETIMEDOUT;
188 }
189 }
190
191 /* Transfer complete - reset SPI HW */
192 bcm2835_spi_reset_hw(master);
193 /* and return without waiting for completion */
194 return 0;
195}
196
197static int bcm2835_spi_transfer_one_irq(struct spi_master *master,
198 struct spi_device *spi,
199 struct spi_transfer *tfr,
200 u32 cs)
201{
202 struct bcm2835_spi *bs = spi_master_get_devdata(master);
203
204 /* fill in fifo if we have gpio-cs
205 * note that there have been rare events where the native-CS
206 * flapped for <1us which may change the behaviour
207 * with gpio-cs this does not happen, so it is implemented
208 * only for this case
209 */
210 if (gpio_is_valid(spi->cs_gpio)) {
211 /* enable HW block, but without interrupts enabled
212 * this would triggern an immediate interrupt
213 */
214 bcm2835_wr(bs, BCM2835_SPI_CS,
215 cs | BCM2835_SPI_CS_TA);
216 /* fill in tx fifo as much as possible */
217 bcm2835_wr_fifo(bs);
218 }
219
220 /*
221 * Enable the HW block. This will immediately trigger a DONE (TX
222 * empty) interrupt, upon which we will fill the TX FIFO with the
223 * first TX bytes. Pre-filling the TX FIFO here to avoid the
224 * interrupt doesn't work:-(
225 */
226 cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA;
227 bcm2835_wr(bs, BCM2835_SPI_CS, cs);
228
229 /* signal that we need to wait for completion */
230 return 1;
231}
232
159static int bcm2835_spi_transfer_one(struct spi_master *master, 233static int bcm2835_spi_transfer_one(struct spi_master *master,
160 struct spi_device *spi, 234 struct spi_device *spi,
161 struct spi_transfer *tfr) 235 struct spi_transfer *tfr)
162{ 236{
163 struct bcm2835_spi *bs = spi_master_get_devdata(master); 237 struct bcm2835_spi *bs = spi_master_get_devdata(master);
164 unsigned long spi_hz, clk_hz, cdiv; 238 unsigned long spi_hz, clk_hz, cdiv;
239 unsigned long spi_used_hz, xfer_time_us;
165 u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); 240 u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
166 241
167 /* set clock */ 242 /* set clock */
@@ -180,6 +255,7 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
180 } else { 255 } else {
181 cdiv = 0; /* 0 is the slowest we can go */ 256 cdiv = 0; /* 0 is the slowest we can go */
182 } 257 }
258 spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
183 bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); 259 bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
184 260
185 /* handle all the modes */ 261 /* handle all the modes */
@@ -203,33 +279,17 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
203 bs->tx_len = tfr->len; 279 bs->tx_len = tfr->len;
204 bs->rx_len = tfr->len; 280 bs->rx_len = tfr->len;
205 281
206 /* fill in fifo if we have gpio-cs 282 /* calculate the estimated time in us the transfer runs */
207 * note that there have been rare events where the native-CS 283 xfer_time_us = tfr->len
208 * flapped for <1us which may change the behaviour 284 * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */
209 * with gpio-cs this does not happen, so it is implemented 285 * 1000000 / spi_used_hz;
210 * only for this case
211 */
212 if (gpio_is_valid(spi->cs_gpio)) {
213 /* enable HW block, but without interrupts enabled
214 * this would triggern an immediate interrupt
215 */
216 bcm2835_wr(bs, BCM2835_SPI_CS,
217 cs | BCM2835_SPI_CS_TA);
218 /* fill in tx fifo as much as possible */
219 bcm2835_wr_fifo(bs);
220 }
221 286
222 /* 287 /* for short requests run polling*/
223 * Enable the HW block. This will immediately trigger a DONE (TX 288 if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US)
224 * empty) interrupt, upon which we will fill the TX FIFO with the 289 return bcm2835_spi_transfer_one_poll(master, spi, tfr,
225 * first TX bytes. Pre-filling the TX FIFO here to avoid the 290 cs, xfer_time_us);
226 * interrupt doesn't work:-(
227 */
228 cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA;
229 bcm2835_wr(bs, BCM2835_SPI_CS, cs);
230 291
231 /* signal that we need to wait for completion */ 292 return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs);
232 return 1;
233} 293}
234 294
235static void bcm2835_spi_handle_err(struct spi_master *master, 295static void bcm2835_spi_handle_err(struct spi_master *master,