aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/spi-bcm2835aux.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
index f92b4a69fffa..05d2d6eb7bfa 100644
--- a/drivers/spi/spi-bcm2835aux.c
+++ b/drivers/spi/spi-bcm2835aux.c
@@ -104,6 +104,7 @@ struct bcm2835aux_spi {
104 u8 *rx_buf; 104 u8 *rx_buf;
105 int tx_len; 105 int tx_len;
106 int rx_len; 106 int rx_len;
107 int pending;
107}; 108};
108 109
109static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg) 110static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg)
@@ -120,15 +121,27 @@ static inline void bcm2835aux_wr(struct bcm2835aux_spi *bs, unsigned reg,
120static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs) 121static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs)
121{ 122{
122 u32 data; 123 u32 data;
123 int i;
124 int count = min(bs->rx_len, 3); 124 int count = min(bs->rx_len, 3);
125 125
126 data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO); 126 data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO);
127 if (bs->rx_buf) { 127 if (bs->rx_buf) {
128 for (i = 0; i < count; i++) 128 switch (count) {
129 *bs->rx_buf++ = (data >> (8 * (2 - i))) & 0xff; 129 case 4:
130 *bs->rx_buf++ = (data >> 24) & 0xff;
131 /* fallthrough */
132 case 3:
133 *bs->rx_buf++ = (data >> 16) & 0xff;
134 /* fallthrough */
135 case 2:
136 *bs->rx_buf++ = (data >> 8) & 0xff;
137 /* fallthrough */
138 case 1:
139 *bs->rx_buf++ = (data >> 0) & 0xff;
140 /* fallthrough - no default */
141 }
130 } 142 }
131 bs->rx_len -= count; 143 bs->rx_len -= count;
144 bs->pending -= count;
132} 145}
133 146
134static inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs) 147static inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs)
@@ -151,6 +164,7 @@ static inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs)
151 164
152 /* and decrement length */ 165 /* and decrement length */
153 bs->tx_len -= count; 166 bs->tx_len -= count;
167 bs->pending += count;
154 168
155 /* write to the correct TX-register */ 169 /* write to the correct TX-register */
156 if (bs->tx_len) 170 if (bs->tx_len)
@@ -183,6 +197,7 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
183 197
184 /* check if we have data to write */ 198 /* check if we have data to write */
185 while (bs->tx_len && 199 while (bs->tx_len &&
200 (bs->pending < 12) &&
186 (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & 201 (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
187 BCM2835_AUX_SPI_STAT_TX_FULL))) { 202 BCM2835_AUX_SPI_STAT_TX_FULL))) {
188 bcm2835aux_wr_fifo(bs); 203 bcm2835aux_wr_fifo(bs);
@@ -234,6 +249,7 @@ static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
234 249
235 /* fill in tx fifo with data before enabling interrupts */ 250 /* fill in tx fifo with data before enabling interrupts */
236 while ((bs->tx_len) && 251 while ((bs->tx_len) &&
252 (bs->pending < 12) &&
237 (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & 253 (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
238 BCM2835_AUX_SPI_STAT_TX_FULL))) { 254 BCM2835_AUX_SPI_STAT_TX_FULL))) {
239 bcm2835aux_wr_fifo(bs); 255 bcm2835aux_wr_fifo(bs);
@@ -245,8 +261,7 @@ static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
245 261
246static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, 262static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
247 struct spi_device *spi, 263 struct spi_device *spi,
248 struct spi_transfer *tfr, 264 struct spi_transfer *tfr)
249 unsigned long xfer_time_us)
250{ 265{
251 struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 266 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
252 unsigned long timeout; 267 unsigned long timeout;
@@ -305,7 +320,8 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
305{ 320{
306 struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 321 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
307 unsigned long spi_hz, clk_hz, speed; 322 unsigned long spi_hz, clk_hz, speed;
308 unsigned long spi_used_hz, xfer_time_us; 323 unsigned long spi_used_hz;
324 unsigned long long xfer_time_us;
309 325
310 /* calculate the registers to handle 326 /* calculate the registers to handle
311 * 327 *
@@ -348,16 +364,19 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
348 bs->rx_buf = tfr->rx_buf; 364 bs->rx_buf = tfr->rx_buf;
349 bs->tx_len = tfr->len; 365 bs->tx_len = tfr->len;
350 bs->rx_len = tfr->len; 366 bs->rx_len = tfr->len;
367 bs->pending = 0;
351 368
352 /* calculate the estimated time in us the transfer runs */ 369 /* calculate the estimated time in us the transfer runs
353 xfer_time_us = tfr->len 370 * note that there are are 2 idle clocks after each
354 * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */ 371 * chunk getting transferred - in our case the chunk size
355 * 1000000 / spi_used_hz; 372 * is 3 bytes, so we approximate this by 9 bits/byte
373 */
374 xfer_time_us = tfr->len * 9 * 1000000;
375 do_div(xfer_time_us, spi_used_hz);
356 376
357 /* run in polling mode for short transfers */ 377 /* run in polling mode for short transfers */
358 if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US) 378 if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US)
359 return bcm2835aux_spi_transfer_one_poll(master, spi, tfr, 379 return bcm2835aux_spi_transfer_one_poll(master, spi, tfr);
360 xfer_time_us);
361 380
362 /* run in interrupt mode for all others */ 381 /* run in interrupt mode for all others */
363 return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); 382 return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);