diff options
-rw-r--r-- | drivers/spi/spi-qup.c | 118 |
1 files changed, 55 insertions, 63 deletions
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index c0d4defc1c13..abe799bbc67f 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c | |||
@@ -149,11 +149,18 @@ struct spi_qup { | |||
149 | int rx_bytes; | 149 | int rx_bytes; |
150 | int qup_v1; | 150 | int qup_v1; |
151 | 151 | ||
152 | int use_dma; | 152 | int mode; |
153 | struct dma_slave_config rx_conf; | 153 | struct dma_slave_config rx_conf; |
154 | struct dma_slave_config tx_conf; | 154 | struct dma_slave_config tx_conf; |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static inline bool spi_qup_is_dma_xfer(int mode) | ||
158 | { | ||
159 | if (mode == QUP_IO_M_MODE_DMOV || mode == QUP_IO_M_MODE_BAM) | ||
160 | return true; | ||
161 | |||
162 | return false; | ||
163 | } | ||
157 | 164 | ||
158 | static inline bool spi_qup_is_valid_state(struct spi_qup *controller) | 165 | static inline bool spi_qup_is_valid_state(struct spi_qup *controller) |
159 | { | 166 | { |
@@ -424,7 +431,7 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) | |||
424 | error = -EIO; | 431 | error = -EIO; |
425 | } | 432 | } |
426 | 433 | ||
427 | if (!controller->use_dma) { | 434 | if (!spi_qup_is_dma_xfer(controller->mode)) { |
428 | if (opflags & QUP_OP_IN_SERVICE_FLAG) | 435 | if (opflags & QUP_OP_IN_SERVICE_FLAG) |
429 | spi_qup_fifo_read(controller, xfer); | 436 | spi_qup_fifo_read(controller, xfer); |
430 | 437 | ||
@@ -443,34 +450,11 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) | |||
443 | return IRQ_HANDLED; | 450 | return IRQ_HANDLED; |
444 | } | 451 | } |
445 | 452 | ||
446 | static u32 | ||
447 | spi_qup_get_mode(struct spi_master *master, struct spi_transfer *xfer) | ||
448 | { | ||
449 | struct spi_qup *qup = spi_master_get_devdata(master); | ||
450 | u32 mode; | ||
451 | |||
452 | qup->w_size = 4; | ||
453 | |||
454 | if (xfer->bits_per_word <= 8) | ||
455 | qup->w_size = 1; | ||
456 | else if (xfer->bits_per_word <= 16) | ||
457 | qup->w_size = 2; | ||
458 | |||
459 | qup->n_words = xfer->len / qup->w_size; | ||
460 | |||
461 | if (qup->n_words <= (qup->in_fifo_sz / sizeof(u32))) | ||
462 | mode = QUP_IO_M_MODE_FIFO; | ||
463 | else | ||
464 | mode = QUP_IO_M_MODE_BLOCK; | ||
465 | |||
466 | return mode; | ||
467 | } | ||
468 | |||
469 | /* set clock freq ... bits per word */ | 453 | /* set clock freq ... bits per word */ |
470 | static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) | 454 | static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) |
471 | { | 455 | { |
472 | struct spi_qup *controller = spi_master_get_devdata(spi->master); | 456 | struct spi_qup *controller = spi_master_get_devdata(spi->master); |
473 | u32 config, iomode, mode, control; | 457 | u32 config, iomode, control; |
474 | int ret, n_words; | 458 | int ret, n_words; |
475 | 459 | ||
476 | if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) { | 460 | if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) { |
@@ -491,25 +475,30 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) | |||
491 | return -EIO; | 475 | return -EIO; |
492 | } | 476 | } |
493 | 477 | ||
494 | mode = spi_qup_get_mode(spi->master, xfer); | 478 | controller->w_size = DIV_ROUND_UP(xfer->bits_per_word, 8); |
479 | controller->n_words = xfer->len / controller->w_size; | ||
495 | n_words = controller->n_words; | 480 | n_words = controller->n_words; |
496 | 481 | ||
497 | if (mode == QUP_IO_M_MODE_FIFO) { | 482 | if (n_words <= (controller->in_fifo_sz / sizeof(u32))) { |
483 | |||
484 | controller->mode = QUP_IO_M_MODE_FIFO; | ||
485 | |||
498 | writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT); | 486 | writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT); |
499 | writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT); | 487 | writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT); |
500 | /* must be zero for FIFO */ | 488 | /* must be zero for FIFO */ |
501 | writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT); | 489 | writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT); |
502 | writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); | 490 | writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); |
503 | } else if (!controller->use_dma) { | 491 | } else if (spi->master->can_dma && |
492 | spi->master->can_dma(spi->master, spi, xfer) && | ||
493 | spi->master->cur_msg_mapped) { | ||
494 | |||
495 | controller->mode = QUP_IO_M_MODE_BAM; | ||
496 | |||
504 | writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT); | 497 | writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT); |
505 | writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT); | 498 | writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT); |
506 | /* must be zero for BLOCK and BAM */ | 499 | /* must be zero for BLOCK and BAM */ |
507 | writel_relaxed(0, controller->base + QUP_MX_READ_CNT); | 500 | writel_relaxed(0, controller->base + QUP_MX_READ_CNT); |
508 | writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); | 501 | writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); |
509 | } else { | ||
510 | mode = QUP_IO_M_MODE_BAM; | ||
511 | writel_relaxed(0, controller->base + QUP_MX_READ_CNT); | ||
512 | writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); | ||
513 | 502 | ||
514 | if (!controller->qup_v1) { | 503 | if (!controller->qup_v1) { |
515 | void __iomem *input_cnt; | 504 | void __iomem *input_cnt; |
@@ -528,19 +517,28 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) | |||
528 | 517 | ||
529 | writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); | 518 | writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); |
530 | } | 519 | } |
520 | } else { | ||
521 | |||
522 | controller->mode = QUP_IO_M_MODE_BLOCK; | ||
523 | |||
524 | writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT); | ||
525 | writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT); | ||
526 | /* must be zero for BLOCK and BAM */ | ||
527 | writel_relaxed(0, controller->base + QUP_MX_READ_CNT); | ||
528 | writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); | ||
531 | } | 529 | } |
532 | 530 | ||
533 | iomode = readl_relaxed(controller->base + QUP_IO_M_MODES); | 531 | iomode = readl_relaxed(controller->base + QUP_IO_M_MODES); |
534 | /* Set input and output transfer mode */ | 532 | /* Set input and output transfer mode */ |
535 | iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK); | 533 | iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK); |
536 | 534 | ||
537 | if (!controller->use_dma) | 535 | if (!spi_qup_is_dma_xfer(controller->mode)) |
538 | iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN); | 536 | iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN); |
539 | else | 537 | else |
540 | iomode |= QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN; | 538 | iomode |= QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN; |
541 | 539 | ||
542 | iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT); | 540 | iomode |= (controller->mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT); |
543 | iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT); | 541 | iomode |= (controller->mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT); |
544 | 542 | ||
545 | writel_relaxed(iomode, controller->base + QUP_IO_M_MODES); | 543 | writel_relaxed(iomode, controller->base + QUP_IO_M_MODES); |
546 | 544 | ||
@@ -581,7 +579,7 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) | |||
581 | config |= xfer->bits_per_word - 1; | 579 | config |= xfer->bits_per_word - 1; |
582 | config |= QUP_CONFIG_SPI_MODE; | 580 | config |= QUP_CONFIG_SPI_MODE; |
583 | 581 | ||
584 | if (controller->use_dma) { | 582 | if (spi_qup_is_dma_xfer(controller->mode)) { |
585 | if (!xfer->tx_buf) | 583 | if (!xfer->tx_buf) |
586 | config |= QUP_CONFIG_NO_OUTPUT; | 584 | config |= QUP_CONFIG_NO_OUTPUT; |
587 | if (!xfer->rx_buf) | 585 | if (!xfer->rx_buf) |
@@ -599,7 +597,7 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) | |||
599 | * status change in BAM mode | 597 | * status change in BAM mode |
600 | */ | 598 | */ |
601 | 599 | ||
602 | if (mode == QUP_IO_M_MODE_BAM) | 600 | if (spi_qup_is_dma_xfer(controller->mode)) |
603 | mask = QUP_OP_IN_SERVICE_FLAG | QUP_OP_OUT_SERVICE_FLAG; | 601 | mask = QUP_OP_IN_SERVICE_FLAG | QUP_OP_OUT_SERVICE_FLAG; |
604 | 602 | ||
605 | writel_relaxed(mask, controller->base + QUP_OPERATIONAL_MASK); | 603 | writel_relaxed(mask, controller->base + QUP_OPERATIONAL_MASK); |
@@ -633,7 +631,7 @@ static int spi_qup_transfer_one(struct spi_master *master, | |||
633 | controller->tx_bytes = 0; | 631 | controller->tx_bytes = 0; |
634 | spin_unlock_irqrestore(&controller->lock, flags); | 632 | spin_unlock_irqrestore(&controller->lock, flags); |
635 | 633 | ||
636 | if (controller->use_dma) | 634 | if (spi_qup_is_dma_xfer(controller->mode)) |
637 | ret = spi_qup_do_dma(master, xfer); | 635 | ret = spi_qup_do_dma(master, xfer); |
638 | else | 636 | else |
639 | ret = spi_qup_do_pio(master, xfer); | 637 | ret = spi_qup_do_pio(master, xfer); |
@@ -641,14 +639,6 @@ static int spi_qup_transfer_one(struct spi_master *master, | |||
641 | if (ret) | 639 | if (ret) |
642 | goto exit; | 640 | goto exit; |
643 | 641 | ||
644 | if (spi_qup_set_state(controller, QUP_STATE_RUN)) { | ||
645 | dev_warn(controller->dev, "cannot set EXECUTE state\n"); | ||
646 | goto exit; | ||
647 | } | ||
648 | |||
649 | if (!wait_for_completion_timeout(&controller->done, timeout)) | ||
650 | ret = -ETIMEDOUT; | ||
651 | |||
652 | exit: | 642 | exit: |
653 | spi_qup_set_state(controller, QUP_STATE_RESET); | 643 | spi_qup_set_state(controller, QUP_STATE_RESET); |
654 | spin_lock_irqsave(&controller->lock, flags); | 644 | spin_lock_irqsave(&controller->lock, flags); |
@@ -657,7 +647,7 @@ exit: | |||
657 | ret = controller->error; | 647 | ret = controller->error; |
658 | spin_unlock_irqrestore(&controller->lock, flags); | 648 | spin_unlock_irqrestore(&controller->lock, flags); |
659 | 649 | ||
660 | if (ret && controller->use_dma) | 650 | if (ret && spi_qup_is_dma_xfer(controller->mode)) |
661 | spi_qup_dma_terminate(master, xfer); | 651 | spi_qup_dma_terminate(master, xfer); |
662 | 652 | ||
663 | return ret; | 653 | return ret; |
@@ -668,26 +658,28 @@ static bool spi_qup_can_dma(struct spi_master *master, struct spi_device *spi, | |||
668 | { | 658 | { |
669 | struct spi_qup *qup = spi_master_get_devdata(master); | 659 | struct spi_qup *qup = spi_master_get_devdata(master); |
670 | size_t dma_align = dma_get_cache_alignment(); | 660 | size_t dma_align = dma_get_cache_alignment(); |
671 | u32 mode; | 661 | int n_words; |
672 | |||
673 | qup->use_dma = 0; | ||
674 | 662 | ||
675 | if (xfer->rx_buf && (xfer->len % qup->in_blk_sz || | 663 | if (xfer->rx_buf) { |
676 | IS_ERR_OR_NULL(master->dma_rx) || | 664 | if (!IS_ALIGNED((size_t)xfer->rx_buf, dma_align) || |
677 | !IS_ALIGNED((size_t)xfer->rx_buf, dma_align))) | 665 | IS_ERR_OR_NULL(master->dma_rx)) |
678 | return false; | 666 | return false; |
667 | if (qup->qup_v1 && (xfer->len % qup->in_blk_sz)) | ||
668 | return false; | ||
669 | } | ||
679 | 670 | ||
680 | if (xfer->tx_buf && (xfer->len % qup->out_blk_sz || | 671 | if (xfer->tx_buf) { |
681 | IS_ERR_OR_NULL(master->dma_tx) || | 672 | if (!IS_ALIGNED((size_t)xfer->tx_buf, dma_align) || |
682 | !IS_ALIGNED((size_t)xfer->tx_buf, dma_align))) | 673 | IS_ERR_OR_NULL(master->dma_tx)) |
683 | return false; | 674 | return false; |
675 | if (qup->qup_v1 && (xfer->len % qup->out_blk_sz)) | ||
676 | return false; | ||
677 | } | ||
684 | 678 | ||
685 | mode = spi_qup_get_mode(master, xfer); | 679 | n_words = xfer->len / DIV_ROUND_UP(xfer->bits_per_word, 8); |
686 | if (mode == QUP_IO_M_MODE_FIFO) | 680 | if (n_words <= (qup->in_fifo_sz / sizeof(u32))) |
687 | return false; | 681 | return false; |
688 | 682 | ||
689 | qup->use_dma = 1; | ||
690 | |||
691 | return true; | 683 | return true; |
692 | } | 684 | } |
693 | 685 | ||