2014-08-30 17:32:58 +08:00
|
|
|
From 8b9de04ef3aaa154f30baf1ac703a2d3b474ad4e Mon Sep 17 00:00:00 2001
|
|
|
|
From: Andy Gross <agross@codeaurora.org>
|
|
|
|
Date: Thu, 12 Jun 2014 14:34:12 -0500
|
|
|
|
Subject: [PATCH 135/182] 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>
|
|
|
|
---
|
|
|
|
.../devicetree/bindings/spi/qcom,spi-qup.txt | 6 +++-
|
|
|
|
drivers/spi/spi-qup.c | 36 ++++++++++++--------
|
|
|
|
2 files changed, 27 insertions(+), 15 deletions(-)
|
|
|
|
|
|
|
|
--- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
|
|
|
|
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
|
2014-09-11 05:40:19 +08:00
|
|
|
@@ -7,7 +7,11 @@ SPI in master mode supports up to 50MHz,
|
2014-08-30 17:32:58 +08:00
|
|
|
data path from 4 bits to 32 bits and numerous protocol variants.
|
|
|
|
|
|
|
|
Required properties:
|
|
|
|
-- compatible: Should contain "qcom,spi-qup-v2.1.1" or "qcom,spi-qup-v2.2.1"
|
|
|
|
+- compatible: Should contain:
|
|
|
|
+ "qcom,spi-qup-v1.1.1" for 8660, 8960 and 8064.
|
|
|
|
+ "qcom,spi-qup-v2.1.1" for 8974 and later
|
|
|
|
+ "qcom,spi-qup-v2.2.1" for 8974 v2 and later.
|
|
|
|
+
|
|
|
|
- reg: Should contain base register location and length
|
|
|
|
- interrupts: Interrupt number used by this controller
|
|
|
|
|
|
|
|
--- a/drivers/spi/spi-qup.c
|
|
|
|
+++ b/drivers/spi/spi-qup.c
|
|
|
|
@@ -142,6 +142,7 @@ struct spi_qup {
|
|
|
|
int w_size; /* bytes per SPI word */
|
|
|
|
int tx_bytes;
|
|
|
|
int rx_bytes;
|
|
|
|
+ int qup_v1;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-09-11 05:40:19 +08:00
|
|
|
@@ -420,7 +421,9 @@ static int spi_qup_io_config(struct spi_
|
2014-08-30 17:32:58 +08:00
|
|
|
config |= QUP_CONFIG_SPI_MODE;
|
|
|
|
writel_relaxed(config, controller->base + QUP_CONFIG);
|
|
|
|
|
|
|
|
- writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
|
|
|
|
+ /* only write to OPERATIONAL_MASK when register is present */
|
|
|
|
+ if (!controller->qup_v1)
|
|
|
|
+ writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-11 05:40:19 +08:00
|
|
|
@@ -486,7 +489,7 @@ static int spi_qup_probe(struct platform
|
2014-08-30 17:32:58 +08:00
|
|
|
struct resource *res;
|
|
|
|
struct device *dev;
|
|
|
|
void __iomem *base;
|
|
|
|
- u32 data, max_freq, iomode;
|
|
|
|
+ u32 max_freq, iomode;
|
|
|
|
int ret, irq, size;
|
|
|
|
|
|
|
|
dev = &pdev->dev;
|
2014-09-11 05:40:19 +08:00
|
|
|
@@ -529,15 +532,6 @@ static int spi_qup_probe(struct platform
|
2014-08-30 17:32:58 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
- data = readl_relaxed(base + QUP_HW_VERSION);
|
|
|
|
-
|
|
|
|
- if (data < QUP_HW_VERSION_2_1_1) {
|
|
|
|
- clk_disable_unprepare(cclk);
|
|
|
|
- clk_disable_unprepare(iclk);
|
|
|
|
- dev_err(dev, "v.%08x is not supported\n", data);
|
|
|
|
- return -ENXIO;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
master = spi_alloc_master(dev, sizeof(struct spi_qup));
|
|
|
|
if (!master) {
|
|
|
|
clk_disable_unprepare(cclk);
|
2014-09-11 05:40:19 +08:00
|
|
|
@@ -570,6 +564,10 @@ static int spi_qup_probe(struct platform
|
2014-08-30 17:32:58 +08:00
|
|
|
controller->cclk = cclk;
|
|
|
|
controller->irq = irq;
|
|
|
|
|
|
|
|
+ /* set v1 flag if device is version 1 */
|
|
|
|
+ if (of_device_is_compatible(dev->of_node, "qcom,spi-qup-v1.1.1"))
|
|
|
|
+ controller->qup_v1 = 1;
|
|
|
|
+
|
|
|
|
spin_lock_init(&controller->lock);
|
|
|
|
init_completion(&controller->done);
|
|
|
|
|
2014-09-11 05:40:19 +08:00
|
|
|
@@ -593,8 +591,8 @@ static int spi_qup_probe(struct platform
|
2014-08-30 17:32:58 +08:00
|
|
|
size = QUP_IO_M_INPUT_FIFO_SIZE(iomode);
|
|
|
|
controller->in_fifo_sz = controller->in_blk_sz * (2 << size);
|
|
|
|
|
|
|
|
- dev_info(dev, "v.%08x IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
|
|
|
|
- data, controller->in_blk_sz, controller->in_fifo_sz,
|
|
|
|
+ dev_info(dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
|
|
|
|
+ controller->in_blk_sz, controller->in_fifo_sz,
|
|
|
|
controller->out_blk_sz, controller->out_fifo_sz);
|
|
|
|
|
|
|
|
writel_relaxed(1, base + QUP_SW_RESET);
|
2014-09-11 05:40:19 +08:00
|
|
|
@@ -607,10 +605,19 @@ static int spi_qup_probe(struct platform
|
2014-08-30 17:32:58 +08:00
|
|
|
|
|
|
|
writel_relaxed(0, base + QUP_OPERATIONAL);
|
|
|
|
writel_relaxed(0, base + QUP_IO_M_MODES);
|
|
|
|
- writel_relaxed(0, base + QUP_OPERATIONAL_MASK);
|
|
|
|
+
|
|
|
|
+ if (!controller->qup_v1)
|
|
|
|
+ writel_relaxed(0, base + QUP_OPERATIONAL_MASK);
|
|
|
|
+
|
|
|
|
writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN,
|
|
|
|
base + SPI_ERROR_FLAGS_EN);
|
|
|
|
|
|
|
|
+ /* if earlier version of the QUP, disable INPUT_OVERRUN */
|
|
|
|
+ if (controller->qup_v1)
|
|
|
|
+ writel_relaxed(QUP_ERROR_OUTPUT_OVER_RUN |
|
|
|
|
+ QUP_ERROR_INPUT_UNDER_RUN | QUP_ERROR_OUTPUT_UNDER_RUN,
|
|
|
|
+ base + QUP_ERROR_FLAGS_EN);
|
|
|
|
+
|
|
|
|
writel_relaxed(0, base + SPI_CONFIG);
|
|
|
|
writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL);
|
|
|
|
|
2014-09-11 05:40:19 +08:00
|
|
|
@@ -732,6 +739,7 @@ static int spi_qup_remove(struct platfor
|
2014-08-30 17:32:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct of_device_id spi_qup_dt_match[] = {
|
|
|
|
+ { .compatible = "qcom,spi-qup-v1.1.1", },
|
|
|
|
{ .compatible = "qcom,spi-qup-v2.1.1", },
|
|
|
|
{ .compatible = "qcom,spi-qup-v2.2.1", },
|
|
|
|
{ }
|