diff options
author | Varadarajan Narayanan <varada@codeaurora.org> | 2017-07-28 02:52:57 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-08-08 07:15:39 -0400 |
commit | 5dc47fefe1d470da47dd400796bbf93ffe82fd33 (patch) | |
tree | 0451d79b6290e4d9afdd453254488851b5846ecb | |
parent | 3b5ea2c981dd470882bdc83e548dd15a942dbf4d (diff) |
spi: qup: allow block mode to generate multiple transactions
This let's you write more to the SPI bus than 64K-1 which is important
if the block size of a SPI device is >= 64K or some other device wants
to do something larger.
This has the benefit of completely removing spi_message from the spi-qup
transactions
Signed-off-by: Matthew McClintock <mmcclint@codeaurora.org>
Signed-off-by: Varadarajan Narayanan <varada@codeaurora.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/spi/spi-qup.c | 128 |
1 files changed, 80 insertions, 48 deletions
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 1aa60785bf98..707b1ec427fa 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c | |||
@@ -120,7 +120,7 @@ | |||
120 | 120 | ||
121 | #define SPI_NUM_CHIPSELECTS 4 | 121 | #define SPI_NUM_CHIPSELECTS 4 |
122 | 122 | ||
123 | #define SPI_MAX_DMA_XFER (SZ_64K - 64) | 123 | #define SPI_MAX_XFER (SZ_64K - 64) |
124 | 124 | ||
125 | /* high speed mode is when bus rate is greater then 26MHz */ | 125 | /* high speed mode is when bus rate is greater then 26MHz */ |
126 | #define SPI_HS_MIN_RATE 26000000 | 126 | #define SPI_HS_MIN_RATE 26000000 |
@@ -149,6 +149,8 @@ struct spi_qup { | |||
149 | int n_words; | 149 | int n_words; |
150 | int tx_bytes; | 150 | int tx_bytes; |
151 | int rx_bytes; | 151 | int rx_bytes; |
152 | const u8 *tx_buf; | ||
153 | u8 *rx_buf; | ||
152 | int qup_v1; | 154 | int qup_v1; |
153 | 155 | ||
154 | int mode; | 156 | int mode; |
@@ -173,6 +175,12 @@ static inline bool spi_qup_is_dma_xfer(int mode) | |||
173 | return false; | 175 | return false; |
174 | } | 176 | } |
175 | 177 | ||
178 | /* get's the transaction size length */ | ||
179 | static inline unsigned int spi_qup_len(struct spi_qup *controller) | ||
180 | { | ||
181 | return controller->n_words * controller->w_size; | ||
182 | } | ||
183 | |||
176 | static inline bool spi_qup_is_valid_state(struct spi_qup *controller) | 184 | static inline bool spi_qup_is_valid_state(struct spi_qup *controller) |
177 | { | 185 | { |
178 | u32 opstate = readl_relaxed(controller->base + QUP_STATE); | 186 | u32 opstate = readl_relaxed(controller->base + QUP_STATE); |
@@ -225,10 +233,9 @@ static int spi_qup_set_state(struct spi_qup *controller, u32 state) | |||
225 | return 0; | 233 | return 0; |
226 | } | 234 | } |
227 | 235 | ||
228 | static void spi_qup_read_from_fifo(struct spi_qup *controller, | 236 | static void spi_qup_read_from_fifo(struct spi_qup *controller, u32 num_words) |
229 | struct spi_transfer *xfer, u32 num_words) | ||
230 | { | 237 | { |
231 | u8 *rx_buf = xfer->rx_buf; | 238 | u8 *rx_buf = controller->rx_buf; |
232 | int i, shift, num_bytes; | 239 | int i, shift, num_bytes; |
233 | u32 word; | 240 | u32 word; |
234 | 241 | ||
@@ -236,8 +243,9 @@ static void spi_qup_read_from_fifo(struct spi_qup *controller, | |||
236 | 243 | ||
237 | word = readl_relaxed(controller->base + QUP_INPUT_FIFO); | 244 | word = readl_relaxed(controller->base + QUP_INPUT_FIFO); |
238 | 245 | ||
239 | num_bytes = min_t(int, xfer->len - controller->rx_bytes, | 246 | num_bytes = min_t(int, spi_qup_len(controller) - |
240 | controller->w_size); | 247 | controller->rx_bytes, |
248 | controller->w_size); | ||
241 | 249 | ||
242 | if (!rx_buf) { | 250 | if (!rx_buf) { |
243 | controller->rx_bytes += num_bytes; | 251 | controller->rx_bytes += num_bytes; |
@@ -258,13 +266,12 @@ static void spi_qup_read_from_fifo(struct spi_qup *controller, | |||
258 | } | 266 | } |
259 | } | 267 | } |
260 | 268 | ||
261 | static void spi_qup_read(struct spi_qup *controller, | 269 | static void spi_qup_read(struct spi_qup *controller) |
262 | struct spi_transfer *xfer) | ||
263 | { | 270 | { |
264 | u32 remainder, words_per_block, num_words; | 271 | u32 remainder, words_per_block, num_words; |
265 | bool is_block_mode = controller->mode == QUP_IO_M_MODE_BLOCK; | 272 | bool is_block_mode = controller->mode == QUP_IO_M_MODE_BLOCK; |
266 | 273 | ||
267 | remainder = DIV_ROUND_UP(xfer->len - controller->rx_bytes, | 274 | remainder = DIV_ROUND_UP(spi_qup_len(controller) - controller->rx_bytes, |
268 | controller->w_size); | 275 | controller->w_size); |
269 | words_per_block = controller->in_blk_sz >> 2; | 276 | words_per_block = controller->in_blk_sz >> 2; |
270 | 277 | ||
@@ -285,7 +292,7 @@ static void spi_qup_read(struct spi_qup *controller, | |||
285 | } | 292 | } |
286 | 293 | ||
287 | /* read up to the maximum transfer size available */ | 294 | /* read up to the maximum transfer size available */ |
288 | spi_qup_read_from_fifo(controller, xfer, num_words); | 295 | spi_qup_read_from_fifo(controller, num_words); |
289 | 296 | ||
290 | remainder -= num_words; | 297 | remainder -= num_words; |
291 | 298 | ||
@@ -307,18 +314,18 @@ static void spi_qup_read(struct spi_qup *controller, | |||
307 | 314 | ||
308 | } | 315 | } |
309 | 316 | ||
310 | static void spi_qup_write_to_fifo(struct spi_qup *controller, | 317 | static void spi_qup_write_to_fifo(struct spi_qup *controller, u32 num_words) |
311 | struct spi_transfer *xfer, u32 num_words) | ||
312 | { | 318 | { |
313 | const u8 *tx_buf = xfer->tx_buf; | 319 | const u8 *tx_buf = controller->tx_buf; |
314 | int i, num_bytes; | 320 | int i, num_bytes; |
315 | u32 word, data; | 321 | u32 word, data; |
316 | 322 | ||
317 | for (; num_words; num_words--) { | 323 | for (; num_words; num_words--) { |
318 | word = 0; | 324 | word = 0; |
319 | 325 | ||
320 | num_bytes = min_t(int, xfer->len - controller->tx_bytes, | 326 | num_bytes = min_t(int, spi_qup_len(controller) - |
321 | controller->w_size); | 327 | controller->tx_bytes, |
328 | controller->w_size); | ||
322 | if (tx_buf) | 329 | if (tx_buf) |
323 | for (i = 0; i < num_bytes; i++) { | 330 | for (i = 0; i < num_bytes; i++) { |
324 | data = tx_buf[controller->tx_bytes + i]; | 331 | data = tx_buf[controller->tx_bytes + i]; |
@@ -338,13 +345,12 @@ static void spi_qup_dma_done(void *data) | |||
338 | complete(&qup->done); | 345 | complete(&qup->done); |
339 | } | 346 | } |
340 | 347 | ||
341 | static void spi_qup_write(struct spi_qup *controller, | 348 | static void spi_qup_write(struct spi_qup *controller) |
342 | struct spi_transfer *xfer) | ||
343 | { | 349 | { |
344 | bool is_block_mode = controller->mode == QUP_IO_M_MODE_BLOCK; | 350 | bool is_block_mode = controller->mode == QUP_IO_M_MODE_BLOCK; |
345 | u32 remainder, words_per_block, num_words; | 351 | u32 remainder, words_per_block, num_words; |
346 | 352 | ||
347 | remainder = DIV_ROUND_UP(xfer->len - controller->tx_bytes, | 353 | remainder = DIV_ROUND_UP(spi_qup_len(controller) - controller->tx_bytes, |
348 | controller->w_size); | 354 | controller->w_size); |
349 | words_per_block = controller->out_blk_sz >> 2; | 355 | words_per_block = controller->out_blk_sz >> 2; |
350 | 356 | ||
@@ -364,7 +370,7 @@ static void spi_qup_write(struct spi_qup *controller, | |||
364 | num_words = 1; | 370 | num_words = 1; |
365 | } | 371 | } |
366 | 372 | ||
367 | spi_qup_write_to_fifo(controller, xfer, num_words); | 373 | spi_qup_write_to_fifo(controller, num_words); |
368 | 374 | ||
369 | remainder -= num_words; | 375 | remainder -= num_words; |
370 | 376 | ||
@@ -471,36 +477,62 @@ static int spi_qup_do_pio(struct spi_device *spi, struct spi_transfer *xfer, | |||
471 | { | 477 | { |
472 | struct spi_master *master = spi->master; | 478 | struct spi_master *master = spi->master; |
473 | struct spi_qup *qup = spi_master_get_devdata(master); | 479 | struct spi_qup *qup = spi_master_get_devdata(master); |
474 | int ret; | 480 | int ret, n_words, iterations, offset = 0; |
475 | 481 | ||
476 | ret = spi_qup_io_config(spi, xfer); | 482 | n_words = qup->n_words; |
477 | if (ret) | 483 | iterations = n_words / SPI_MAX_XFER; /* round down */ |
478 | return ret; | 484 | qup->rx_buf = xfer->rx_buf; |
485 | qup->tx_buf = xfer->tx_buf; | ||
479 | 486 | ||
480 | ret = spi_qup_set_state(qup, QUP_STATE_RUN); | 487 | do { |
481 | if (ret) { | 488 | if (iterations) |
482 | dev_warn(qup->dev, "cannot set RUN state\n"); | 489 | qup->n_words = SPI_MAX_XFER; |
483 | return ret; | 490 | else |
484 | } | 491 | qup->n_words = n_words % SPI_MAX_XFER; |
485 | 492 | ||
486 | ret = spi_qup_set_state(qup, QUP_STATE_PAUSE); | 493 | if (qup->tx_buf && offset) |
487 | if (ret) { | 494 | qup->tx_buf = xfer->tx_buf + offset * SPI_MAX_XFER; |
488 | dev_warn(qup->dev, "cannot set PAUSE state\n"); | ||
489 | return ret; | ||
490 | } | ||
491 | 495 | ||
492 | if (qup->mode == QUP_IO_M_MODE_FIFO) | 496 | if (qup->rx_buf && offset) |
493 | spi_qup_write(qup, xfer); | 497 | qup->rx_buf = xfer->rx_buf + offset * SPI_MAX_XFER; |
494 | 498 | ||
495 | ret = spi_qup_set_state(qup, QUP_STATE_RUN); | 499 | /* |
496 | if (ret) { | 500 | * if the transaction is small enough, we need |
497 | dev_warn(qup->dev, "%s(%d): cannot set RUN state\n", | 501 | * to fallback to FIFO mode |
498 | __func__, __LINE__); | 502 | */ |
499 | return ret; | 503 | if (qup->n_words <= (qup->in_fifo_sz / sizeof(u32))) |
500 | } | 504 | qup->mode = QUP_IO_M_MODE_FIFO; |
501 | 505 | ||
502 | if (!wait_for_completion_timeout(&qup->done, timeout)) | 506 | ret = spi_qup_io_config(spi, xfer); |
503 | return -ETIMEDOUT; | 507 | if (ret) |
508 | return ret; | ||
509 | |||
510 | ret = spi_qup_set_state(qup, QUP_STATE_RUN); | ||
511 | if (ret) { | ||
512 | dev_warn(qup->dev, "cannot set RUN state\n"); | ||
513 | return ret; | ||
514 | } | ||
515 | |||
516 | ret = spi_qup_set_state(qup, QUP_STATE_PAUSE); | ||
517 | if (ret) { | ||
518 | dev_warn(qup->dev, "cannot set PAUSE state\n"); | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | if (qup->mode == QUP_IO_M_MODE_FIFO) | ||
523 | spi_qup_write(qup); | ||
524 | |||
525 | ret = spi_qup_set_state(qup, QUP_STATE_RUN); | ||
526 | if (ret) { | ||
527 | dev_warn(qup->dev, "cannot set RUN state\n"); | ||
528 | return ret; | ||
529 | } | ||
530 | |||
531 | if (!wait_for_completion_timeout(&qup->done, timeout)) | ||
532 | return -ETIMEDOUT; | ||
533 | |||
534 | offset++; | ||
535 | } while (iterations--); | ||
504 | 536 | ||
505 | return 0; | 537 | return 0; |
506 | } | 538 | } |
@@ -508,7 +540,6 @@ static int spi_qup_do_pio(struct spi_device *spi, struct spi_transfer *xfer, | |||
508 | static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) | 540 | static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) |
509 | { | 541 | { |
510 | struct spi_qup *controller = dev_id; | 542 | struct spi_qup *controller = dev_id; |
511 | struct spi_transfer *xfer = controller->xfer; | ||
512 | u32 opflags, qup_err, spi_err; | 543 | u32 opflags, qup_err, spi_err; |
513 | int error = 0; | 544 | int error = 0; |
514 | 545 | ||
@@ -545,10 +576,10 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) | |||
545 | writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); | 576 | writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); |
546 | } else { | 577 | } else { |
547 | if (opflags & QUP_OP_IN_SERVICE_FLAG) | 578 | if (opflags & QUP_OP_IN_SERVICE_FLAG) |
548 | spi_qup_read(controller, xfer); | 579 | spi_qup_read(controller); |
549 | 580 | ||
550 | if (opflags & QUP_OP_OUT_SERVICE_FLAG) | 581 | if (opflags & QUP_OP_OUT_SERVICE_FLAG) |
551 | spi_qup_write(controller, xfer); | 582 | spi_qup_write(controller); |
552 | } | 583 | } |
553 | 584 | ||
554 | if ((opflags & QUP_OP_MAX_INPUT_DONE_FLAG) || error) | 585 | if ((opflags & QUP_OP_MAX_INPUT_DONE_FLAG) || error) |
@@ -755,7 +786,8 @@ static int spi_qup_transfer_one(struct spi_master *master, | |||
755 | return ret; | 786 | return ret; |
756 | 787 | ||
757 | timeout = DIV_ROUND_UP(xfer->speed_hz, MSEC_PER_SEC); | 788 | timeout = DIV_ROUND_UP(xfer->speed_hz, MSEC_PER_SEC); |
758 | timeout = DIV_ROUND_UP(xfer->len * 8, timeout); | 789 | timeout = DIV_ROUND_UP(min_t(unsigned long, SPI_MAX_XFER, |
790 | xfer->len) * 8, timeout); | ||
759 | timeout = 100 * msecs_to_jiffies(timeout); | 791 | timeout = 100 * msecs_to_jiffies(timeout); |
760 | 792 | ||
761 | reinit_completion(&controller->done); | 793 | reinit_completion(&controller->done); |
@@ -969,7 +1001,7 @@ static int spi_qup_probe(struct platform_device *pdev) | |||
969 | master->dev.of_node = pdev->dev.of_node; | 1001 | master->dev.of_node = pdev->dev.of_node; |
970 | master->auto_runtime_pm = true; | 1002 | master->auto_runtime_pm = true; |
971 | master->dma_alignment = dma_get_cache_alignment(); | 1003 | master->dma_alignment = dma_get_cache_alignment(); |
972 | master->max_dma_len = SPI_MAX_DMA_XFER; | 1004 | master->max_dma_len = SPI_MAX_XFER; |
973 | 1005 | ||
974 | platform_set_drvdata(pdev, master); | 1006 | platform_set_drvdata(pdev, master); |
975 | 1007 | ||