aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt64
-rw-r--r--Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt23
-rw-r--r--Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml50
-rw-r--r--Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml55
-rw-r--r--Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml35
-rw-r--r--drivers/spi/atmel-quadspi.c11
-rw-r--r--drivers/spi/spi-axi-spi-engine.c34
-rw-r--r--drivers/spi/spi-imx.c5
-rw-r--r--drivers/spi/spi.c29
9 files changed, 191 insertions, 115 deletions
diff --git a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
deleted file mode 100644
index d10cc06c0c37..000000000000
--- a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-Device tree bindings for Marvell PXA SSP ports
-
-Required properties:
-
- - compatible: Must be one of
- mrvl,pxa25x-ssp
- mvrl,pxa25x-nssp
- mrvl,pxa27x-ssp
- mrvl,pxa3xx-ssp
- mvrl,pxa168-ssp
- mrvl,pxa910-ssp
- mrvl,ce4100-ssp
-
- - reg: The memory base
- - dmas: Two dma phandles, one for rx, one for tx
- - dma-names: Must be "rx", "tx"
-
-
-Example for PXA3xx:
-
- ssp0: ssp@41000000 {
- compatible = "mrvl,pxa3xx-ssp";
- reg = <0x41000000 0x40>;
- ssp-id = <1>;
- interrupts = <24>;
- clock-names = "pxa27x-ssp.0";
- dmas = <&dma 13
- &dma 14>;
- dma-names = "rx", "tx";
- };
-
- ssp1: ssp@41700000 {
- compatible = "mrvl,pxa3xx-ssp";
- reg = <0x41700000 0x40>;
- ssp-id = <2>;
- interrupts = <16>;
- clock-names = "pxa27x-ssp.1";
- dmas = <&dma 15
- &dma 16>;
- dma-names = "rx", "tx";
- };
-
- ssp2: ssp@41900000 {
- compatibl3 = "mrvl,pxa3xx-ssp";
- reg = <0x41900000 0x40>;
- ssp-id = <3>;
- interrupts = <0>;
- clock-names = "pxa27x-ssp.2";
- dmas = <&dma 66
- &dma 67>;
- dma-names = "rx", "tx";
- };
-
- ssp3: ssp@41a00000 {
- compatible = "mrvl,pxa3xx-ssp";
- reg = <0x41a00000 0x40>;
- ssp-id = <4>;
- interrupts = <13>;
- clock-names = "pxa27x-ssp.3";
- dmas = <&dma 2
- &dma 3>;
- dma-names = "rx", "tx";
- };
-
diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt
deleted file mode 100644
index 3d55dd64b1be..000000000000
--- a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-Broadcom BCM2835 SPI0 controller
-
-The BCM2835 contains two forms of SPI master controller, one known simply as
-SPI0, and the other known as the "Universal SPI Master"; part of the
-auxiliary block. This binding applies to the SPI0 controller.
-
-Required properties:
-- compatible: Should be one of "brcm,bcm2835-spi" for BCM2835/2836/2837 or
- "brcm,bcm2711-spi" for BCM2711 or "brcm,bcm7211-spi" for BCM7211.
-- reg: Should contain register location and length.
-- interrupts: Should contain interrupt.
-- clocks: The clock feeding the SPI controller.
-
-Example:
-
-spi@20204000 {
- compatible = "brcm,bcm2835-spi";
- reg = <0x7e204000 0x1000>;
- interrupts = <2 22>;
- clocks = <&clk_spi>;
- #address-cells = <1>;
- #size-cells = <0>;
-};
diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml
new file mode 100644
index 000000000000..94da68792194
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/brcm,bcm2835-spi.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/brcm,bcm2835-spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM2835 SPI0 controller
+
+maintainers:
+ - Florian Fainelli <[email protected]>
+ - Kanak Shilledar <[email protected]>
+ - Stefan Wahren <[email protected]>
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+properties:
+ compatible:
+ enum:
+ - brcm,bcm2835-spi
+ - brcm,bcm2711-spi
+ - brcm,bcm7211-spi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi@20204000 {
+ compatible = "brcm,bcm2835-spi";
+ reg = <0x7e204000 0x1000>;
+ interrupts = <2 22>;
+ clocks = <&clk_spi>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml b/Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml
new file mode 100644
index 000000000000..d7fec4c3a801
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/ibm,spi-fsi.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/ibm,spi-fsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IBM FSI-attached SPI Controller
+
+maintainers:
+ - Eddie James <[email protected]>
+
+description:
+ A SPI controller found on IBM Power processors, accessed over FSI from a
+ service processor. This node will always be a child node of an ibm,fsi2spi
+ node.
+
+properties:
+ compatible:
+ enum:
+ - ibm,spi-fsi
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ fsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ spi@0 {
+ compatible = "ibm,spi-fsi";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ compatible = "atmel,at25";
+ reg = <0>;
+ size = <0x80000>;
+ address-width = <24>;
+ pagesize = <256>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml b/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml
index 5f4f6b5615d0..0a1bada8f800 100644
--- a/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml
+++ b/Documentation/devicetree/bindings/spi/marvell,mmp2-ssp.yaml
@@ -10,12 +10,17 @@ title: PXA2xx SSP SPI Controller
maintainers:
- Lubomir Rintel <[email protected]>
-allOf:
- - $ref: spi-controller.yaml#
-
properties:
compatible:
- const: marvell,mmp2-ssp
+ enum:
+ - marvell,mmp2-ssp
+ - mrvl,ce4100-ssp
+ - mvrl,pxa168-ssp
+ - mrvl,pxa25x-ssp
+ - mvrl,pxa25x-nssp
+ - mrvl,pxa27x-ssp
+ - mrvl,pxa3xx-ssp
+ - mrvl,pxa910-ssp
interrupts:
maxItems: 1
@@ -26,6 +31,16 @@ properties:
clocks:
maxItems: 1
+ dmas:
+ items:
+ - description: Receive DMA
+ - description: Transmit DMA
+
+ dma-names:
+ items:
+ - const: rx
+ - const: tx
+
ready-gpios:
description: |
GPIO used to signal a SPI master that the FIFO is filled and we're
@@ -41,6 +56,18 @@ required:
dependencies:
ready-gpios: [ spi-slave ]
+allOf:
+ - $ref: spi-controller.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: marvell,mmp2-ssp
+ then:
+ properties:
+ dmas: false
+ dma-names: false
+
unevaluatedProperties: false
examples:
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index 370c4d1572ed..5aaff3bee1b7 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -756,8 +756,15 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev)
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
int ret;
- clk_prepare(aq->pclk);
- clk_prepare(aq->qspick);
+ ret = clk_prepare(aq->pclk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare(aq->qspick);
+ if (ret) {
+ clk_unprepare(aq->pclk);
+ return ret;
+ }
ret = pm_runtime_force_resume(dev);
if (ret < 0)
diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c
index e358ac5b4509..3231f67ae265 100644
--- a/drivers/spi/spi-axi-spi-engine.c
+++ b/drivers/spi/spi-axi-spi-engine.c
@@ -46,6 +46,7 @@
#define SPI_ENGINE_INST_ASSERT 0x1
#define SPI_ENGINE_INST_WRITE 0x2
#define SPI_ENGINE_INST_MISC 0x3
+#define SPI_ENGINE_INST_CS_INV 0x4
#define SPI_ENGINE_CMD_REG_CLK_DIV 0x0
#define SPI_ENGINE_CMD_REG_CONFIG 0x1
@@ -73,6 +74,8 @@
SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SLEEP, (delay))
#define SPI_ENGINE_CMD_SYNC(id) \
SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SYNC, (id))
+#define SPI_ENGINE_CMD_CS_INV(flags) \
+ SPI_ENGINE_CMD(SPI_ENGINE_INST_CS_INV, 0, (flags))
struct spi_engine_program {
unsigned int length;
@@ -111,6 +114,8 @@ struct spi_engine {
struct spi_engine_message_state msg_state;
struct completion msg_complete;
unsigned int int_enable;
+ /* shadows hardware CS inversion flag state */
+ u8 cs_inv;
};
static void spi_engine_program_add_cmd(struct spi_engine_program *p,
@@ -530,6 +535,29 @@ static int spi_engine_unoptimize_message(struct spi_message *msg)
return 0;
}
+static int spi_engine_setup(struct spi_device *device)
+{
+ struct spi_controller *host = device->controller;
+ struct spi_engine *spi_engine = spi_controller_get_devdata(host);
+
+ if (device->mode & SPI_CS_HIGH)
+ spi_engine->cs_inv |= BIT(spi_get_chipselect(device, 0));
+ else
+ spi_engine->cs_inv &= ~BIT(spi_get_chipselect(device, 0));
+
+ writel_relaxed(SPI_ENGINE_CMD_CS_INV(spi_engine->cs_inv),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+
+ /*
+ * In addition to setting the flags, we have to do a CS assert command
+ * to make the new setting actually take effect.
+ */
+ writel_relaxed(SPI_ENGINE_CMD_ASSERT(0, 0xff),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+
+ return 0;
+}
+
static int spi_engine_transfer_one_message(struct spi_controller *host,
struct spi_message *msg)
{
@@ -653,6 +681,12 @@ static int spi_engine_probe(struct platform_device *pdev)
host->unoptimize_message = spi_engine_unoptimize_message;
host->num_chipselect = 8;
+ /* Some features depend of the IP core version. */
+ if (ADI_AXI_PCORE_VER_MINOR(version) >= 2) {
+ host->mode_bits |= SPI_CS_HIGH;
+ host->setup = spi_engine_setup;
+ }
+
if (host->max_speed_hz == 0)
return dev_err_probe(&pdev->dev, -EINVAL, "spi_clk rate is 0");
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f4006c82f867..cf0cb52946d2 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1666,10 +1666,6 @@ static int spi_imx_setup(struct spi_device *spi)
return 0;
}
-static void spi_imx_cleanup(struct spi_device *spi)
-{
-}
-
static int
spi_imx_prepare_message(struct spi_controller *controller, struct spi_message *msg)
{
@@ -1766,7 +1762,6 @@ static int spi_imx_probe(struct platform_device *pdev)
controller->transfer_one = spi_imx_transfer_one;
controller->setup = spi_imx_setup;
- controller->cleanup = spi_imx_cleanup;
controller->prepare_message = spi_imx_prepare_message;
controller->unprepare_message = spi_imx_unprepare_message;
controller->target_abort = spi_imx_target_abort;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index f94420858c22..cc8bb7d5ba1a 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2219,11 +2219,8 @@ static int spi_start_queue(struct spi_controller *ctlr)
static int spi_stop_queue(struct spi_controller *ctlr)
{
+ unsigned int limit = 500;
unsigned long flags;
- unsigned limit = 500;
- int ret = 0;
-
- spin_lock_irqsave(&ctlr->queue_lock, flags);
/*
* This is a bit lame, but is optimized for the common execution path.
@@ -2231,20 +2228,18 @@ static int spi_stop_queue(struct spi_controller *ctlr)
* execution path (pump_messages) would be required to call wake_up or
* friends on every SPI message. Do this instead.
*/
- while ((!list_empty(&ctlr->queue) || ctlr->busy) && limit--) {
+ do {
+ spin_lock_irqsave(&ctlr->queue_lock, flags);
+ if (list_empty(&ctlr->queue) && !ctlr->busy) {
+ ctlr->running = false;
+ spin_unlock_irqrestore(&ctlr->queue_lock, flags);
+ return 0;
+ }
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
usleep_range(10000, 11000);
- spin_lock_irqsave(&ctlr->queue_lock, flags);
- }
-
- if (!list_empty(&ctlr->queue) || ctlr->busy)
- ret = -EBUSY;
- else
- ctlr->running = false;
+ } while (--limit);
- spin_unlock_irqrestore(&ctlr->queue_lock, flags);
-
- return ret;
+ return -EBUSY;
}
static int spi_destroy_queue(struct spi_controller *ctlr)
@@ -2729,7 +2724,7 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
return -ENODEV;
if (ctlr) {
- if (ACPI_HANDLE(ctlr->dev.parent) != parent_handle)
+ if (!device_match_acpi_handle(ctlr->dev.parent, parent_handle))
return -ENODEV;
} else {
struct acpi_device *adev;
@@ -2828,7 +2823,7 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
if (!lookup.max_speed_hz &&
ACPI_SUCCESS(acpi_get_parent(adev->handle, &parent_handle)) &&
- ACPI_HANDLE(lookup.ctlr->dev.parent) == parent_handle) {
+ device_match_acpi_handle(lookup.ctlr->dev.parent, parent_handle)) {
/* Apple does not use _CRS but nested devices for SPI slaves */
acpi_spi_parse_apple_properties(adev, &lookup);
}