Merge tag 'spi-v6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi updates from Mark Brown:
 "The highlight here is that David Lechner has added support for
  multi-lane SPI devices. Unlike the existing dual/quad SPI support this
  is for devices (typically ADCs/DACs) which support multiple
  independent data streams over multiple data lanes, instead of sending
  one data stream N times as fast they simultaneously transfer N
  different data streams.

  This is very similar to the case where multiple devices are grouped
  together but in this case it's a single device in a way that's visible
  to software.

  Otherwise there's been quite a bit of work on existing drivers, both
  cleanup and feature improvement, and a reasonable collection of new
  drivers.

   - Support for multi-lane SPI devices

   - Preparatory work for some memory mapped flash improvements that
     will happen in the MTD subsystem

   - Several conversions to fwnode APIs

   - A bunch of cleanup and hardening work on the ST drivers

   - Support for DMA mode on Renesas RZV2H and i.MX target mode

   - Support for ATCSPI200, AXIADO AX300, NXP XPI and Renesas RZ/N1"

* tag 'spi-v6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (108 commits)
  spi: tools: Add include folder to .gitignore
  spi: cadence-qspi: Add support for the Renesas RZ/N1 controller
  spi: cadence-qspi: Kill cqspi_jh7110_clk_init
  spi: dt-bindings: cdns,qspi-nor: Add Renesas RZ/N1D400 to the list
  spi: geni-qcom: Add target abort support
  spi: geni-qcom: Drop unused msg parameter from timeout handlers
  spi: geni-qcom: Fix abort sequence execution for serial engine errors
  spi: geni-qcom: Improve target mode allocation by using proper allocation functions
  spi: xilinx: use device property accessors.
  dt-bindings: spi: Add binding for Faraday FTSSP010
  spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE
  spi: dt-bindings: adi,axi-spi-engine: add multi-lane support
  spi: Documentation: add page on multi-lane support
  spi: add multi_lane_mode field to struct spi_transfer
  spi: support controllers with multiple data lanes
  spi: dt-bindings: add spi-{tx,rx}-lane-map properties
  spi: dt-bindings: change spi-{rx,tx}-bus-width to arrays
  spi: dw: Remove not-going-to-be-supported code for Baikal SoC
  spi: cadence-qspi: Use a default value for cdns,fifo-width
  spi: cadence-qspi: Make sure write protection is disabled
  ...
