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 | { } |
