diff options
author | Andy Gross <agross@codeaurora.org> | 2014-06-12 15:34:12 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-06-21 06:13:19 -0400 |
commit | 70cea0a95331fe7593f125e2d791c2d5ae454c94 (patch) | |
tree | 623113b5705b3904095c31b65607829989ba7eff | |
parent | 7171511eaec5bf23fb06078f59784a3a0626b38f (diff) |
spi: qup: Add support for v1.1.1
This patch adds support for v1.1.1 of the SPI QUP controller.
Signed-off-by: Andy Gross <agross@codeaurora.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | Documentation/devicetree/bindings/spi/qcom,spi-qup.txt | 6 | ||||
-rw-r--r-- | drivers/spi/spi-qup.c | 36 |
2 files changed, 27 insertions, 15 deletions
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt index b82a268f1bd4..775a2d86f502 100644 --- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt +++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt | |||
@@ -7,7 +7,11 @@ SPI in master mode supports up to 50MHz, up to four chip selects, programmable | |||
7 | data path from 4 bits to 32 bits and numerous protocol variants. | 7 | data path from 4 bits to 32 bits and numerous protocol variants. |
8 | 8 | ||
9 | Required properties: | 9 | Required properties: |
10 | - compatible: Should contain "qcom,spi-qup-v2.1.1" or "qcom,spi-qup-v2.2.1" | 10 | - compatible: Should contain: |
11 | "qcom,spi-qup-v1.1.1" for 8660, 8960 and 8064. | ||
12 | "qcom,spi-qup-v2.1.1" for 8974 and later | ||
13 | "qcom,spi-qup-v2.2.1" for 8974 v2 and later. | ||
14 | |||
11 | - reg: Should contain base register location and length | 15 | - reg: Should contain base register location and length |
12 | - interrupts: Interrupt number used by this controller | 16 | - interrupts: Interrupt number used by this controller |
13 | 17 | ||
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index fc1de86d3c8a..f5b646e35cc4 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c | |||
@@ -142,6 +142,7 @@ struct spi_qup { | |||
142 | int w_size; /* bytes per SPI word */ | 142 | int w_size; /* bytes per SPI word */ |
143 | int tx_bytes; | 143 | int tx_bytes; |
144 | int rx_bytes; | 144 | int rx_bytes; |
145 | int qup_v1; | ||
145 | }; | 146 | }; |
146 | 147 | ||
147 | 148 | ||
@@ -420,7 +421,9 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) | |||
420 | config |= QUP_CONFIG_SPI_MODE; | 421 | config |= QUP_CONFIG_SPI_MODE; |
421 | writel_relaxed(config, controller->base + QUP_CONFIG); | 422 | writel_relaxed(config, controller->base + QUP_CONFIG); |
422 | 423 | ||
423 | writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK); | 424 | /* only write to OPERATIONAL_MASK when register is present */ |
425 | if (!controller->qup_v1) | ||
426 | writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK); | ||
424 | return 0; | 427 | return 0; |
425 | } | 428 | } |
426 | 429 | ||
@@ -511,7 +514,7 @@ static int spi_qup_probe(struct platform_device *pdev) | |||
511 | struct resource *res; | 514 | struct resource *res; |
512 | struct device *dev; | 515 | struct device *dev; |
513 | void __iomem *base; | 516 | void __iomem *base; |
514 | u32 data, max_freq, iomode; | 517 | u32 max_freq, iomode; |
515 | int ret, irq, size; | 518 | int ret, irq, size; |
516 | 519 | ||
517 | dev = &pdev->dev; | 520 | dev = &pdev->dev; |
@@ -554,15 +557,6 @@ static int spi_qup_probe(struct platform_device *pdev) | |||
554 | return ret; | 557 | return ret; |
555 | } | 558 | } |
556 | 559 | ||
557 | data = readl_relaxed(base + QUP_HW_VERSION); | ||
558 | |||
559 | if (data < QUP_HW_VERSION_2_1_1) { | ||
560 | clk_disable_unprepare(cclk); | ||
561 | clk_disable_unprepare(iclk); | ||
562 | dev_err(dev, "v.%08x is not supported\n", data); | ||
563 | return -ENXIO; | ||
564 | } | ||
565 | |||
566 | master = spi_alloc_master(dev, sizeof(struct spi_qup)); | 560 | master = spi_alloc_master(dev, sizeof(struct spi_qup)); |
567 | if (!master) { | 561 | if (!master) { |
568 | clk_disable_unprepare(cclk); | 562 | clk_disable_unprepare(cclk); |
@@ -591,6 +585,10 @@ static int spi_qup_probe(struct platform_device *pdev) | |||
591 | controller->cclk = cclk; | 585 | controller->cclk = cclk; |
592 | controller->irq = irq; | 586 | controller->irq = irq; |
593 | 587 | ||
588 | /* set v1 flag if device is version 1 */ | ||
589 | if (of_device_is_compatible(dev->of_node, "qcom,spi-qup-v1.1.1")) | ||
590 | controller->qup_v1 = 1; | ||
591 | |||
594 | spin_lock_init(&controller->lock); | 592 | spin_lock_init(&controller->lock); |
595 | init_completion(&controller->done); | 593 | init_completion(&controller->done); |
596 | 594 | ||
@@ -614,8 +612,8 @@ static int spi_qup_probe(struct platform_device *pdev) | |||
614 | size = QUP_IO_M_INPUT_FIFO_SIZE(iomode); | 612 | size = QUP_IO_M_INPUT_FIFO_SIZE(iomode); |
615 | controller->in_fifo_sz = controller->in_blk_sz * (2 << size); | 613 | controller->in_fifo_sz = controller->in_blk_sz * (2 << size); |
616 | 614 | ||
617 | dev_info(dev, "v.%08x IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", | 615 | dev_info(dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", |
618 | data, controller->in_blk_sz, controller->in_fifo_sz, | 616 | controller->in_blk_sz, controller->in_fifo_sz, |
619 | controller->out_blk_sz, controller->out_fifo_sz); | 617 | controller->out_blk_sz, controller->out_fifo_sz); |
620 | 618 | ||
621 | writel_relaxed(1, base + QUP_SW_RESET); | 619 | writel_relaxed(1, base + QUP_SW_RESET); |
@@ -628,10 +626,19 @@ static int spi_qup_probe(struct platform_device *pdev) | |||
628 | 626 | ||
629 | writel_relaxed(0, base + QUP_OPERATIONAL); | 627 | writel_relaxed(0, base + QUP_OPERATIONAL); |
630 | writel_relaxed(0, base + QUP_IO_M_MODES); | 628 | writel_relaxed(0, base + QUP_IO_M_MODES); |
631 | writel_relaxed(0, base + QUP_OPERATIONAL_MASK); | 629 | |
630 | if (!controller->qup_v1) | ||
631 | writel_relaxed(0, base + QUP_OPERATIONAL_MASK); | ||
632 | |||
632 | writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN, | 633 | writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN, |
633 | base + SPI_ERROR_FLAGS_EN); | 634 | base + SPI_ERROR_FLAGS_EN); |
634 | 635 | ||
636 | /* if earlier version of the QUP, disable INPUT_OVERRUN */ | ||
637 | if (controller->qup_v1) | ||
638 | writel_relaxed(QUP_ERROR_OUTPUT_OVER_RUN | | ||
639 | QUP_ERROR_INPUT_UNDER_RUN | QUP_ERROR_OUTPUT_UNDER_RUN, | ||
640 | base + QUP_ERROR_FLAGS_EN); | ||
641 | |||
635 | writel_relaxed(0, base + SPI_CONFIG); | 642 | writel_relaxed(0, base + SPI_CONFIG); |
636 | writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL); | 643 | writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL); |
637 | 644 | ||
@@ -750,6 +757,7 @@ static int spi_qup_remove(struct platform_device *pdev) | |||
750 | } | 757 | } |
751 | 758 | ||
752 | static const struct of_device_id spi_qup_dt_match[] = { | 759 | static const struct of_device_id spi_qup_dt_match[] = { |
760 | { .compatible = "qcom,spi-qup-v1.1.1", }, | ||
753 | { .compatible = "qcom,spi-qup-v2.1.1", }, | 761 | { .compatible = "qcom,spi-qup-v2.1.1", }, |
754 | { .compatible = "qcom,spi-qup-v2.2.1", }, | 762 | { .compatible = "qcom,spi-qup-v2.2.1", }, |
755 | { } | 763 | { } |