aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2024-05-02 12:54:41 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2024-05-02 12:54:41 +1000
commit624b330936c386aa276035077e9b901474b2856a (patch)
tree4459073e974755875df9167b09762540bfe518b3
parentf9e6c05f191c2be4fc93939117766f50c642ef93 (diff)
parentd37fd46e9b72d79c9f4e4c37ff672b76e563d557 (diff)
downloadlinux-next-history-624b330936c386aa276035077e9b901474b2856a.tar.gz
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
Notice: this object is not reachable from any branch.
Notice: this object is not reachable from any branch.
-rw-r--r--Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml8
-rw-r--r--Documentation/devicetree/bindings/spi/marvell,armada-3700-spi.yaml55
-rw-r--r--Documentation/devicetree/bindings/spi/renesas,sh-msiof.yaml1
-rw-r--r--Documentation/devicetree/bindings/spi/spi-armada-3700.txt25
-rw-r--r--Documentation/spi/pxa2xx.rst5
-rw-r--r--Documentation/spi/spi-summary.rst5
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/arm/mach-pxa/devices.c18
-rw-r--r--arch/arm/mach-pxa/spitz.c14
-rw-r--r--drivers/gpio/Kconfig9
-rw-r--r--drivers/gpio/gpiolib-swnode.c44
-rw-r--r--drivers/soc/pxa/ssp.c2
-rw-r--r--drivers/spi/Kconfig5
-rw-r--r--drivers/spi/spi-altera-platform.c1
-rw-r--r--drivers/spi/spi-amd.c112
-rw-r--r--drivers/spi/spi-atmel.c8
-rw-r--r--drivers/spi/spi-au1550.c29
-rw-r--r--drivers/spi/spi-cadence-quadspi.c109
-rw-r--r--drivers/spi/spi-cadence-xspi.c8
-rw-r--r--drivers/spi/spi-coldfire-qspi.c1
-rw-r--r--drivers/spi/spi-cs42l43.c127
-rw-r--r--drivers/spi/spi-fsl-cpm.c14
-rw-r--r--drivers/spi/spi-fsl-cpm.h5
-rw-r--r--drivers/spi/spi-fsl-dspi.c1
-rw-r--r--drivers/spi/spi-fsl-spi.c7
-rw-r--r--drivers/spi/spi-loopback-test.c1
-rw-r--r--drivers/spi/spi-mt65xx.c32
-rw-r--r--drivers/spi/spi-mt7621.c95
-rw-r--r--drivers/spi/spi-mux.c2
-rw-r--r--drivers/spi/spi-oc-tiny.c2
-rw-r--r--drivers/spi/spi-omap2-mcspi.c95
-rw-r--r--drivers/spi/spi-pxa2xx.c131
-rw-r--r--drivers/spi/spi-rspi.c12
-rw-r--r--drivers/spi/spi-s3c64xx.c6
-rw-r--r--drivers/spi/spi.c104
-rw-r--r--include/linux/gpio/property.h4
-rw-r--r--include/linux/platform_data/spi-omap2-mcspi.h3
-rw-r--r--include/linux/pxa2xx_ssp.h2
-rw-r--r--include/linux/spi/pxa2xx_spi.h10
-rw-r--r--include/linux/spi/rspi.h18
-rw-r--r--include/linux/spi/spi.h12
-rw-r--r--include/linux/spi/xilinx_spi.h14
42 files changed, 741 insertions, 417 deletions
diff --git a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml
index cca81f89e252d5..d48ecd6cd5ad83 100644
--- a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml
+++ b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml
@@ -68,12 +68,13 @@ properties:
- items:
- enum:
- amd,pensando-elba-qspi
- - ti,k2g-qspi
- - ti,am654-ospi
- intel,lgm-qspi
- - xlnx,versal-ospi-1.0
- intel,socfpga-qspi
+ - mobileye,eyeq5-ospi
- starfive,jh7110-qspi
+ - ti,am654-ospi
+ - ti,k2g-qspi
+ - xlnx,versal-ospi-1.0
- const: cdns,qspi-nor
- const: cdns,qspi-nor
@@ -145,7 +146,6 @@ required:
- reg
- interrupts
- clocks
- - cdns,fifo-depth
- cdns,fifo-width
- cdns,trigger-address
- '#address-cells'
diff --git a/Documentation/devicetree/bindings/spi/marvell,armada-3700-spi.yaml b/Documentation/devicetree/bindings/spi/marvell,armada-3700-spi.yaml
new file mode 100644
index 00000000000000..61caa1d86188af
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/marvell,armada-3700-spi.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/marvell,armada-3700-spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell Armada 3700 SPI Controller
+
+description:
+ The SPI controller on Marvell Armada 3700 SoC.
+
+maintainers:
+ - Kousik Sanagavarapu <five231003@gmail.com>
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+properties:
+ compatible:
+ const: marvell,armada-3700-spi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ num-cs:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ spi0: spi@10600 {
+ compatible = "marvell,armada-3700-spi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x10600 0x5d>;
+ clocks = <&nb_perih_clk 7>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <4>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/spi/renesas,sh-msiof.yaml b/Documentation/devicetree/bindings/spi/renesas,sh-msiof.yaml
index 00acbbb0f65dcf..49649fc3f95af9 100644
--- a/Documentation/devicetree/bindings/spi/renesas,sh-msiof.yaml
+++ b/Documentation/devicetree/bindings/spi/renesas,sh-msiof.yaml
@@ -54,6 +54,7 @@ properties:
- renesas,msiof-r8a779a0 # R-Car V3U
- renesas,msiof-r8a779f0 # R-Car S4-8
- renesas,msiof-r8a779g0 # R-Car V4H
+ - renesas,msiof-r8a779h0 # R-Car V4M
- const: renesas,rcar-gen4-msiof # generic R-Car Gen4
# compatible device
- items:
diff --git a/Documentation/devicetree/bindings/spi/spi-armada-3700.txt b/Documentation/devicetree/bindings/spi/spi-armada-3700.txt
deleted file mode 100644
index 1564aa8c02cdb1..00000000000000
--- a/Documentation/devicetree/bindings/spi/spi-armada-3700.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-* Marvell Armada 3700 SPI Controller
-
-Required Properties:
-
-- compatible: should be "marvell,armada-3700-spi"
-- reg: physical base address of the controller and length of memory mapped
- region.
-- interrupts: The interrupt number. The interrupt specifier format depends on
- the interrupt controller and of its driver.
-- clocks: Must contain the clock source, usually from the North Bridge clocks.
-- num-cs: The number of chip selects that is supported by this SPI Controller
-- #address-cells: should be 1.
-- #size-cells: should be 0.
-
-Example:
-
- spi0: spi@10600 {
- compatible = "marvell,armada-3700-spi";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x10600 0x5d>;
- clocks = <&nb_perih_clk 7>;
- interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
- num-cs = <4>;
- };
diff --git a/Documentation/spi/pxa2xx.rst b/Documentation/spi/pxa2xx.rst
index 19479b801826cf..33d2ad95901ee1 100644
--- a/Documentation/spi/pxa2xx.rst
+++ b/Documentation/spi/pxa2xx.rst
@@ -24,7 +24,7 @@ arch/.../mach-*/board-*.c as a "platform device". The host controller configurat
is passed to the driver via a table found in include/linux/spi/pxa2xx_spi.h::
struct pxa2xx_spi_controller {
- u16 num_chipselect;
+ u8 num_chipselect;
u8 enable_dma;
...
};
@@ -194,9 +194,6 @@ The following logic is used to determine the type of I/O to be used on
a per "spi_transfer" basis::
if spi_message.len > 65536 then
- if spi_message.is_dma_mapped or rx_dma_buf != 0 or tx_dma_buf != 0 then
- reject premapped transfers
-
print "rate limited" warning
use PIO transfers
diff --git a/Documentation/spi/spi-summary.rst b/Documentation/spi/spi-summary.rst
index 546de37d6caf10..7f8accfae6f98f 100644
--- a/Documentation/spi/spi-summary.rst
+++ b/Documentation/spi/spi-summary.rst
@@ -348,7 +348,6 @@ SPI protocol drivers somewhat resemble platform device drivers::
static struct spi_driver CHIP_driver = {
.driver = {
.name = "CHIP",
- .owner = THIS_MODULE,
.pm = &CHIP_pm_ops,
},
@@ -419,10 +418,6 @@ any more such messages.
to make extra copies unless the hardware requires it (e.g. working
around hardware errata that force the use of bounce buffering).
- If standard dma_map_single() handling of these buffers is inappropriate,
- you can use spi_message.is_dma_mapped to tell the controller driver
- that you've already provided the relevant DMA addresses.
-
- The basic I/O primitive is spi_async(). Async requests may be
issued in any context (irq handler, task, etc) and completion
is reported using a callback provided with the message.
diff --git a/MAINTAINERS b/MAINTAINERS
index 9c76adaa11bc98..5ca057409a7da5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22015,7 +22015,7 @@ F: Documentation/devicetree/bindings/sound/tas2552.txt
F: Documentation/devicetree/bindings/sound/tas2562.yaml
F: Documentation/devicetree/bindings/sound/tas2770.yaml
F: Documentation/devicetree/bindings/sound/tas27xx.yaml
-F: Documentation/devicetree/bindings/sound/ti,pcm1681.txt
+F: Documentation/devicetree/bindings/sound/ti,pcm1681.yaml
F: Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
F: Documentation/devicetree/bindings/sound/ti,tlv320*.yaml
F: Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 661b3fc4327596..1e4cd502340ece 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -7,7 +7,6 @@
#include <linux/clk-provider.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
-#include <linux/spi/pxa2xx_spi.h>
#include <linux/platform_data/i2c-pxa.h>
#include <linux/soc/pxa/cpu.h>
@@ -665,23 +664,6 @@ struct platform_device pxa27x_device_gpio = {
.resource = pxa_resource_gpio,
};
-/* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1.
- * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */
-void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_controller *info)
-{
- struct platform_device *pd;
-
- pd = platform_device_alloc("pxa2xx-spi", id);
- if (pd == NULL) {
- printk(KERN_ERR "pxa2xx-spi: failed to allocate device id %d\n",
- id);
- return;
- }
-
- pd->dev.platform_data = info;
- platform_device_add(pd);
-}
-
static struct resource pxa_dma_resource[] = {
[0] = {
.start = 0x40000000,
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index cc691b199429ca..318402ad685ead 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -585,6 +585,9 @@ static struct gpiod_lookup_table spitz_spi_gpio_table = {
static void __init spitz_spi_init(void)
{
+ struct platform_device *pd;
+ int id = 2;
+
if (machine_is_akita())
gpiod_add_lookup_table(&akita_lcdcon_gpio_table);
else
@@ -592,7 +595,16 @@ static void __init spitz_spi_init(void)
gpiod_add_lookup_table(&spitz_ads7846_gpio_table);
gpiod_add_lookup_table(&spitz_spi_gpio_table);
- pxa2xx_set_spi_info(2, &spitz_spi_info);
+
+ /* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1 */
+ pd = platform_device_alloc("pxa2xx-spi", id);
+ if (pd == NULL) {
+ pr_err("pxa2xx-spi: failed to allocate device id %d\n", id);
+ } else {
+ pd->dev.platform_data = &spitz_spi_info;
+ platform_device_add(pd);
+ }
+
spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices));
}
#else
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b50d0b47084977..00b5c007a2bb43 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -103,6 +103,15 @@ config GPIO_REGMAP
select REGMAP
tristate
+config GPIO_SWNODE_UNDEFINED
+ bool
+ help
+ This adds a special place holder for software nodes to contain an
+ undefined GPIO reference, this is primarily used by SPI to allow a
+ list of GPIO chip selects to mark a certain chip select as being
+ controlled the SPI device's internal chip select mechanism and not
+ a GPIO.
+
# put drivers in the right section, in alphabetical order
# This symbol is selected by both I2C and SPI expanders
diff --git a/drivers/gpio/gpiolib-swnode.c b/drivers/gpio/gpiolib-swnode.c
index fa52bdb1a29a34..cec1ab878af866 100644
--- a/drivers/gpio/gpiolib-swnode.c
+++ b/drivers/gpio/gpiolib-swnode.c
@@ -4,8 +4,13 @@
*
* Copyright 2022 Google LLC
*/
+
+#define pr_fmt(fmt) "gpiolib: swnode: " fmt
+
#include <linux/err.h>
#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/property.h>
@@ -17,6 +22,8 @@
#include "gpiolib.h"
#include "gpiolib-swnode.h"
+#define GPIOLIB_SWNODE_UNDEFINED_NAME "swnode-gpio-undefined"
+
static void swnode_format_propname(const char *con_id, char *propname,
size_t max_size)
{
@@ -40,6 +47,14 @@ static struct gpio_device *swnode_get_gpio_device(struct fwnode_handle *fwnode)
if (!gdev_node || !gdev_node->name)
return ERR_PTR(-EINVAL);
+ /*
+ * Check for a special node that identifies undefined GPIOs, this is
+ * primarily used as a key for internal chip selects in SPI bindings.
+ */
+ if (IS_ENABLED(CONFIG_GPIO_SWNODE_UNDEFINED) &&
+ !strcmp(gdev_node->name, GPIOLIB_SWNODE_UNDEFINED_NAME))
+ return ERR_PTR(-ENOENT);
+
gdev = gpio_device_find_by_label(gdev_node->name);
return gdev ?: ERR_PTR(-EPROBE_DEFER);
}
@@ -121,3 +136,32 @@ int swnode_gpio_count(const struct fwnode_handle *fwnode, const char *con_id)
return count ?: -ENOENT;
}
+
+#if IS_ENABLED(CONFIG_GPIO_SWNODE_UNDEFINED)
+/*
+ * A special node that identifies undefined GPIOs, this is primarily used as
+ * a key for internal chip selects in SPI bindings.
+ */
+const struct software_node swnode_gpio_undefined = {
+ .name = GPIOLIB_SWNODE_UNDEFINED_NAME,
+};
+EXPORT_SYMBOL_NS_GPL(swnode_gpio_undefined, GPIO_SWNODE);
+
+static int __init swnode_gpio_init(void)
+{
+ int ret;
+
+ ret = software_node_register(&swnode_gpio_undefined);
+ if (ret < 0)
+ pr_err("failed to register swnode: %d\n", ret);
+
+ return ret;
+}
+subsys_initcall(swnode_gpio_init);
+
+static void __exit swnode_gpio_cleanup(void)
+{
+ software_node_unregister(&swnode_gpio_undefined);
+}
+__exitcall(swnode_gpio_cleanup);
+#endif
diff --git a/drivers/soc/pxa/ssp.c b/drivers/soc/pxa/ssp.c
index 7af04e8b816376..854d32e0455834 100644
--- a/drivers/soc/pxa/ssp.c
+++ b/drivers/soc/pxa/ssp.c
@@ -25,7 +25,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
-#include <linux/spi/pxa2xx_spi.h>
+#include <linux/pxa2xx_ssp.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index bc7021da2fe91c..17325e0b7bd5d8 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -246,7 +246,7 @@ config SPI_CADENCE
config SPI_CADENCE_QUADSPI
tristate "Cadence Quad SPI controller"
- depends on OF && (ARM || ARM64 || X86 || RISCV || COMPILE_TEST)
+ depends on OF && (ARM || ARM64 || X86 || RISCV || MIPS || COMPILE_TEST)
help
Enable support for the Cadence Quad SPI Flash controller.
@@ -284,6 +284,7 @@ config SPI_COLDFIRE_QSPI
config SPI_CS42L43
tristate "Cirrus Logic CS42L43 SPI controller"
depends on MFD_CS42L43 && PINCTRL_CS42L43
+ select GPIO_SWNODE_UNDEFINED
help
This enables support for the SPI controller inside the Cirrus Logic
CS42L43 audio codec.
@@ -817,7 +818,7 @@ config SPI_PPC4xx
config SPI_PXA2XX
tristate "PXA2xx SSP SPI master"
- depends on ARCH_PXA || ARCH_MMP || PCI || ACPI || COMPILE_TEST
+ depends on ARCH_PXA || ARCH_MMP || (X86 && (PCI || ACPI)) || COMPILE_TEST
select PXA_SSP if ARCH_PXA || ARCH_MMP
help
This enables using a PXA2xx or Sodaville SSP port as a SPI master
diff --git a/drivers/spi/spi-altera-platform.c b/drivers/spi/spi-altera-platform.c
index 72e7a0f217939f..585393802e9f9f 100644
--- a/drivers/spi/spi-altera-platform.c
+++ b/drivers/spi/spi-altera-platform.c
@@ -169,4 +169,3 @@ module_platform_driver(altera_spi_driver);
MODULE_DESCRIPTION("Altera SPI driver");
MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c
index 5d9b246b696340..2245ad54b03aa3 100644
--- a/drivers/spi/spi-amd.c
+++ b/drivers/spi/spi-amd.c
@@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <linux/iopoll.h>
+#include <linux/spi/spi-mem.h>
#define AMD_SPI_CTRL0_REG 0x00
#define AMD_SPI_EXEC_CMD BIT(16)
@@ -35,6 +36,7 @@
#define AMD_SPI_FIFO_SIZE 70
#define AMD_SPI_MEM_SIZE 200
+#define AMD_SPI_MAX_DATA 64
#define AMD_SPI_ENA_REG 0x20
#define AMD_SPI_ALT_SPD_SHIFT 20
@@ -358,6 +360,115 @@ fin_msg:
return message->status;
}
+static bool amd_spi_supports_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ /* bus width is number of IO lines used to transmit */
+ if (op->cmd.buswidth > 1 || op->addr.buswidth > 1 ||
+ op->data.buswidth > 1 || op->data.nbytes > AMD_SPI_MAX_DATA)
+ return false;
+
+ return spi_mem_default_supports_op(mem, op);
+}
+
+static int amd_spi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+{
+ op->data.nbytes = clamp_val(op->data.nbytes, 0, AMD_SPI_MAX_DATA);
+ return 0;
+}
+
+static void amd_spi_set_addr(struct amd_spi *amd_spi,
+ const struct spi_mem_op *op)
+{
+ u8 nbytes = op->addr.nbytes;
+ u64 addr_val = op->addr.val;
+ int base_addr, i;
+
+ base_addr = AMD_SPI_FIFO_BASE + nbytes;
+
+ for (i = 0; i < nbytes; i++) {
+ amd_spi_writereg8(amd_spi, base_addr - i - 1, addr_val &
+ GENMASK(7, 0));
+ addr_val >>= 8;
+ }
+}
+
+static void amd_spi_mem_data_out(struct amd_spi *amd_spi,
+ const struct spi_mem_op *op)
+{
+ int base_addr = AMD_SPI_FIFO_BASE + op->addr.nbytes;
+ u8 *buf = (u8 *)op->data.buf.out;
+ u32 nbytes = op->data.nbytes;
+ int i;
+
+ amd_spi_set_opcode(amd_spi, op->cmd.opcode);
+ amd_spi_set_addr(amd_spi, op);
+
+ for (i = 0; i < nbytes; i++)
+ amd_spi_writereg8(amd_spi, (base_addr + i), buf[i]);
+
+ amd_spi_set_tx_count(amd_spi, op->addr.nbytes + op->data.nbytes);
+ amd_spi_set_rx_count(amd_spi, 0);
+ amd_spi_clear_fifo_ptr(amd_spi);
+ amd_spi_execute_opcode(amd_spi);
+}
+
+static void amd_spi_mem_data_in(struct amd_spi *amd_spi,
+ const struct spi_mem_op *op)
+{
+ int offset = (op->addr.nbytes == 0) ? 0 : 1;
+ u8 *buf = (u8 *)op->data.buf.in;
+ u32 nbytes = op->data.nbytes;
+ int base_addr, i;
+
+ base_addr = AMD_SPI_FIFO_BASE + op->addr.nbytes + offset;
+
+ amd_spi_set_opcode(amd_spi, op->cmd.opcode);
+ amd_spi_set_addr(amd_spi, op);
+ amd_spi_set_tx_count(amd_spi, op->addr.nbytes);
+ amd_spi_set_rx_count(amd_spi, op->data.nbytes + 1);
+ amd_spi_clear_fifo_ptr(amd_spi);
+ amd_spi_execute_opcode(amd_spi);
+ amd_spi_busy_wait(amd_spi);
+
+ for (i = 0; i < nbytes; i++)
+ buf[i] = amd_spi_readreg8(amd_spi, base_addr + i);
+}
+
+static int amd_spi_exec_mem_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ struct amd_spi *amd_spi;
+ int ret;
+
+ amd_spi = spi_controller_get_devdata(mem->spi->controller);
+
+ ret = amd_set_spi_freq(amd_spi, mem->spi->max_speed_hz);
+ if (ret)
+ return ret;
+
+ switch (op->data.dir) {
+ case SPI_MEM_DATA_IN:
+ amd_spi_mem_data_in(amd_spi, op);
+ break;
+ case SPI_MEM_DATA_OUT:
+ fallthrough;
+ case SPI_MEM_NO_DATA:
+ amd_spi_mem_data_out(amd_spi, op);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+static const struct spi_controller_mem_ops amd_spi_mem_ops = {
+ .exec_op = amd_spi_exec_mem_op,
+ .adjust_op_size = amd_spi_adjust_op_size,
+ .supports_op = amd_spi_supports_op,
+};
+
static int amd_spi_host_transfer(struct spi_controller *host,
struct spi_message *msg)
{
@@ -409,6 +520,7 @@ static int amd_spi_probe(struct platform_device *pdev)
host->min_speed_hz = AMD_SPI_MIN_HZ;
host->setup = amd_spi_host_setup;
host->transfer_one_message = amd_spi_host_transfer;
+ host->mem_ops = &amd_spi_mem_ops;
host->max_transfer_size = amd_spi_max_transfer_size;
host->max_message_size = amd_spi_max_transfer_size;
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index bad34998454a80..b62f57390d8f0b 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -987,8 +987,6 @@ static void atmel_spi_pdc_next_xfer(struct spi_controller *host,
* For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
* - The buffer is either valid for CPU access, else NULL
* - If the buffer is valid, so is its DMA address
- *
- * This driver manages the dma address unless message->is_dma_mapped.
*/
static int
atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
@@ -1374,8 +1372,7 @@ static int atmel_spi_one_transfer(struct spi_controller *host,
* DMA map early, for performance (empties dcache ASAP) and
* better fault reporting.
*/
- if ((!host->cur_msg->is_dma_mapped)
- && as->use_pdc) {
+ if (as->use_pdc) {
if (atmel_spi_dma_map_xfer(as, xfer) < 0)
return -ENOMEM;
}
@@ -1454,8 +1451,7 @@ static int atmel_spi_one_transfer(struct spi_controller *host,
}
}
- if (!host->cur_msg->is_dma_mapped
- && as->use_pdc)
+ if (as->use_pdc)
atmel_spi_dma_unmap_xfer(host, xfer);
if (as->use_pdc)
diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c
index 825d2f1cdff8e4..16f200bb3d1743 100644
--- a/drivers/spi/spi-au1550.c
+++ b/drivers/spi/spi-au1550.c
@@ -314,11 +314,8 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
hw->tx = t->tx_buf;
hw->rx = t->rx_buf;
- dma_tx_addr = t->tx_dma;
- dma_rx_addr = t->rx_dma;
/*
- * check if buffers are already dma mapped, map them otherwise:
* - first map the TX buffer, so cache data gets written to memory
* - then map the RX buffer, so that cache entries (with
* soon-to-be-stale data) get removed
@@ -326,23 +323,17 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
* use temp rx buffer (preallocated or realloc to fit) for rx dma
*/
if (t->tx_buf) {
- if (t->tx_dma == 0) { /* if DMA_ADDR_INVALID, map it */
- dma_tx_addr = dma_map_single(hw->dev,
- (void *)t->tx_buf,
- t->len, DMA_TO_DEVICE);
- if (dma_mapping_error(hw->dev, dma_tx_addr))
- dev_err(hw->dev, "tx dma map error\n");
- }
+ dma_tx_addr = dma_map_single(hw->dev, (void *)t->tx_buf,
+ t->len, DMA_TO_DEVICE);
+ if (dma_mapping_error(hw->dev, dma_tx_addr))
+ dev_err(hw->dev, "tx dma map error\n");
}
if (t->rx_buf) {
- if (t->rx_dma == 0) { /* if DMA_ADDR_INVALID, map it */
- dma_rx_addr = dma_map_single(hw->dev,
- (void *)t->rx_buf,
- t->len, DMA_FROM_DEVICE);
- if (dma_mapping_error(hw->dev, dma_rx_addr))
- dev_err(hw->dev, "rx dma map error\n");
- }
+ dma_rx_addr = dma_map_single(hw->dev, (void *)t->rx_buf,
+ t->len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(hw->dev, dma_rx_addr))
+ dev_err(hw->dev, "rx dma map error\n");
} else {
if (t->len > hw->dma_rx_tmpbuf_size) {
int ret;
@@ -398,10 +389,10 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
DMA_FROM_DEVICE);
}
/* unmap buffers if mapped above */
- if (t->rx_buf && t->rx_dma == 0)
+ if (t->rx_buf)
dma_unmap_single(hw->dev, dma_rx_addr, t->len,
DMA_FROM_DEVICE);
- if (t->tx_buf && t->tx_dma == 0)
+ if (t->tx_buf)
dma_unmap_single(hw->dev, dma_tx_addr, t->len,
DMA_TO_DEVICE);
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index 350b3dab3a05d1..05ebb03d319fcb 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -42,6 +42,7 @@ static_assert(CQSPI_MAX_CHIPSELECT <= SPI_CS_CNT_MAX);
#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3)
#define CQSPI_SLOW_SRAM BIT(4)
#define CQSPI_NEEDS_APB_AHB_HAZARD_WAR BIT(5)
+#define CQSPI_RD_NO_IRQ BIT(6)
/* Capabilities */
#define CQSPI_SUPPORTS_OCTAL BIT(0)
@@ -102,6 +103,8 @@ struct cqspi_st {
bool apb_ahb_hazard;
bool is_jh7110; /* Flag for StarFive JH7110 SoC */
+
+ const struct cqspi_driver_platdata *ddata;
};
struct cqspi_driver_platdata {
@@ -117,6 +120,7 @@ struct cqspi_driver_platdata {
/* Operation timeout value */
#define CQSPI_TIMEOUT_MS 500
#define CQSPI_READ_TIMEOUT_MS 10
+#define CQSPI_BUSYWAIT_TIMEOUT_US 500
/* Runtime_pm autosuspend delay */
#define CQSPI_AUTOSUSPEND_TIMEOUT 2000
@@ -295,13 +299,27 @@ struct cqspi_driver_platdata {
#define CQSPI_REG_VERSAL_DMA_VAL 0x602
-static int cqspi_wait_for_bit(void __iomem *reg, const u32 mask, bool clr)
+static int cqspi_wait_for_bit(const struct cqspi_driver_platdata *ddata,
+ void __iomem *reg, const u32 mask, bool clr,
+ bool busywait)
{
+ u64 timeout_us = CQSPI_TIMEOUT_MS * USEC_PER_MSEC;
u32 val;
+ if (busywait) {
+ int ret = readl_relaxed_poll_timeout(reg, val,
+ (((clr ? ~val : val) & mask) == mask),
+ 0, CQSPI_BUSYWAIT_TIMEOUT_US);
+
+ if (ret != -ETIMEDOUT)
+ return ret;
+
+ timeout_us -= CQSPI_BUSYWAIT_TIMEOUT_US;
+ }
+
return readl_relaxed_poll_timeout(reg, val,
(((clr ? ~val : val) & mask) == mask),
- 10, CQSPI_TIMEOUT_MS * 1000);
+ 10, timeout_us);
}
static bool cqspi_is_idle(struct cqspi_st *cqspi)
@@ -334,11 +352,8 @@ static u32 cqspi_get_versal_dma_status(struct cqspi_st *cqspi)
static irqreturn_t cqspi_irq_handler(int this_irq, void *dev)
{
struct cqspi_st *cqspi = dev;
+ const struct cqspi_driver_platdata *ddata = cqspi->ddata;
unsigned int irq_status;
- struct device *device = &cqspi->pdev->dev;
- const struct cqspi_driver_platdata *ddata;
-
- ddata = of_device_get_match_data(device);
/* Read interrupt status */
irq_status = readl(cqspi->iobase + CQSPI_REG_IRQSTATUS);
@@ -434,8 +449,8 @@ static int cqspi_exec_flash_cmd(struct cqspi_st *cqspi, unsigned int reg)
writel(reg, reg_base + CQSPI_REG_CMDCTRL);
/* Polling for completion. */
- ret = cqspi_wait_for_bit(reg_base + CQSPI_REG_CMDCTRL,
- CQSPI_REG_CMDCTRL_INPROGRESS_MASK, 1);
+ ret = cqspi_wait_for_bit(cqspi->ddata, reg_base + CQSPI_REG_CMDCTRL,
+ CQSPI_REG_CMDCTRL_INPROGRESS_MASK, 1, true);
if (ret) {
dev_err(&cqspi->pdev->dev,
"Flash command execution timed out.\n");
@@ -492,8 +507,11 @@ static int cqspi_enable_dtr(struct cqspi_flash_pdata *f_pdata,
if (ret)
return ret;
} else {
- reg &= ~CQSPI_REG_CONFIG_DTR_PROTO;
- reg &= ~CQSPI_REG_CONFIG_DUAL_OPCODE;
+ unsigned int mask = CQSPI_REG_CONFIG_DTR_PROTO | CQSPI_REG_CONFIG_DUAL_OPCODE;
+ /* Shortcut if DTR is already disabled. */
+ if ((reg & mask) == 0)
+ return 0;
+ reg &= ~mask;
}
writel(reg, reg_base + CQSPI_REG_CONFIG);
@@ -700,6 +718,7 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
const size_t n_rx)
{
struct cqspi_st *cqspi = f_pdata->cqspi;
+ bool use_irq = !(cqspi->ddata && cqspi->ddata->quirks & CQSPI_RD_NO_IRQ);
struct device *dev = &cqspi->pdev->dev;
void __iomem *reg_base = cqspi->iobase;
void __iomem *ahb_base = cqspi->ahb_base;
@@ -723,17 +742,20 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
* all the read interrupts disabled for max performance.
*/
- if (!cqspi->slow_sram)
+ if (use_irq && cqspi->slow_sram)
+ writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
+ else if (use_irq)
writel(CQSPI_IRQ_MASK_RD, reg_base + CQSPI_REG_IRQMASK);
else
- writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
+ writel(0, reg_base + CQSPI_REG_IRQMASK);
reinit_completion(&cqspi->transfer_complete);
writel(CQSPI_REG_INDIRECTRD_START_MASK,
reg_base + CQSPI_REG_INDIRECTRD);
while (remaining > 0) {
- if (!wait_for_completion_timeout(&cqspi->transfer_complete,
+ if (use_irq &&
+ !wait_for_completion_timeout(&cqspi->transfer_complete,
msecs_to_jiffies(CQSPI_READ_TIMEOUT_MS)))
ret = -ETIMEDOUT;
@@ -775,7 +797,7 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
}
- if (remaining > 0) {
+ if (use_irq && remaining > 0) {
reinit_completion(&cqspi->transfer_complete);
if (cqspi->slow_sram)
writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
@@ -783,8 +805,8 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
}
/* Check indirect done status */
- ret = cqspi_wait_for_bit(reg_base + CQSPI_REG_INDIRECTRD,
- CQSPI_REG_INDIRECTRD_DONE_MASK, 0);
+ ret = cqspi_wait_for_bit(cqspi->ddata, reg_base + CQSPI_REG_INDIRECTRD,
+ CQSPI_REG_INDIRECTRD_DONE_MASK, 0, true);
if (ret) {
dev_err(dev, "Indirect read completion error (%i)\n", ret);
goto failrd;
@@ -1084,8 +1106,8 @@ static int cqspi_indirect_write_execute(struct cqspi_flash_pdata *f_pdata,
}
/* Check indirect done status */
- ret = cqspi_wait_for_bit(reg_base + CQSPI_REG_INDIRECTWR,
- CQSPI_REG_INDIRECTWR_DONE_MASK, 0);
+ ret = cqspi_wait_for_bit(cqspi->ddata, reg_base + CQSPI_REG_INDIRECTWR,
+ CQSPI_REG_INDIRECTWR_DONE_MASK, 0, false);
if (ret) {
dev_err(dev, "Indirect write completion error (%i)\n", ret);
goto failwr;
@@ -1358,16 +1380,13 @@ static ssize_t cqspi_read(struct cqspi_flash_pdata *f_pdata,
const struct spi_mem_op *op)
{
struct cqspi_st *cqspi = f_pdata->cqspi;
- struct device *dev = &cqspi->pdev->dev;
- const struct cqspi_driver_platdata *ddata;
+ const struct cqspi_driver_platdata *ddata = cqspi->ddata;
loff_t from = op->addr.val;
size_t len = op->data.nbytes;
u_char *buf = op->data.buf.in;
u64 dma_align = (u64)(uintptr_t)buf;
int ret;
- ddata = of_device_get_match_data(dev);
-
ret = cqspi_read_setup(f_pdata, op);
if (ret)
return ret;
@@ -1511,8 +1530,8 @@ static int cqspi_of_get_pdata(struct cqspi_st *cqspi)
cqspi->is_decoded_cs = of_property_read_bool(np, "cdns,is-decoded-cs");
if (of_property_read_u32(np, "cdns,fifo-depth", &cqspi->fifo_depth)) {
- dev_err(dev, "couldn't determine fifo-depth\n");
- return -ENXIO;
+ /* Zero signals FIFO depth should be runtime detected. */
+ cqspi->fifo_depth = 0;
}
if (of_property_read_u32(np, "cdns,fifo-width", &cqspi->fifo_width)) {
@@ -1542,8 +1561,6 @@ static void cqspi_controller_init(struct cqspi_st *cqspi)
{
u32 reg;
- cqspi_controller_enable(cqspi, 0);
-
/* Configure the remap address register, no remap */
writel(0, cqspi->iobase + CQSPI_REG_REMAP);
@@ -1577,8 +1594,29 @@ static void cqspi_controller_init(struct cqspi_st *cqspi)
reg |= CQSPI_REG_CONFIG_DMA_MASK;
writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
}
+}
- cqspi_controller_enable(cqspi, 1);
+static void cqspi_controller_detect_fifo_depth(struct cqspi_st *cqspi)
+{
+ struct device *dev = &cqspi->pdev->dev;
+ u32 reg, fifo_depth;
+
+ /*
+ * Bits N-1:0 are writable while bits 31:N are read as zero, with 2^N
+ * the FIFO depth.
+ */
+ writel(U32_MAX, cqspi->iobase + CQSPI_REG_SRAMPARTITION);
+ reg = readl(cqspi->iobase + CQSPI_REG_SRAMPARTITION);
+ fifo_depth = reg + 1;
+
+ /* FIFO depth of zero means no value from devicetree was provided. */
+ if (cqspi->fifo_depth == 0) {
+ cqspi->fifo_depth = fifo_depth;
+ dev_dbg(dev, "using FIFO depth of %u\n", fifo_depth);
+ } else if (fifo_depth != cqspi->fifo_depth) {
+ dev_warn(dev, "detected FIFO depth (%u) different from config (%u)\n",
+ fifo_depth, cqspi->fifo_depth);
+ }
}
static int cqspi_request_mmap_dma(struct cqspi_st *cqspi)
@@ -1731,6 +1769,7 @@ static int cqspi_probe(struct platform_device *pdev)
cqspi->pdev = pdev;
cqspi->host = host;
cqspi->is_jh7110 = false;
+ cqspi->ddata = ddata = of_device_get_match_data(dev);
platform_set_drvdata(pdev, cqspi);
/* Obtain configuration from OF. */
@@ -1822,7 +1861,6 @@ static int cqspi_probe(struct platform_device *pdev)
/* write completion is supported by default */
cqspi->wr_completion = true;
- ddata = of_device_get_match_data(dev);
if (ddata) {
if (ddata->quirks & CQSPI_NEEDS_WR_DELAY)
cqspi->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC,
@@ -1864,7 +1902,10 @@ static int cqspi_probe(struct platform_device *pdev)
}
cqspi_wait_idle(cqspi);
+ cqspi_controller_enable(cqspi, 0);
+ cqspi_controller_detect_fifo_depth(cqspi);
cqspi_controller_init(cqspi);
+ cqspi_controller_enable(cqspi, 1);
cqspi->current_cs = -1;
cqspi->sclk = 0;
@@ -1947,7 +1988,9 @@ static int cqspi_runtime_resume(struct device *dev)
clk_prepare_enable(cqspi->clk);
cqspi_wait_idle(cqspi);
+ cqspi_controller_enable(cqspi, 0);
cqspi_controller_init(cqspi);
+ cqspi_controller_enable(cqspi, 1);
cqspi->current_cs = -1;
cqspi->sclk = 0;
@@ -2012,6 +2055,12 @@ static const struct cqspi_driver_platdata pensando_cdns_qspi = {
.quirks = CQSPI_NEEDS_APB_AHB_HAZARD_WAR | CQSPI_DISABLE_DAC_MODE,
};
+static const struct cqspi_driver_platdata mobileye_eyeq5_ospi = {
+ .hwcaps_mask = CQSPI_SUPPORTS_OCTAL,
+ .quirks = CQSPI_DISABLE_DAC_MODE | CQSPI_NO_SUPPORT_WR_COMPLETION |
+ CQSPI_RD_NO_IRQ,
+};
+
static const struct of_device_id cqspi_dt_ids[] = {
{
.compatible = "cdns,qspi-nor",
@@ -2045,6 +2094,10 @@ static const struct of_device_id cqspi_dt_ids[] = {
.compatible = "amd,pensando-elba-qspi",
.data = &pensando_cdns_qspi,
},
+ {
+ .compatible = "mobileye,eyeq5-ospi",
+ .data = &mobileye_eyeq5_ospi,
+ },
{ /* end of table */ }
};
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c
index 8648b8eb080dc9..2209e9fc378fa9 100644
--- a/drivers/spi/spi-cadence-xspi.c
+++ b/drivers/spi/spi-cadence-xspi.c
@@ -486,20 +486,14 @@ static irqreturn_t cdns_xspi_irq_handler(int this_irq, void *dev)
static int cdns_xspi_of_get_plat_data(struct platform_device *pdev)
{
struct device_node *node_prop = pdev->dev.of_node;
- struct device_node *node_child;
unsigned int cs;
- for_each_child_of_node(node_prop, node_child) {
- if (!of_device_is_available(node_child))
- continue;
-
+ for_each_available_child_of_node_scoped(node_prop, node_child) {
if (of_property_read_u32(node_child, "reg", &cs)) {
dev_err(&pdev->dev, "Couldn't get memory chip select\n");
- of_node_put(node_child);
return -ENXIO;
} else if (cs >= CDNS_XSPI_MAX_BANKS) {
dev_err(&pdev->dev, "reg (cs) parameter value too large\n");
- of_node_put(node_child);
return -ENXIO;
}
}
diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c
index b341b6908df06d..e83cd0510f2029 100644
--- a/drivers/spi/spi-coldfire-qspi.c
+++ b/drivers/spi/spi-coldfire-qspi.c
@@ -500,7 +500,6 @@ static const struct dev_pm_ops mcfqspi_pm = {
static struct platform_driver mcfqspi_driver = {
.driver.name = DRIVER_NAME,
- .driver.owner = THIS_MODULE,
.driver.pm = &mcfqspi_pm,
.probe = mcfqspi_probe,
.remove_new = mcfqspi_remove,
diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c
index aabef9fc84bdfb..9d747ea6992640 100644
--- a/drivers/spi/spi-cs42l43.c
+++ b/drivers/spi/spi-cs42l43.c
@@ -5,10 +5,14 @@
// Copyright (C) 2022-2023 Cirrus Logic, Inc. and
// Cirrus Logic International Semiconductor Ltd.
+#include <linux/acpi.h>
+#include <linux/array_size.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/errno.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio/property.h>
#include <linux/mfd/cs42l43.h>
#include <linux/mfd/cs42l43-regs.h>
#include <linux/mod_devicetable.h>
@@ -16,6 +20,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/units.h>
@@ -39,6 +44,44 @@ static const unsigned int cs42l43_clock_divs[] = {
2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30
};
+static const struct software_node ampl = {
+ .name = "cs35l56-left",
+};
+
+static const struct software_node ampr = {
+ .name = "cs35l56-right",
+};
+
+static struct spi_board_info ampl_info = {
+ .modalias = "cs35l56",
+ .max_speed_hz = 20 * HZ_PER_MHZ,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ .swnode = &ampl,
+};
+
+static struct spi_board_info ampr_info = {
+ .modalias = "cs35l56",
+ .max_speed_hz = 20 * HZ_PER_MHZ,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ .swnode = &ampr,
+};
+
+static const struct software_node cs42l43_gpiochip_swnode = {
+ .name = "cs42l43-pinctrl",
+};
+
+static const struct software_node_ref_args cs42l43_cs_refs[] = {
+ SOFTWARE_NODE_REFERENCE(&cs42l43_gpiochip_swnode, 0, GPIO_ACTIVE_LOW),
+ SOFTWARE_NODE_REFERENCE(&swnode_gpio_undefined),
+};
+
+static const struct property_entry cs42l43_cs_props[] = {
+ PROPERTY_ENTRY_REF_ARRAY("cs-gpios", cs42l43_cs_refs),
+ {}
+};
+
static int cs42l43_spi_tx(struct regmap *regmap, const u8 *buf, unsigned int len)
{
const u8 *end = buf + len;
@@ -203,16 +246,59 @@ static size_t cs42l43_spi_max_length(struct spi_device *spi)
return CS42L43_SPI_MAX_LENGTH;
}
+static bool cs42l43_has_sidecar(struct fwnode_handle *fwnode)
+{
+ static const u32 func_smart_amp = 0x1;
+ struct fwnode_handle *child_fwnode, *ext_fwnode;
+ unsigned int val;
+ u32 function;
+ int ret;
+
+ fwnode_for_each_child_node(fwnode, child_fwnode) {
+ acpi_handle handle = ACPI_HANDLE_FWNODE(child_fwnode);
+
+ ret = acpi_get_local_address(handle, &function);
+ if (ret || function != func_smart_amp)
+ continue;
+
+ ext_fwnode = fwnode_get_named_child_node(child_fwnode,
+ "mipi-sdca-function-expansion-subproperties");
+ if (!ext_fwnode)
+ continue;
+
+ ret = fwnode_property_read_u32(ext_fwnode,
+ "01fa-sidecar-instances",
+ &val);
+
+ fwnode_handle_put(ext_fwnode);
+
+ if (ret)
+ continue;
+
+ fwnode_handle_put(child_fwnode);
+
+ return !!val;
+ }
+
+ return false;
+}
+
static void cs42l43_release_of_node(void *data)
{
fwnode_handle_put(data);
}
+static void cs42l43_release_sw_node(void *data)
+{
+ software_node_unregister(&cs42l43_gpiochip_swnode);
+}
+
static int cs42l43_spi_probe(struct platform_device *pdev)
{
struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent);
struct cs42l43_spi *priv;
struct fwnode_handle *fwnode = dev_fwnode(cs42l43->dev);
+ bool has_sidecar = cs42l43_has_sidecar(fwnode);
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -259,21 +345,45 @@ static int cs42l43_spi_probe(struct platform_device *pdev)
if (is_of_node(fwnode)) {
fwnode = fwnode_get_named_child_node(fwnode, "spi");
- ret = devm_add_action(priv->dev, cs42l43_release_of_node, fwnode);
- if (ret) {
- fwnode_handle_put(fwnode);
+ ret = devm_add_action_or_reset(priv->dev, cs42l43_release_of_node, fwnode);
+ if (ret)
return ret;
- }
}
- device_set_node(&priv->ctlr->dev, fwnode);
+ if (has_sidecar) {
+ ret = software_node_register(&cs42l43_gpiochip_swnode);
+ if (ret)
+ return dev_err_probe(priv->dev, ret,
+ "Failed to register gpio swnode\n");
+
+ ret = devm_add_action_or_reset(priv->dev, cs42l43_release_sw_node, NULL);
+ if (ret)
+ return ret;
+
+ ret = device_create_managed_software_node(&priv->ctlr->dev,
+ cs42l43_cs_props, NULL);
+ if (ret)
+ return dev_err_probe(priv->dev, ret, "Failed to add swnode\n");
+ } else {
+ device_set_node(&priv->ctlr->dev, fwnode);
+ }
ret = devm_spi_register_controller(priv->dev, priv->ctlr);
- if (ret) {
- dev_err(priv->dev, "Failed to register SPI controller: %d\n", ret);
+ if (ret)
+ return dev_err_probe(priv->dev, ret,
+ "Failed to register SPI controller\n");
+
+ if (has_sidecar) {
+ if (!spi_new_device(priv->ctlr, &ampl_info))
+ return dev_err_probe(priv->dev, -ENODEV,
+ "Failed to create left amp slave\n");
+
+ if (!spi_new_device(priv->ctlr, &ampr_info))
+ return dev_err_probe(priv->dev, -ENODEV,
+ "Failed to create right amp slave\n");
}
- return ret;
+ return 0;
}
static const struct platform_device_id cs42l43_spi_id_table[] = {
@@ -291,6 +401,7 @@ static struct platform_driver cs42l43_spi_driver = {
};
module_platform_driver(cs42l43_spi_driver);
+MODULE_IMPORT_NS(GPIO_SWNODE);
MODULE_DESCRIPTION("CS42L43 SPI Driver");
MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
MODULE_AUTHOR("Maciej Strozek <mstrozek@opensource.cirrus.com>");
diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c
index 47c7a5c6257ff8..e335132080bf95 100644
--- a/drivers/spi/spi-fsl-cpm.c
+++ b/drivers/spi/spi-fsl-cpm.c
@@ -98,19 +98,13 @@ static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
}
-int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
- struct spi_transfer *t, bool is_dma_mapped)
+int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t)
{
struct device *dev = mspi->dev;
struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
- if (is_dma_mapped) {
- mspi->map_tx_dma = 0;
- mspi->map_rx_dma = 0;
- } else {
- mspi->map_tx_dma = 1;
- mspi->map_rx_dma = 1;
- }
+ mspi->map_tx_dma = 1;
+ mspi->map_rx_dma = 1;
if (!t->tx_buf) {
mspi->tx_dma = mspi->dma_dummy_tx;
@@ -147,7 +141,7 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
return -ENOMEM;
}
} else if (t->tx_buf) {
- mspi->tx_dma = t->tx_dma;
+ mspi->tx_dma = 0;
}
if (mspi->map_rx_dma) {
diff --git a/drivers/spi/spi-fsl-cpm.h b/drivers/spi/spi-fsl-cpm.h
index 160f999708b691..e012abba055f48 100644
--- a/drivers/spi/spi-fsl-cpm.h
+++ b/drivers/spi/spi-fsl-cpm.h
@@ -20,7 +20,7 @@
#ifdef CONFIG_FSL_SOC
extern void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi);
extern int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
- struct spi_transfer *t, bool is_dma_mapped);
+ struct spi_transfer *t);
extern void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi);
extern void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events);
extern int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi);
@@ -28,8 +28,7 @@ extern void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi);
#else
static inline void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi) { }
static inline int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
- struct spi_transfer *t,
- bool is_dma_mapped) { return 0; }
+ struct spi_transfer *t) { return 0; }
static inline void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) { }
static inline void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) { }
static inline int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) { return 0; }
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 38defdcf9370a3..0a2730cd07c6a1 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1458,7 +1458,6 @@ static void dspi_shutdown(struct platform_device *pdev)
static struct platform_driver fsl_dspi_driver = {
.driver.name = DRIVER_NAME,
.driver.of_match_table = fsl_dspi_dt_ids,
- .driver.owner = THIS_MODULE,
.driver.pm = &dspi_pm,
.probe = dspi_probe,
.remove_new = dspi_remove,
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 97faf984801f95..997e07c0a24aa9 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -249,8 +249,7 @@ static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
return 0;
}
-static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
- bool is_dma_mapped)
+static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
{
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(spi->controller);
struct fsl_spi_reg __iomem *reg_base;
@@ -274,7 +273,7 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
reinit_completion(&mpc8xxx_spi->done);
if (mpc8xxx_spi->flags & SPI_CPM_MODE)
- ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
+ ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t);
else
ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
if (ret)
@@ -353,7 +352,7 @@ static int fsl_spi_transfer_one(struct spi_controller *controller,
if (status < 0)
return status;
if (t->len)
- status = fsl_spi_bufs(spi, t, !!t->tx_dma || !!t->rx_dma);
+ status = fsl_spi_bufs(spi, t);
if (status > 0)
return -EMSGSIZE;
diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c
index fee8893d2751c0..31a878d9458d95 100644
--- a/drivers/spi/spi-loopback-test.c
+++ b/drivers/spi/spi-loopback-test.c
@@ -396,7 +396,6 @@ MODULE_DEVICE_TABLE(of, spi_loopback_test_of_match);
static struct spi_driver spi_loopback_test_driver = {
.driver = {
.name = "spi-loopback-test",
- .owner = THIS_MODULE,
.of_match_table = spi_loopback_test_of_match,
},
.probe = spi_loopback_test_probe,
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index e4cb22fe007523..36c2f52cd6b846 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -748,7 +748,7 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
u32 cmd, reg_val, cnt, remainder, len;
struct spi_controller *host = dev_id;
struct mtk_spi *mdata = spi_controller_get_devdata(host);
- struct spi_transfer *trans = mdata->cur_transfer;
+ struct spi_transfer *xfer = mdata->cur_transfer;
reg_val = readl(mdata->base + SPI_STATUS0_REG);
if (reg_val & MTK_SPI_PAUSE_INT_STATUS)
@@ -762,42 +762,40 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
- if (!host->can_dma(host, NULL, trans)) {
- if (trans->rx_buf) {
+ if (!host->can_dma(host, NULL, xfer)) {
+ if (xfer->rx_buf) {
cnt = mdata->xfer_len / 4;
ioread32_rep(mdata->base + SPI_RX_DATA_REG,
- trans->rx_buf + mdata->num_xfered, cnt);
+ xfer->rx_buf + mdata->num_xfered, cnt);
remainder = mdata->xfer_len % 4;
if (remainder > 0) {
reg_val = readl(mdata->base + SPI_RX_DATA_REG);
- memcpy(trans->rx_buf +
- mdata->num_xfered +
- (cnt * 4),
+ memcpy(xfer->rx_buf + (cnt * 4) + mdata->num_xfered,
&reg_val,
remainder);
}
}
mdata->num_xfered += mdata->xfer_len;
- if (mdata->num_xfered == trans->len) {
+ if (mdata->num_xfered == xfer->len) {
spi_finalize_current_transfer(host);
return IRQ_HANDLED;
}
- len = trans->len - mdata->num_xfered;
+ len = xfer->len - mdata->num_xfered;
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
mtk_spi_setup_packet(host);
- if (trans->tx_buf) {
+ if (xfer->tx_buf) {
cnt = mdata->xfer_len / 4;
iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
- trans->tx_buf + mdata->num_xfered, cnt);
+ xfer->tx_buf + mdata->num_xfered, cnt);
remainder = mdata->xfer_len % 4;
if (remainder > 0) {
reg_val = 0;
memcpy(&reg_val,
- trans->tx_buf + (cnt * 4) + mdata->num_xfered,
+ xfer->tx_buf + (cnt * 4) + mdata->num_xfered,
remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
}
@@ -809,21 +807,21 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
}
if (mdata->tx_sgl)
- trans->tx_dma += mdata->xfer_len;
+ xfer->tx_dma += mdata->xfer_len;
if (mdata->rx_sgl)
- trans->rx_dma += mdata->xfer_len;
+ xfer->rx_dma += mdata->xfer_len;
if (mdata->tx_sgl && (mdata->tx_sgl_len == 0)) {
mdata->tx_sgl = sg_next(mdata->tx_sgl);
if (mdata->tx_sgl) {
- trans->tx_dma = sg_dma_address(mdata->tx_sgl);
+ xfer->tx_dma = sg_dma_address(mdata->tx_sgl);
mdata->tx_sgl_len = sg_dma_len(mdata->tx_sgl);
}
}
if (mdata->rx_sgl && (mdata->rx_sgl_len == 0)) {
mdata->rx_sgl = sg_next(mdata->rx_sgl);
if (mdata->rx_sgl) {
- trans->rx_dma = sg_dma_address(mdata->rx_sgl);
+ xfer->rx_dma = sg_dma_address(mdata->rx_sgl);
mdata->rx_sgl_len = sg_dma_len(mdata->rx_sgl);
}
}
@@ -841,7 +839,7 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
mtk_spi_update_mdata_len(host);
mtk_spi_setup_packet(host);
- mtk_spi_setup_dma_addr(host, trans);
+ mtk_spi_setup_dma_addr(host, xfer);
mtk_spi_enable_transfer(host);
return IRQ_HANDLED;
diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c
index 4e9053d03d5a66..3770b8e096a417 100644
--- a/drivers/spi/spi-mt7621.c
+++ b/drivers/spi/spi-mt7621.c
@@ -52,6 +52,8 @@
#define MT7621_CPOL BIT(4)
#define MT7621_LSB_FIRST BIT(3)
+#define MT7621_NATIVE_CS_COUNT 2
+
struct mt7621_spi {
struct spi_controller *host;
void __iomem *base;
@@ -75,10 +77,11 @@ static inline void mt7621_spi_write(struct mt7621_spi *rs, u32 reg, u32 val)
iowrite32(val, rs->base + reg);
}
-static void mt7621_spi_set_cs(struct spi_device *spi, int enable)
+static void mt7621_spi_set_native_cs(struct spi_device *spi, bool enable)
{
struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
int cs = spi_get_chipselect(spi, 0);
+ bool active = spi->mode & SPI_CS_HIGH ? enable : !enable;
u32 polar = 0;
u32 host;
@@ -94,7 +97,7 @@ static void mt7621_spi_set_cs(struct spi_device *spi, int enable)
rs->pending_write = 0;
- if (enable)
+ if (active)
polar = BIT(cs);
mt7621_spi_write(rs, MT7621_SPI_POLAR, polar);
}
@@ -154,6 +157,23 @@ static inline int mt7621_spi_wait_till_ready(struct mt7621_spi *rs)
return -ETIMEDOUT;
}
+static int mt7621_spi_prepare_message(struct spi_controller *host,
+ struct spi_message *m)
+{
+ struct mt7621_spi *rs = spi_controller_get_devdata(host);
+ struct spi_device *spi = m->spi;
+ unsigned int speed = spi->max_speed_hz;
+ struct spi_transfer *t = NULL;
+
+ mt7621_spi_wait_till_ready(rs);
+
+ list_for_each_entry(t, &m->transfers, transfer_list)
+ if (t->speed_hz < speed)
+ speed = t->speed_hz;
+
+ return mt7621_spi_prepare(spi, speed);
+}
+
static void mt7621_spi_read_half_duplex(struct mt7621_spi *rs,
int rx_len, u8 *buf)
{
@@ -243,59 +263,30 @@ static void mt7621_spi_write_half_duplex(struct mt7621_spi *rs,
}
rs->pending_write = len;
+ mt7621_spi_flush(rs);
}
-static int mt7621_spi_transfer_one_message(struct spi_controller *host,
- struct spi_message *m)
+static int mt7621_spi_transfer_one(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *t)
{
struct mt7621_spi *rs = spi_controller_get_devdata(host);
- struct spi_device *spi = m->spi;
- unsigned int speed = spi->max_speed_hz;
- struct spi_transfer *t = NULL;
- int status = 0;
-
- mt7621_spi_wait_till_ready(rs);
- list_for_each_entry(t, &m->transfers, transfer_list)
- if (t->speed_hz < speed)
- speed = t->speed_hz;
-
- if (mt7621_spi_prepare(spi, speed)) {
- status = -EIO;
- goto msg_done;
- }
-
- /* Assert CS */
- mt7621_spi_set_cs(spi, 1);
-
- m->actual_length = 0;
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if ((t->rx_buf) && (t->tx_buf)) {
- /*
- * This controller will shift some extra data out
- * of spi_opcode if (mosi_bit_cnt > 0) &&
- * (cmd_bit_cnt == 0). So the claimed full-duplex
- * support is broken since we have no way to read
- * the MISO value during that bit.
- */
- status = -EIO;
- goto msg_done;
- } else if (t->rx_buf) {
- mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf);
- } else if (t->tx_buf) {
- mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf);
- }
- m->actual_length += t->len;
+ if ((t->rx_buf) && (t->tx_buf)) {
+ /*
+ * This controller will shift some extra data out
+ * of spi_opcode if (mosi_bit_cnt > 0) &&
+ * (cmd_bit_cnt == 0). So the claimed full-duplex
+ * support is broken since we have no way to read
+ * the MISO value during that bit.
+ */
+ return -EIO;
+ } else if (t->rx_buf) {
+ mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf);
+ } else if (t->tx_buf) {
+ mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf);
}
- /* Flush data and deassert CS */
- mt7621_spi_flush(rs);
- mt7621_spi_set_cs(spi, 0);
-
-msg_done:
- m->status = status;
- spi_finalize_current_message(host);
-
return 0;
}
@@ -353,10 +344,14 @@ static int mt7621_spi_probe(struct platform_device *pdev)
host->mode_bits = SPI_LSB_FIRST;
host->flags = SPI_CONTROLLER_HALF_DUPLEX;
host->setup = mt7621_spi_setup;
- host->transfer_one_message = mt7621_spi_transfer_one_message;
+ host->prepare_message = mt7621_spi_prepare_message;
+ host->set_cs = mt7621_spi_set_native_cs;
+ host->transfer_one = mt7621_spi_transfer_one;
host->bits_per_word_mask = SPI_BPW_MASK(8);
host->dev.of_node = pdev->dev.of_node;
- host->num_chipselect = 2;
+ host->max_native_cs = MT7621_NATIVE_CS_COUNT;
+ host->num_chipselect = MT7621_NATIVE_CS_COUNT;
+ host->use_gpio_descriptors = true;
dev_set_drvdata(&pdev->dev, host);
diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c
index bd988f53753e21..5d72e3d59df837 100644
--- a/drivers/spi/spi-mux.c
+++ b/drivers/spi/spi-mux.c
@@ -68,6 +68,8 @@ static int spi_mux_select(struct spi_device *spi)
priv->current_cs = spi_get_chipselect(spi, 0);
+ spi_setup(priv->spi);
+
return 0;
}
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index 6ea38f5e7d64f5..7d8c5cd680d1d9 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -184,8 +184,6 @@ static irqreturn_t tiny_spi_irq(int irq, void *dev)
}
#ifdef CONFIG_OF
-#include <linux/of_gpio.h>
-
static int tiny_spi_of_probe(struct platform_device *pdev)
{
struct tiny_spi *hw = platform_get_drvdata(pdev);
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index ddf1c684bcc7d8..7e3083b835348a 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -131,6 +131,7 @@ struct omap2_mcspi {
unsigned int pin_dir:1;
size_t max_xfer_len;
u32 ref_clk_hz;
+ bool use_multi_mode;
};
struct omap2_mcspi_cs {
@@ -256,10 +257,15 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
l = mcspi_cached_chconf0(spi);
- if (enable)
+ /* Only enable chip select manually if single mode is used */
+ if (mcspi->use_multi_mode) {
l &= ~OMAP2_MCSPI_CHCONF_FORCE;
- else
- l |= OMAP2_MCSPI_CHCONF_FORCE;
+ } else {
+ if (enable)
+ l &= ~OMAP2_MCSPI_CHCONF_FORCE;
+ else
+ l |= OMAP2_MCSPI_CHCONF_FORCE;
+ }
mcspi_write_chconf0(spi, l);
@@ -283,7 +289,12 @@ static void omap2_mcspi_set_mode(struct spi_controller *ctlr)
l |= (OMAP2_MCSPI_MODULCTRL_MS);
} else {
l &= ~(OMAP2_MCSPI_MODULCTRL_MS);
- l |= OMAP2_MCSPI_MODULCTRL_SINGLE;
+
+ /* Enable single mode if needed */
+ if (mcspi->use_multi_mode)
+ l &= ~OMAP2_MCSPI_MODULCTRL_SINGLE;
+ else
+ l |= OMAP2_MCSPI_MODULCTRL_SINGLE;
}
mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, l);
@@ -1175,13 +1186,6 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
t->bits_per_word == spi->bits_per_word)
par_override = 0;
}
- if (cd && cd->cs_per_word) {
- chconf = mcspi->ctx.modulctrl;
- chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE;
- mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, chconf);
- mcspi->ctx.modulctrl =
- mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
- }
chconf = mcspi_cached_chconf0(spi);
chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
@@ -1240,14 +1244,6 @@ out:
status = omap2_mcspi_setup_transfer(spi, NULL);
}
- if (cd && cd->cs_per_word) {
- chconf = mcspi->ctx.modulctrl;
- chconf |= OMAP2_MCSPI_MODULCTRL_SINGLE;
- mcspi_write_reg(ctlr, OMAP2_MCSPI_MODULCTRL, chconf);
- mcspi->ctx.modulctrl =
- mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
- }
-
omap2_mcspi_set_enable(spi, 0);
if (spi_get_csgpiod(spi, 0))
@@ -1265,15 +1261,72 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr);
struct omap2_mcspi_regs *ctx = &mcspi->ctx;
struct omap2_mcspi_cs *cs;
+ struct spi_transfer *tr;
+ u8 bits_per_word;
+
+ /*
+ * The conditions are strict, it is mandatory to check each transfer of the list to see if
+ * multi-mode is applicable.
+ */
+ mcspi->use_multi_mode = true;
+ list_for_each_entry(tr, &msg->transfers, transfer_list) {
+ if (!tr->bits_per_word)
+ bits_per_word = msg->spi->bits_per_word;
+ else
+ bits_per_word = tr->bits_per_word;
- /* Only a single channel can have the FORCE bit enabled
+ /*
+ * Check if this transfer contains only one word;
+ * OR contains 1 to 4 words, with bits_per_word == 8 and no delay between each word
+ * OR contains 1 to 2 words, with bits_per_word == 16 and no delay between each word
+ *
+ * If one of the two last case is true, this also change the bits_per_word of this
+ * transfer to make it a bit faster.
+ * It's not an issue to change the bits_per_word here even if the multi-mode is not
+ * applicable for this message, the signal on the wire will be the same.
+ */
+ if (bits_per_word < 8 && tr->len == 1) {
+ /* multi-mode is applicable, only one word (1..7 bits) */
+ } else if (tr->word_delay.value == 0 && bits_per_word == 8 && tr->len <= 4) {
+ /* multi-mode is applicable, only one "bigger" word (8,16,24,32 bits) */
+ tr->bits_per_word = tr->len * bits_per_word;
+ } else if (tr->word_delay.value == 0 && bits_per_word == 16 && tr->len <= 2) {
+ /* multi-mode is applicable, only one "bigger" word (16,32 bits) */
+ tr->bits_per_word = tr->len * bits_per_word / 2;
+ } else if (bits_per_word >= 8 && tr->len == bits_per_word / 8) {
+ /* multi-mode is applicable, only one word (9..15,17..32 bits) */
+ } else {
+ /* multi-mode is not applicable: more than one word in the transfer */
+ mcspi->use_multi_mode = false;
+ }
+
+ /* Check if transfer asks to change the CS status after the transfer */
+ if (!tr->cs_change)
+ mcspi->use_multi_mode = false;
+
+ /*
+ * If at least one message is not compatible, switch back to single mode
+ *
+ * The bits_per_word of certain transfer can be different, but it will have no
+ * impact on the signal itself.
+ */
+ if (!mcspi->use_multi_mode)
+ break;
+ }
+
+ omap2_mcspi_set_mode(ctlr);
+
+ /* In single mode only a single channel can have the FORCE bit enabled
* in its chconf0 register.
* Scan all channels and disable them except the current one.
* A FORCE can remain from a last transfer having cs_change enabled
+ *
+ * In multi mode all FORCE bits must be disabled.
*/
list_for_each_entry(cs, &ctx->cs, node) {
- if (msg->spi->controller_state == cs)
+ if (msg->spi->controller_state == cs && !mcspi->use_multi_mode) {
continue;
+ }
if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE)) {
cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE;
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index f2a856f6a99e45..2f60b2fde8d505 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -19,7 +19,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
-#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
@@ -944,7 +943,6 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller,
struct spi_transfer *transfer)
{
struct driver_data *drv_data = spi_controller_get_devdata(controller);
- struct spi_message *message = controller->cur_msg;
struct chip_data *chip = spi_get_ctldata(spi);
u32 dma_thresh = chip->dma_threshold;
u32 dma_burst = chip->dma_burst_size;
@@ -959,16 +957,6 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller,
/* Check if we can DMA this transfer */
if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
-
- /* Reject already-mapped transfers; PIO won't always work */
- if (message->is_dma_mapped
- || transfer->rx_dma || transfer->tx_dma) {
- dev_err(&spi->dev,
- "Mapped transfer length of %u is greater than %d\n",
- transfer->len, MAX_DMA_LEN);
- return -EINVAL;
- }
-
/* Warn ... we force this to PIO mode */
dev_warn_ratelimited(&spi->dev,
"DMA disabled for transfer length %u greater than %d\n",
@@ -1209,6 +1197,13 @@ static int setup(struct spi_device *spi)
break;
}
+ if (drv_data->ssp_type == CE4100_SSP) {
+ if (spi_get_chipselect(spi, 0) > 4) {
+ dev_err(&spi->dev, "failed setup: cs number must not be > 4.\n");
+ return -EINVAL;
+ }
+ }
+
/* Only allocate on the first setup */
chip = spi_get_ctldata(spi);
if (!chip) {
@@ -1216,14 +1211,6 @@ static int setup(struct spi_device *spi)
if (!chip)
return -ENOMEM;
- if (drv_data->ssp_type == CE4100_SSP) {
- if (spi_get_chipselect(spi, 0) > 4) {
- dev_err(&spi->dev,
- "failed setup: cs number must not be > 4.\n");
- kfree(chip);
- return -EINVAL;
- }
- }
chip->enable_dma = drv_data->controller_info->enable_dma;
chip->timeout = TIMOUT_DFLT;
}
@@ -1326,19 +1313,51 @@ static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
return param == chan->device->dev;
}
+static int
+pxa2xx_spi_init_ssp(struct platform_device *pdev, struct ssp_device *ssp, enum pxa_ssp_type type)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ int status;
+ u64 uid;
+
+ ssp->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(ssp->mmio_base))
+ return PTR_ERR(ssp->mmio_base);
+
+ ssp->phys_base = res->start;
+
+ ssp->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(ssp->clk))
+ return PTR_ERR(ssp->clk);
+
+ ssp->irq = platform_get_irq(pdev, 0);
+ if (ssp->irq < 0)
+ return ssp->irq;
+
+ ssp->type = type;
+ ssp->dev = dev;
+
+ status = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
+ if (status)
+ ssp->port_id = -1;
+ else
+ ssp->port_id = uid;
+
+ return 0;
+}
+
static struct pxa2xx_spi_controller *
pxa2xx_spi_init_pdata(struct platform_device *pdev)
{
struct pxa2xx_spi_controller *pdata;
struct device *dev = &pdev->dev;
struct device *parent = dev->parent;
- struct ssp_device *ssp;
- struct resource *res;
enum pxa_ssp_type type = SSP_UNDEFINED;
+ struct ssp_device *ssp = NULL;
const void *match;
bool is_lpss_priv;
int status;
- u64 uid;
is_lpss_priv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpss_priv");
@@ -1353,6 +1372,12 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev)
return ERR_PTR(status);
type = (enum pxa_ssp_type)value;
+ } else {
+ ssp = pxa_ssp_request(pdev->id, pdev->name);
+ if (ssp) {
+ type = ssp->type;
+ pxa_ssp_free(ssp);
+ }
}
/* Validate the SSP type correctness */
@@ -1363,14 +1388,6 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev)
if (!pdata)
return ERR_PTR(-ENOMEM);
- ssp = &pdata->ssp;
-
- ssp->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
- if (IS_ERR(ssp->mmio_base))
- return ERR_CAST(ssp->mmio_base);
-
- ssp->phys_base = res->start;
-
/* Platforms with iDMA 64-bit */
if (is_lpss_priv) {
pdata->tx_param = parent;
@@ -1378,28 +1395,19 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev)
pdata->dma_filter = pxa2xx_spi_idma_filter;
}
- ssp->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(ssp->clk))
- return ERR_CAST(ssp->clk);
-
- ssp->irq = platform_get_irq(pdev, 0);
- if (ssp->irq < 0)
- return ERR_PTR(ssp->irq);
-
- ssp->type = type;
- ssp->dev = dev;
-
- status = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
- if (status)
- ssp->port_id = -1;
- else
- ssp->port_id = uid;
-
pdata->is_target = device_property_read_bool(dev, "spi-slave");
pdata->num_chipselect = 1;
pdata->enable_dma = true;
pdata->dma_burst_size = 1;
+ /* If SSP has been already enumerated, use it */
+ if (ssp)
+ return pdata;
+
+ status = pxa2xx_spi_init_ssp(pdev, &pdata->ssp, type);
+ if (status)
+ return ERR_PTR(status);
+
return pdata;
}
@@ -1446,20 +1454,16 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
platform_info = dev_get_platdata(dev);
if (!platform_info) {
platform_info = pxa2xx_spi_init_pdata(pdev);
- if (IS_ERR(platform_info)) {
- dev_err(&pdev->dev, "missing platform data\n");
- return PTR_ERR(platform_info);
- }
+ if (IS_ERR(platform_info))
+ return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
}
ssp = pxa_ssp_request(pdev->id, pdev->name);
if (!ssp)
ssp = &platform_info->ssp;
- if (!ssp->mmio_base) {
- dev_err(&pdev->dev, "failed to get SSP\n");
- return -ENODEV;
- }
+ if (!ssp->mmio_base)
+ return dev_err_probe(dev, -ENODEV, "failed to get SSP\n");
if (platform_info->is_target)
controller = devm_spi_alloc_target(dev, sizeof(*drv_data));
@@ -1467,8 +1471,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
controller = devm_spi_alloc_host(dev, sizeof(*drv_data));
if (!controller) {
- dev_err(&pdev->dev, "cannot alloc spi_controller\n");
- status = -ENOMEM;
+ status = dev_err_probe(dev, -ENOMEM, "cannot alloc spi_controller\n");
goto out_error_controller_alloc;
}
drv_data = spi_controller_get_devdata(controller);
@@ -1522,7 +1525,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev),
drv_data);
if (status < 0) {
- dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
+ dev_err_probe(dev, status, "cannot get IRQ %d\n", ssp->irq);
goto out_error_controller_alloc;
}
@@ -1638,7 +1641,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drv_data);
status = spi_register_controller(controller);
if (status) {
- dev_err(&pdev->dev, "problem registering SPI controller\n");
+ dev_err_probe(dev, status, "problem registering SPI controller\n");
goto out_error_pm_runtime_enabled;
}
@@ -1741,7 +1744,6 @@ static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend, pxa2xx_spi_runtime_resume, NULL)
};
-#ifdef CONFIG_ACPI
static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
{ "80860F0E", LPSS_BYT_SSP },
{ "8086228E", LPSS_BSW_SSP },
@@ -1752,9 +1754,8 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
{}
};
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
-#endif
-static const struct of_device_id pxa2xx_spi_of_match[] __maybe_unused = {
+static const struct of_device_id pxa2xx_spi_of_match[] = {
{ .compatible = "marvell,mmp2-ssp", .data = (void *)MMP2_SSP },
{}
};
@@ -1764,8 +1765,8 @@ static struct platform_driver driver = {
.driver = {
.name = "pxa2xx-spi",
.pm = pm_ptr(&pxa2xx_spi_pm_ops),
- .acpi_match_table = ACPI_PTR(pxa2xx_spi_acpi_match),
- .of_match_table = of_match_ptr(pxa2xx_spi_of_match),
+ .acpi_match_table = pxa2xx_spi_acpi_match,
+ .of_match_table = pxa2xx_spi_of_match,
},
.probe = pxa2xx_spi_probe,
.remove_new = pxa2xx_spi_remove,
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 8e81f1a8623f90..7f95d22fb1ac65 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -24,7 +24,6 @@
#include <linux/reset.h>
#include <linux/sh_dma.h>
#include <linux/spi/spi.h>
-#include <linux/spi/rspi.h>
#include <linux/spinlock.h>
#define RSPI_SPCR 0x00 /* Control Register */
@@ -1131,16 +1130,12 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
static int rspi_request_dma(struct device *dev, struct spi_controller *ctlr,
const struct resource *res)
{
- const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
unsigned int dma_tx_id, dma_rx_id;
if (dev->of_node) {
/* In the OF case we will get the slave IDs from the DT */
dma_tx_id = 0;
dma_rx_id = 0;
- } else if (rspi_pd && rspi_pd->dma_tx_id && rspi_pd->dma_rx_id) {
- dma_tx_id = rspi_pd->dma_tx_id;
- dma_rx_id = rspi_pd->dma_rx_id;
} else {
/* The driver assumes no error. */
return 0;
@@ -1290,7 +1285,6 @@ static int rspi_probe(struct platform_device *pdev)
struct spi_controller *ctlr;
struct rspi_data *rspi;
int ret;
- const struct rspi_plat_data *rspi_pd;
const struct spi_ops *ops;
unsigned long clksrc;
@@ -1305,11 +1299,7 @@ static int rspi_probe(struct platform_device *pdev)
goto error1;
} else {
ops = (struct spi_ops *)pdev->id_entry->driver_data;
- rspi_pd = dev_get_platdata(&pdev->dev);
- if (rspi_pd && rspi_pd->num_chipselect)
- ctlr->num_chipselect = rspi_pd->num_chipselect;
- else
- ctlr->num_chipselect = 2; /* default */
+ ctlr->num_chipselect = 2; /* default */
}
rspi = spi_controller_get_devdata(ctlr);
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index f726d86704287e..833c58c88e4086 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -950,7 +950,7 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_target_ctrldata(
struct spi_device *spi)
{
struct s3c64xx_spi_csinfo *cs;
- struct device_node *target_np, *data_np = NULL;
+ struct device_node *target_np;
u32 fb_delay = 0;
target_np = spi->dev.of_node;
@@ -963,7 +963,8 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_target_ctrldata(
if (!cs)
return ERR_PTR(-ENOMEM);
- data_np = of_get_child_by_name(target_np, "controller-data");
+ struct device_node *data_np __free(device_node) =
+ of_get_child_by_name(target_np, "controller-data");
if (!data_np) {
dev_info(&spi->dev, "feedback delay set to default (0)\n");
return cs;
@@ -971,7 +972,6 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_target_ctrldata(
of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay);
cs->fb_delay = fb_delay;
- of_node_put(data_np);
return cs;
}
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a2c467d9e92f59..a0b897a38b5d58 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -312,7 +312,7 @@ static const struct attribute_group *spi_master_groups[] = {
static void spi_statistics_add_transfer_stats(struct spi_statistics __percpu *pcpu_stats,
struct spi_transfer *xfer,
- struct spi_controller *ctlr)
+ struct spi_message *msg)
{
int l2len = min(fls(xfer->len), SPI_STATISTICS_HISTO_SIZE) - 1;
struct spi_statistics *stats;
@@ -328,11 +328,9 @@ static void spi_statistics_add_transfer_stats(struct spi_statistics __percpu *pc
u64_stats_inc(&stats->transfer_bytes_histo[l2len]);
u64_stats_add(&stats->bytes, xfer->len);
- if ((xfer->tx_buf) &&
- (xfer->tx_buf != ctlr->dummy_tx))
+ if (spi_valid_txbuf(msg, xfer))
u64_stats_add(&stats->bytes_tx, xfer->len);
- if ((xfer->rx_buf) &&
- (xfer->rx_buf != ctlr->dummy_rx))
+ if (spi_valid_rxbuf(msg, xfer))
u64_stats_add(&stats->bytes_rx, xfer->len);
u64_stats_update_end(&stats->syncp);
@@ -597,10 +595,16 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
static void spi_dev_set_name(struct spi_device *spi)
{
- struct acpi_device *adev = ACPI_COMPANION(&spi->dev);
+ struct device *dev = &spi->dev;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
- if (adev) {
- dev_set_name(&spi->dev, "spi-%s", acpi_dev_name(adev));
+ if (is_acpi_device_node(fwnode)) {
+ dev_set_name(dev, "spi-%s", acpi_dev_name(to_acpi_device_node(fwnode)));
+ return;
+ }
+
+ if (is_software_node(fwnode)) {
+ dev_set_name(dev, "spi-%pfwP", fwnode);
return;
}
@@ -822,14 +826,10 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr,
proxy->controller_data = chip->controller_data;
proxy->controller_state = NULL;
/*
- * spi->chip_select[i] gives the corresponding physical CS for logical CS i
- * logical CS number is represented by setting the ith bit in spi->cs_index_mask
- * So, for example, if spi->cs_index_mask = 0x01 then logical CS number is 0 and
- * spi->chip_select[0] will give the physical CS.
- * By default spi->chip_select[0] will hold the physical CS number so, set
- * spi->cs_index_mask as 0x01.
+ * By default spi->chip_select[0] will hold the physical CS number,
+ * so set bit 0 in spi->cs_index_mask.
*/
- proxy->cs_index_mask = 0x01;
+ proxy->cs_index_mask = BIT(0);
if (chip->swnode) {
status = device_add_software_node(&proxy->dev, chip->swnode);
@@ -1022,20 +1022,45 @@ static void spi_res_release(struct spi_controller *ctlr, struct spi_message *mes
}
/*-------------------------------------------------------------------------*/
+#define spi_for_each_valid_cs(spi, idx) \
+ for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) \
+ if (!(spi->cs_index_mask & BIT(idx))) {} else
+
static inline bool spi_is_last_cs(struct spi_device *spi)
{
u8 idx;
bool last = false;
- for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
- if (spi->cs_index_mask & BIT(idx)) {
- if (spi->controller->last_cs[idx] == spi_get_chipselect(spi, idx))
- last = true;
- }
+ spi_for_each_valid_cs(spi, idx) {
+ if (spi->controller->last_cs[idx] == spi_get_chipselect(spi, idx))
+ last = true;
}
return last;
}
+static void spi_toggle_csgpiod(struct spi_device *spi, u8 idx, bool enable, bool activate)
+{
+ /*
+ * Historically ACPI has no means of the GPIO polarity and
+ * thus the SPISerialBus() resource defines it on the per-chip
+ * basis. In order to avoid a chain of negations, the GPIO
+ * polarity is considered being Active High. Even for the cases
+ * when _DSD() is involved (in the updated versions of ACPI)
+ * the GPIO CS polarity must be defined Active High to avoid
+ * ambiguity. That's why we use enable, that takes SPI_CS_HIGH
+ * into account.
+ */
+ if (has_acpi_companion(&spi->dev))
+ gpiod_set_value_cansleep(spi_get_csgpiod(spi, idx), !enable);
+ else
+ /* Polarity handled by GPIO library */
+ gpiod_set_value_cansleep(spi_get_csgpiod(spi, idx), activate);
+
+ if (activate)
+ spi_delay_exec(&spi->cs_setup, NULL);
+ else
+ spi_delay_exec(&spi->cs_inactive, NULL);
+}
static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
{
@@ -1072,31 +1097,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
if (spi_is_csgpiod(spi)) {
if (!(spi->mode & SPI_NO_CS)) {
- /*
- * Historically ACPI has no means of the GPIO polarity and
- * thus the SPISerialBus() resource defines it on the per-chip
- * basis. In order to avoid a chain of negations, the GPIO
- * polarity is considered being Active High. Even for the cases
- * when _DSD() is involved (in the updated versions of ACPI)
- * the GPIO CS polarity must be defined Active High to avoid
- * ambiguity. That's why we use enable, that takes SPI_CS_HIGH
- * into account.
- */
- for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
- if ((spi->cs_index_mask & BIT(idx)) && spi_get_csgpiod(spi, idx)) {
- if (has_acpi_companion(&spi->dev))
- gpiod_set_value_cansleep(spi_get_csgpiod(spi, idx),
- !enable);
- else
- /* Polarity handled by GPIO library */
- gpiod_set_value_cansleep(spi_get_csgpiod(spi, idx),
- activate);
-
- if (activate)
- spi_delay_exec(&spi->cs_setup, NULL);
- else
- spi_delay_exec(&spi->cs_inactive, NULL);
- }
+ spi_for_each_valid_cs(spi, idx) {
+ if (spi_get_csgpiod(spi, idx))
+ spi_toggle_csgpiod(spi, idx, enable, activate);
}
}
/* Some SPI masters need both GPIO CS & slave_select */
@@ -1613,8 +1616,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
trace_spi_transfer_start(msg, xfer);
- spi_statistics_add_transfer_stats(statm, xfer, ctlr);
- spi_statistics_add_transfer_stats(stats, xfer, ctlr);
+ spi_statistics_add_transfer_stats(statm, xfer, msg);
+ spi_statistics_add_transfer_stats(stats, xfer, msg);
if (!ctlr->ptp_sts_supported) {
xfer->ptp_sts_word_pre = 0;
@@ -3709,9 +3712,6 @@ static int __spi_split_transfer_maxsize(struct spi_controller *ctlr,
* to the same values as *xferp, so tx_buf, rx_buf and len
* are all identical (as well as most others)
* so we just have to fix up len and the pointers.
- *
- * This also includes support for the depreciated
- * spi_message.is_dma_mapped interface.
*/
/*
@@ -3725,12 +3725,8 @@ static int __spi_split_transfer_maxsize(struct spi_controller *ctlr,
/* Update rx_buf, tx_buf and DMA */
if (xfers[i].rx_buf)
xfers[i].rx_buf += offset;
- if (xfers[i].rx_dma)
- xfers[i].rx_dma += offset;
if (xfers[i].tx_buf)
xfers[i].tx_buf += offset;
- if (xfers[i].tx_dma)
- xfers[i].tx_dma += offset;
/* Update length */
xfers[i].len = min(maxsize, xfers[i].len - offset);
diff --git a/include/linux/gpio/property.h b/include/linux/gpio/property.h
index 1a14e239221f7e..0d220930800276 100644
--- a/include/linux/gpio/property.h
+++ b/include/linux/gpio/property.h
@@ -4,7 +4,11 @@
#include <linux/property.h>
+struct software_node;
+
#define PROPERTY_ENTRY_GPIO(_name_, _chip_node_, _idx_, _flags_) \
PROPERTY_ENTRY_REF(_name_, _chip_node_, _idx_, _flags_)
+extern const struct software_node swnode_gpio_undefined;
+
#endif /* __LINUX_GPIO_PROPERTY_H */
diff --git a/include/linux/platform_data/spi-omap2-mcspi.h b/include/linux/platform_data/spi-omap2-mcspi.h
index 3b400b1919a9bd..9e3c15b4ac9136 100644
--- a/include/linux/platform_data/spi-omap2-mcspi.h
+++ b/include/linux/platform_data/spi-omap2-mcspi.h
@@ -16,9 +16,6 @@ struct omap2_mcspi_platform_config {
struct omap2_mcspi_device_config {
unsigned turbo_mode:1;
-
- /* toggle chip select after every word */
- unsigned cs_per_word:1;
};
#endif
diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h
index cd1973e6ac4b46..844a2743ca94cb 100644
--- a/include/linux/pxa2xx_ssp.h
+++ b/include/linux/pxa2xx_ssp.h
@@ -217,9 +217,9 @@ enum pxa_ssp_type {
PXA27x_SSP,
PXA3xx_SSP,
PXA168_SSP,
- MMP2_SSP,
PXA910_SSP,
CE4100_SSP,
+ MMP2_SSP,
MRFLD_SSP,
QUARK_X1000_SSP,
/* Keep LPSS types sorted with lpss_platforms[] */
diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h
index ca2cd4e30ead7d..e5a4a045fb6731 100644
--- a/include/linux/spi/pxa2xx_spi.h
+++ b/include/linux/spi/pxa2xx_spi.h
@@ -17,7 +17,7 @@ struct dma_chan;
* (resides in device.platform_data).
*/
struct pxa2xx_spi_controller {
- u16 num_chipselect;
+ u8 num_chipselect;
u8 enable_dma;
u8 dma_burst_size;
bool is_target;
@@ -45,12 +45,4 @@ struct pxa2xx_spi_chip {
u32 timeout;
};
-#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
-
-#include <linux/clk.h>
-
-extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_controller *info);
-
-#endif
-
#endif /* __LINUX_SPI_PXA2XX_SPI_H */
diff --git a/include/linux/spi/rspi.h b/include/linux/spi/rspi.h
deleted file mode 100644
index dbdfcc7a3db220..00000000000000
--- a/include/linux/spi/rspi.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Renesas SPI driver
- *
- * Copyright (C) 2012 Renesas Solutions Corp.
- */
-
-#ifndef __LINUX_SPI_RENESAS_SPI_H__
-#define __LINUX_SPI_RENESAS_SPI_H__
-
-struct rspi_plat_data {
- unsigned int dma_tx_id;
- unsigned int dma_rx_id;
-
- u16 num_chipselect;
-};
-
-#endif
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index c459809efee4fb..e8e1e798924f4c 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -453,6 +453,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* @last_cs_mode_high: was (mode & SPI_CS_HIGH) true on the last call to set_cs.
* @last_cs: the last chip_select that is recorded by set_cs, -1 on non chip
* selected
+ * @last_cs_index_mask: bit mask the last chip selects that were used
* @xfer_completion: used by core transfer_one_message()
* @busy: message pump is busy
* @running: message pump is running
@@ -955,8 +956,8 @@ struct spi_res {
* struct spi_transfer - a read/write buffer pair
* @tx_buf: data to be written (DMA-safe memory), or NULL
* @rx_buf: data to be read (DMA-safe memory), or NULL
- * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
- * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
+ * @tx_dma: DMA address of tx_buf, currently not for client use
+ * @rx_dma: DMA address of rx_buf, currently not for client use
* @tx_nbits: number of bits used for writing. If 0 the default
* (SPI_NBITS_SINGLE) is used.
* @rx_nbits: number of bits used for reading. If 0 the default
@@ -1066,8 +1067,7 @@ struct spi_transfer {
/*
* It's okay if tx_buf == rx_buf (right?).
* For MicroWire, one buffer must be NULL.
- * Buffers must work with dma_*map_single() calls, unless
- * spi_message.is_dma_mapped reports a pre-existing mapping.
+ * Buffers must work with dma_*map_single() calls.
*/
const void *tx_buf;
void *rx_buf;
@@ -1111,8 +1111,6 @@ struct spi_transfer {
* struct spi_message - one multi-segment SPI transaction
* @transfers: list of transfer segments in this transaction
* @spi: SPI device to which the transaction is queued
- * @is_dma_mapped: if true, the caller provided both DMA and CPU virtual
- * addresses for each transfer buffer
* @pre_optimized: peripheral driver pre-optimized the message
* @optimized: the message is in the optimized state
* @prepared: spi_prepare_message was called for the this message
@@ -1146,8 +1144,6 @@ struct spi_message {
struct spi_device *spi;
- unsigned is_dma_mapped:1;
-
/* spi_optimize_message() was called for this message */
bool pre_optimized;
/* __spi_optimize_message() was called for this message */
diff --git a/include/linux/spi/xilinx_spi.h b/include/linux/spi/xilinx_spi.h
index 3934ce789d877b..1b8d984668b682 100644
--- a/include/linux/spi/xilinx_spi.h
+++ b/include/linux/spi/xilinx_spi.h
@@ -2,19 +2,23 @@
#ifndef __LINUX_SPI_XILINX_SPI_H
#define __LINUX_SPI_XILINX_SPI_H
+#include <linux/types.h>
+
+struct spi_board_info;
+
/**
* struct xspi_platform_data - Platform data of the Xilinx SPI driver
- * @num_chipselect: Number of chip select by the IP.
- * @little_endian: If registers should be accessed little endian or not.
- * @bits_per_word: Number of bits per word.
* @devices: Devices to add when the driver is probed.
* @num_devices: Number of devices in the devices array.
+ * @num_chipselect: Number of chip select by the IP.
+ * @bits_per_word: Number of bits per word.
+ * @force_irq: If set, forces QSPI transaction requirements.
*/
struct xspi_platform_data {
- u16 num_chipselect;
- u8 bits_per_word;
struct spi_board_info *devices;
u8 num_devices;
+ u8 num_chipselect;
+ u8 bits_per_word;
bool force_irq;
};