This set of patches provides a few fixes for the SPI QUP driver and support for
an earlier version of the QUP.
The first patch removes the use of the controller's own chip select
functionality. The user should instead use GPIOs and make use of the SPI core's
GPIO chip select feature.
The second patch addresses failures during probing of slave devices that
required SPI transactions. The spi_register_master needs to be called after
the runtime pm is initialized.
The last patch adds support for V1.1.1 of the QUP. This version of the
controller is present in earlier devices (APQ8064, IPQ8064, and MSM8960).
Andy Gross (3):
spi: qup: Remove chip select function
spi: qup: Fix order of spi_register_master
spi: qup: Add support for v1.1.1
.../devicetree/bindings/spi/qcom,spi-qup.txt | 12 ++-
drivers/spi/spi-qup.c | 80 +++++++++-----------
2 files changed, 46 insertions(+), 46 deletions(-)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
This patch removes the chip select function. Chip select should instead be
supported using GPIOs, defining the DT entry "cs-gpios", and letting the SPI
core assert/deassert the chip select as it sees fit.
Signed-off-by: Andy Gross <[email protected]>
---
.../devicetree/bindings/spi/qcom,spi-qup.txt | 6 ++++
drivers/spi/spi-qup.c | 33 ++++----------------
2 files changed, 12 insertions(+), 27 deletions(-)
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
index b82a268..bee6ff2 100644
--- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
@@ -23,6 +23,12 @@ Optional properties:
- spi-max-frequency: Specifies maximum SPI clock frequency,
Units - Hz. Definition as per
Documentation/devicetree/bindings/spi/spi-bus.txt
+- num-cs: total number of chipselects
+- cs-gpios: should specify GPIOs used for chipselects.
+ The gpios will be referred to as reg = <index> in the SPI child
+ nodes. If unspecified, a single SPI device without a chip
+ select can be used.
+
SPI slave nodes must be children of the SPI master node and can contain
properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
index fc1de86..3938c62 100644
--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -424,31 +424,6 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
return 0;
}
-static void spi_qup_set_cs(struct spi_device *spi, bool enable)
-{
- struct spi_qup *controller = spi_master_get_devdata(spi->master);
-
- u32 iocontol, mask;
-
- iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL);
-
- /* Disable auto CS toggle and use manual */
- iocontol &= ~SPI_IO_C_MX_CS_MODE;
- iocontol |= SPI_IO_C_FORCE_CS;
-
- iocontol &= ~SPI_IO_C_CS_SELECT_MASK;
- iocontol |= SPI_IO_C_CS_SELECT(spi->chip_select);
-
- mask = SPI_IO_C_CS_N_POLARITY_0 << spi->chip_select;
-
- if (enable)
- iocontol |= mask;
- else
- iocontol &= ~mask;
-
- writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL);
-}
-
static int spi_qup_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *xfer)
@@ -571,12 +546,16 @@ static int spi_qup_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ /* use num-cs unless not present or out of range */
+ if (of_property_read_u16(dev->of_node, "num-cs",
+ &master->num_chipselect) ||
+ (master->num_chipselect > SPI_NUM_CHIPSELECTS))
+ master->num_chipselect = SPI_NUM_CHIPSELECTS;
+
master->bus_num = pdev->id;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
- master->num_chipselect = SPI_NUM_CHIPSELECTS;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->max_speed_hz = max_freq;
- master->set_cs = spi_qup_set_cs;
master->transfer_one = spi_qup_transfer_one;
master->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
This patch adds support for v1.1.1 of the SPI QUP controller.
Signed-off-by: Andy Gross <[email protected]>
---
.../devicetree/bindings/spi/qcom,spi-qup.txt | 6 +++-
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 bee6ff2..e2c88df 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
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
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
index c08da38..9f83d29 100644
--- 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;
};
@@ -420,7 +421,9 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
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;
}
@@ -486,7 +489,7 @@ static int spi_qup_probe(struct platform_device *pdev)
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;
@@ -529,15 +532,6 @@ static int spi_qup_probe(struct platform_device *pdev)
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);
@@ -570,6 +564,10 @@ static int spi_qup_probe(struct platform_device *pdev)
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);
@@ -593,8 +591,8 @@ static int spi_qup_probe(struct platform_device *pdev)
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);
@@ -607,10 +605,19 @@ static int spi_qup_probe(struct platform_device *pdev)
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);
@@ -732,6 +739,7 @@ static int spi_qup_remove(struct platform_device *pdev)
}
static const 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", },
{ }
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
This patch moves the devm_spi_register_master below the initialization of the
runtime_pm. If done in the wrong order, the spi_register_master fails if any
probed slave devices issue SPI transactions.
Signed-off-by: Andy Gross <[email protected]>
Acked-by: Ivan T. Ivanov <[email protected]>
---
drivers/spi/spi-qup.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
index 3938c62..c08da38 100644
--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -619,16 +619,19 @@ static int spi_qup_probe(struct platform_device *pdev)
if (ret)
goto error;
- ret = devm_spi_register_master(dev, master);
- if (ret)
- goto error;
-
pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
+
+ ret = devm_spi_register_master(dev, master);
+ if (ret)
+ goto disable_pm;
+
return 0;
+disable_pm:
+ pm_runtime_disable(&pdev->dev);
error:
clk_disable_unprepare(cclk);
clk_disable_unprepare(iclk);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
On Jun 12, 2014, at 2:34 PM, Andy Gross <[email protected]> wrote:
> This patch adds support for v1.1.1 of the SPI QUP controller.
>
> Signed-off-by: Andy Gross <[email protected]>
> ---
> .../devicetree/bindings/spi/qcom,spi-qup.txt | 6 +++-
> 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 bee6ff2..e2c88df 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
> 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.
> +
We should probably try to be a bit more clear about ipq/apq/msm here.
> - reg: Should contain base register location and length
> - interrupts: Interrupt number used by this controller
- k
--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
On Thu, Jun 12, 2014 at 02:34:11PM -0500, Andy Gross wrote:
> This patch moves the devm_spi_register_master below the initialization of the
> runtime_pm. If done in the wrong order, the spi_register_master fails if any
> probed slave devices issue SPI transactions.
Applied, thanks.
On Thu, Jun 12, 2014 at 02:34:10PM -0500, Andy Gross wrote:
> This patch removes the chip select function. Chip select should instead be
> supported using GPIOs, defining the DT entry "cs-gpios", and letting the SPI
> core assert/deassert the chip select as it sees fit.
Why?
On Thu, Jun 12, 2014 at 02:34:12PM -0500, Andy Gross wrote:
> This patch adds support for v1.1.1 of the SPI QUP controller.
Applied, thanks.
On Sat, Jun 21, 2014 at 11:13:03AM +0100, Mark Brown wrote:
> On Thu, Jun 12, 2014 at 02:34:10PM -0500, Andy Gross wrote:
> > This patch removes the chip select function. Chip select should instead be
> > supported using GPIOs, defining the DT entry "cs-gpios", and letting the SPI
> > core assert/deassert the chip select as it sees fit.
>
> Why?
The chip select control inside the controller is buggy. It is supposed to
automatically assert the chip select based on the activity in the controller,
but it is buggy and doesn't work at all. So instead we elect to use GPIOs.
--
sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
On Sat, Jun 21, 2014 at 01:56:46PM -0500, Andy Gross wrote:
> On Sat, Jun 21, 2014 at 11:13:03AM +0100, Mark Brown wrote:
> > On Thu, Jun 12, 2014 at 02:34:10PM -0500, Andy Gross wrote:
> > > This patch removes the chip select function. Chip select should instead be
> > > supported using GPIOs, defining the DT entry "cs-gpios", and letting the SPI
> > > core assert/deassert the chip select as it sees fit.
> > Why?
> The chip select control inside the controller is buggy. It is supposed to
> automatically assert the chip select based on the activity in the controller,
> but it is buggy and doesn't work at all. So instead we elect to use GPIOs.
OK, though it was in manual mode.