This commit is contained in:
Linus Torvalds
2026-02-11 09:43:43 -08:00
141 changed files with 5812 additions and 1211 deletions
@@ -34,8 +34,9 @@ properties:
spi-cpol: true
spi-rx-bus-width:
minimum: 0
maximum: 1
items:
minimum: 0
maximum: 1
dc-gpios:
maxItems: 1
@@ -37,7 +37,15 @@ properties:
maximum: 102040816
spi-rx-bus-width:
enum: [1, 2, 4]
maxItems: 2
# all lanes must have the same width
oneOf:
- contains:
const: 1
- contains:
const: 2
- contains:
const: 4
vdd-5v-supply: true
vdd-1v8-supply: true
@@ -88,6 +96,18 @@ oneOf:
unevaluatedProperties: false
allOf:
- if:
properties:
compatible:
enum:
- adi,ad4030-24
- adi,ad4032-24
then:
properties:
spi-rx-bus-width:
maxItems: 1
examples:
- |
#include <dt-bindings/gpio/gpio.h>
@@ -108,3 +128,23 @@ examples:
reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
};
};
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "adi,ad4630-24";
reg = <0>;
spi-max-frequency = <80000000>;
spi-rx-bus-width = <4>, <4>;
vdd-5v-supply = <&supply_5V>;
vdd-1v8-supply = <&supply_1_8V>;
vio-supply = <&supply_1_8V>;
ref-supply = <&supply_5V>;
cnv-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
};
};
@@ -38,8 +38,9 @@ properties:
spi-cpha: true
spi-rx-bus-width:
minimum: 1
maximum: 4
items:
minimum: 1
maximum: 4
avdd-supply:
description: Analog power supply.
@@ -70,6 +70,21 @@ required:
unevaluatedProperties: false
patternProperties:
"^.*@[0-9a-f]+":
type: object
properties:
spi-rx-bus-width:
maxItems: 8
items:
enum: [0, 1]
spi-tx-bus-width:
maxItems: 8
items:
enum: [0, 1]
examples:
- |
spi@44a00000 {
@@ -55,10 +55,12 @@ patternProperties:
maximum: 4
spi-rx-bus-width:
const: 1
items:
- const: 1
spi-tx-bus-width:
const: 1
items:
- const: 1
required:
- compatible
@@ -81,10 +81,12 @@ patternProperties:
maximum: 4
spi-rx-bus-width:
const: 1
items:
- const: 1
spi-tx-bus-width:
const: 1
items:
- const: 1
required:
- compatible
@@ -0,0 +1,87 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/andestech,ae350-spi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Andes ATCSPI200 SPI controller
maintainers:
- CL Wang <cl634@andestech.com>
properties:
compatible:
oneOf:
- items:
- enum:
- andestech,qilai-spi
- const: andestech,ae350-spi
- const: andestech,ae350-spi
reg:
maxItems: 1
clocks:
maxItems: 1
num-cs:
description: Number of chip selects supported
maxItems: 1
dmas:
items:
- description: Transmit FIFO DMA channel
- description: Receive FIFO DMA channel
dma-names:
items:
- const: tx
- const: rx
patternProperties:
"@[0-9a-f]+$":
type: object
additionalProperties: true
properties:
spi-rx-bus-width:
items:
- enum: [1, 4]
spi-tx-bus-width:
items:
- enum: [1, 4]
allOf:
- $ref: spi-controller.yaml#
required:
- compatible
- reg
- clocks
- dmas
- dma-names
unevaluatedProperties: false
examples:
- |
spi@f0b00000 {
compatible = "andestech,ae350-spi";
reg = <0xf0b00000 0x100>;
clocks = <&clk_spi>;
dmas = <&dma0 0>, <&dma0 1>;
dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
spi-cpol;
spi-cpha;
};
};
@@ -19,6 +19,7 @@ properties:
- const: atmel,at91rm9200-spi
- items:
- enum:
- microchip,lan9691-spi
- microchip,sam9x60-spi
- microchip,sam9x7-spi
- microchip,sama7d65-spi
@@ -0,0 +1,73 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/axiado,ax3000-spi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Axiado AX3000 SoC SPI controller
maintainers:
- Vladimir Moravcevic <vmoravcevic@axiado.com>
- Tzu-Hao Wei <twei@axiado.com>
- Swark Yang <syang@axiado.com>
- Prasad Bolisetty <pbolisetty@axiado.com>
allOf:
- $ref: spi-controller.yaml#
properties:
compatible:
enum:
- axiado,ax3000-spi
reg:
maxItems: 1
interrupts:
maxItems: 1
clock-names:
items:
- const: ref
- const: pclk
clocks:
maxItems: 2
num-cs:
description: |
Number of chip selects used.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1
maximum: 4
default: 4
required:
- compatible
- reg
- interrupts
- clock-names
- clocks
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
spi@80510000 {
compatible = "axiado,ax3000-spi";
reg = <0x00 0x80510000 0x00 0x1000>;
clock-names = "ref", "pclk";
clocks = <&spi_clk>, <&apb_pclk>;
interrupt-parent = <&gic500>;
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
num-cs = <4>;
};
};
...
@@ -61,6 +61,20 @@ allOf:
cdns,fifo-depth:
enum: [ 128, 256 ]
default: 128
- if:
properties:
compatible:
contains:
const: renesas,rzn1-qspi
then:
properties:
cdns,trigger-address: false
cdns,fifo-depth: false
cdns,fifo-width: false
else:
required:
- cdns,trigger-address
- cdns,fifo-depth
properties:
compatible:
@@ -80,6 +94,9 @@ properties:
# controllers are meant to be used with flashes of all kinds,
# ie. also NAND flashes, not only NOR flashes.
- const: cdns,qspi-nor
- items:
- const: renesas,r9a06g032-qspi
- const: renesas,rzn1-qspi
- const: cdns,qspi-nor
deprecated: true
@@ -163,8 +180,6 @@ required:
- reg
- interrupts
- clocks
- cdns,fifo-width
- cdns,trigger-address
- '#address-cells'
- '#size-cells'
@@ -172,7 +187,7 @@ unevaluatedProperties: false
examples:
- |
qspi: spi@ff705000 {
spi@ff705000 {
compatible = "intel,socfpga-qspi", "cdns,qspi-nor";
#address-cells = <1>;
#size-cells = <0>;
@@ -0,0 +1,43 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/faraday,ftssp010.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Faraday FTSSP010 SPI Controller
maintainers:
- Linus Walleij <linusw@kernel.org>
properties:
compatible:
const: faraday,ftssp010
interrupts:
maxItems: 1
reg:
maxItems: 1
cs-gpios: true
required:
- compatible
- interrupts
- reg
allOf:
- $ref: spi-controller.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi@4a000000 {
compatible = "faraday,ftssp010";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x4a000000 0x1000>;
interrupts = <0>;
};
@@ -54,10 +54,12 @@ patternProperties:
properties:
spi-rx-bus-width:
enum: [1, 2, 4]
items:
- enum: [1, 2, 4]
spi-tx-bus-width:
enum: [1, 2, 4]
items:
- enum: [1, 2, 4]
required:
- compatible
@@ -0,0 +1,92 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/nxp,imx94-xspi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP External Serial Peripheral Interface (xSPI)
maintainers:
- Haibo Chen <haibo.chen@nxp.com>
- Han Xu <han.xu@nxp.com>
properties:
compatible:
oneOf:
- enum:
- nxp,imx94-xspi
- items:
- enum:
- nxp,imx952-xspi
- const: nxp,imx94-xspi
reg:
items:
- description: registers address space
- description: memory mapped address space
reg-names:
items:
- const: base
- const: mmap
interrupts:
items:
- description: interrupt for EENV0
- description: interrupt for EENV1
- description: interrupt for EENV2
- description: interrupt for EENV3
- description: interrupt for EENV4
clocks:
items:
- description: SPI serial clock
clock-names:
items:
- const: per
required:
- compatible
- reg
- reg-names
- interrupts
- clocks
- clock-names
allOf:
- $ref: spi-controller.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
spi@42b90000 {
compatible = "nxp,imx94-xspi";
reg = <0x0 0x42b90000 0x0 0x50000>, <0x0 0x28000000 0x0 0x08000000>;
reg-names = "base", "mmap";
interrupts = <GIC_SPI 390 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&scmi_1>;
clock-names = "per";
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <200000000>;
spi-rx-bus-width = <8>;
spi-tx-bus-width = <8>;
};
};
};
@@ -20,6 +20,12 @@ properties:
clocks:
maxItems: 1
dmas:
maxItems: 1
dma-names:
const: rx-tx
allOf:
- $ref: spi-controller.yaml#
@@ -38,6 +44,8 @@ examples:
compatible = "nxp,lpc3220-spi";
reg = <0x20088000 0x1000>;
clocks = <&clk LPC32XX_CLK_SPI1>;
dmas = <&dmamux 11 1 0>;
dma-names = "rx-tx";
#address-cells = <1>;
#size-cells = <0>;
};
@@ -57,6 +57,14 @@ properties:
- const: presetn
- const: tresetn
dmas:
maxItems: 2
dma-names:
items:
- const: rx
- const: tx
power-domains:
maxItems: 1
@@ -64,9 +64,23 @@ properties:
description:
Bus width to the SPI bus used for read transfers.
If 0 is provided, then no RX will be possible on this device.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 4, 8]
default: 1
Some SPI peripherals and controllers may have multiple data lanes for
receiving two or more words at the same time. If this is the case, each
index in the array represents the lane on both the SPI peripheral and
controller. Additional mapping properties may be needed if a lane is
skipped on either side.
$ref: /schemas/types.yaml#/definitions/uint32-array
items:
enum: [0, 1, 2, 4, 8]
default: [1]
spi-rx-lane-map:
description: Mapping of peripheral SDO lanes to controller SDI lanes.
Each index in the array represents a peripheral SDO lane, and the value
at that index represents the corresponding controller SDI lane.
$ref: /schemas/types.yaml#/definitions/uint32-array
default: [0, 1, 2, 3, 4, 5, 6, 7]
spi-rx-delay-us:
description:
@@ -81,9 +95,23 @@ properties:
description:
Bus width to the SPI bus used for write transfers.
If 0 is provided, then no TX will be possible on this device.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 4, 8]
default: 1
Some SPI peripherals and controllers may have multiple data lanes for
transmitting two or more words at the same time. If this is the case, each
index in the array represents the lane on both the SPI peripheral and
controller. Additional mapping properties may be needed if a lane is
skipped on either side.
$ref: /schemas/types.yaml#/definitions/uint32-array
items:
enum: [0, 1, 2, 4, 8]
default: [1]
spi-tx-lane-map:
description: Mapping of peripheral SDI lanes to controller SDO lanes.
Each index in the array represents a peripheral SDI lane, and the value
at that index represents the corresponding controller SDO lane.
$ref: /schemas/types.yaml#/definitions/uint32-array
default: [0, 1, 2, 3, 4, 5, 6, 7]
spi-tx-delay-us:
description:
@@ -38,7 +38,6 @@ properties:
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
@@ -96,6 +96,9 @@ properties:
The region should be defined as child node of the AHB SRAM node
as per the generic bindings in Documentation/devicetree/bindings/sram/sram.yaml
power-domains:
maxItems: 1
access-controllers:
minItems: 1
maxItems: 2
+1
View File
@@ -9,6 +9,7 @@ Serial Peripheral Interface (SPI)
spi-summary
spidev
multiple-data-lanes
butterfly
spi-lm70llp
spi-sc18is602
+217
View File
@@ -0,0 +1,217 @@
====================================
SPI devices with multiple data lanes
====================================
Some specialized SPI controllers and peripherals support multiple data lanes
that allow reading more than one word at a time in parallel. This is different
from dual/quad/octal SPI where multiple bits of a single word are transferred
simultaneously.
For example, controllers that support parallel flash memories have this feature
as do some simultaneous-sampling ADCs where each channel has its own data lane.
---------------------
Describing the wiring
---------------------
The ``spi-tx-bus-width`` and ``spi-rx-bus-width`` properties in the devicetree
are used to describe how many data lanes are connected between the controller
and how wide each lane is. The number of items in the array indicates how many
lanes there are, and the value of each item indicates how many bits wide that
lane is.
For example, a dual-simultaneous-sampling ADC with two 4-bit lanes might be
wired up like this::
+--------------+ +----------+
| SPI | | AD4630 |
| Controller | | ADC |
| | | |
| CS0 |--->| CS |
| SCK |--->| SCK |
| SDO |--->| SDI |
| | | |
| SDIA0 |<---| SDOA0 |
| SDIA1 |<---| SDOA1 |
| SDIA2 |<---| SDOA2 |
| SDIA3 |<---| SDOA3 |
| | | |
| SDIB0 |<---| SDOB0 |
| SDIB1 |<---| SDOB1 |
| SDIB2 |<---| SDOB2 |
| SDIB3 |<---| SDOB3 |
| | | |
+--------------+ +----------+
It is described in a devicetree like this::
spi {
compatible = "my,spi-controller";
...
adc@0 {
compatible = "adi,ad4630";
reg = <0>;
...
spi-rx-bus-width = <4>, <4>; /* 2 lanes of 4 bits each */
...
};
};
In most cases, lanes will be wired up symmetrically (A to A, B to B, etc). If
this isn't the case, extra ``spi-rx-lane-map`` and ``spi-tx-lane-map``
properties are needed to provide a mapping between controller lanes and the
physical lane wires.
Here is an example where a multi-lane SPI controller has each lane wired to
separate single-lane peripherals::
+--------------+ +----------+
| SPI | | Thing 1 |
| Controller | | |
| | | |
| CS0 |--->| CS |
| SDO0 |--->| SDI |
| SDI0 |<---| SDO |
| SCLK0 |--->| SCLK |
| | | |
| | +----------+
| |
| | +----------+
| | | Thing 2 |
| | | |
| CS1 |--->| CS |
| SDO1 |--->| SDI |
| SDI1 |<---| SDO |
| SCLK1 |--->| SCLK |
| | | |
+--------------+ +----------+
This is described in a devicetree like this::
spi {
compatible = "my,spi-controller";
...
thing1@0 {
compatible = "my,thing1";
reg = <0>;
...
};
thing2@1 {
compatible = "my,thing2";
reg = <1>;
...
spi-tx-lane-map = <1>; /* lane 0 is not used, lane 1 is used for tx wire */
spi-rx-lane-map = <1>; /* lane 0 is not used, lane 1 is used for rx wire */
...
};
};
The default values of ``spi-rx-bus-width`` and ``spi-tx-bus-width`` are ``<1>``,
so these properties can still be omitted even when ``spi-rx-lane-map`` and
``spi-tx-lane-map`` are used.
----------------------------
Usage in a peripheral driver
----------------------------
These types of SPI controllers generally do not support arbitrary use of the
multiple lanes. Instead, they operate in one of a few defined modes. Peripheral
drivers should set the :c:type:`struct spi_transfer.multi_lane_mode <spi_transfer>`
field to indicate which mode they want to use for a given transfer.
The possible values for this field have the following semantics:
- :c:macro:`SPI_MULTI_BUS_MODE_SINGLE`: Only use the first lane. Other lanes are
ignored. This means that it is operating just like a conventional SPI
peripheral. This is the default, so it does not need to be explicitly set.
Example::
tx_buf[0] = 0x88;
struct spi_transfer xfer = {
.tx_buf = tx_buf,
.len = 1,
};
spi_sync_transfer(spi, &xfer, 1);
Assuming the controller is sending the MSB first, the sequence of bits
sent over the tx wire would be (right-most bit is sent first)::
controller > data bits > peripheral
---------- ---------------- ----------
SDO 0 0-0-0-1-0-0-0-1 SDI 0
- :c:macro:`SPI_MULTI_BUS_MODE_MIRROR`: Send a single data word over all of the
lanes at the same time. This only makes sense for writes and not
for reads.
Example::
tx_buf[0] = 0x88;
struct spi_transfer xfer = {
.tx_buf = tx_buf,
.len = 1,
.multi_lane_mode = SPI_MULTI_BUS_MODE_MIRROR,
};
spi_sync_transfer(spi, &xfer, 1);
The data is mirrored on each tx wire::
controller > data bits > peripheral
---------- ---------------- ----------
SDO 0 0-0-0-1-0-0-0-1 SDI 0
SDO 1 0-0-0-1-0-0-0-1 SDI 1
- :c:macro:`SPI_MULTI_BUS_MODE_STRIPE`: Send or receive two different data words
at the same time, one on each lane. This means that the buffer needs to be
sized to hold data for all lanes. Data is interleaved in the buffer, with
the first word corresponding to lane 0, the second to lane 1, and so on.
Once the last lane is used, the next word in the buffer corresponds to lane
0 again. Accordingly, the buffer size must be a multiple of the number of
lanes. This mode works for both reads and writes.
Example::
struct spi_transfer xfer = {
.rx_buf = rx_buf,
.len = 2,
.multi_lane_mode = SPI_MULTI_BUS_MODE_STRIPE,
};
spi_sync_transfer(spi, &xfer, 1);
Each rx wire has a different data word sent simultaneously::
controller < data bits < peripheral
---------- ---------------- ----------
SDI 0 0-0-0-1-0-0-0-1 SDO 0
SDI 1 1-0-0-0-1-0-0-0 SDO 1
After the transfer, ``rx_buf[0] == 0x11`` (word from SDO 0) and
``rx_buf[1] == 0x88`` (word from SDO 1).
-----------------------------
SPI controller driver support
-----------------------------
To support multiple data lanes, SPI controller drivers need to set
:c:type:`struct spi_controller.num_data_lanes <spi_controller>` to a value
greater than 1.
Then the part of the driver that handles SPI transfers needs to check the
:c:type:`struct spi_transfer.multi_lane_mode <spi_transfer>` field and implement
the appropriate behavior for each supported mode and return an error for
unsupported modes.
The core SPI code should handle the rest.

Some files were not shown because too many files have changed in this diff Show More