diff options
78 files changed, 1321 insertions, 760 deletions
diff --git a/Documentation/devicetree/bindings/spi/renesas,hspi.yaml b/Documentation/devicetree/bindings/spi/renesas,hspi.yaml new file mode 100644 index 000000000000..c429cf4bea5b --- /dev/null +++ b/Documentation/devicetree/bindings/spi/renesas,hspi.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/renesas,hspi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas HSPI + +maintainers: + - Geert Uytterhoeven <geert+renesas@glider.be> + +allOf: + - $ref: spi-controller.yaml# + +properties: + compatible: + items: + - enum: + - renesas,hspi-r8a7778 # R-Car M1A + - renesas,hspi-r8a7779 # R-Car H1 + - const: renesas,hspi + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - '#address-cells' + - '#size-cells' + +examples: + - | + #include <dt-bindings/clock/r8a7778-clock.h> + #include <dt-bindings/interrupt-controller/irq.h> + + hspi0: spi@fffc7000 { + compatible = "renesas,hspi-r8a7778", "renesas,hspi"; + reg = <0xfffc7000 0x18>; + interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp0_clks R8A7778_CLK_HSPI>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; + }; + diff --git a/Documentation/devicetree/bindings/spi/renesas,rzn1-spi.txt b/Documentation/devicetree/bindings/spi/renesas,rzn1-spi.txt new file mode 100644 index 000000000000..fb1a6728638d --- /dev/null +++ b/Documentation/devicetree/bindings/spi/renesas,rzn1-spi.txt @@ -0,0 +1,11 @@ +Renesas RZ/N1 SPI Controller + +This controller is based on the Synopsys DW Synchronous Serial Interface and +inherits all properties defined in snps,dw-apb-ssi.txt except for the +compatible property. + +Required properties: +- compatible : The device specific string followed by the generic RZ/N1 string. + Therefore it must be one of: + "renesas,r9a06g032-spi", "renesas,rzn1-spi" + "renesas,r9a06g033-spi", "renesas,rzn1-spi" diff --git a/Documentation/devicetree/bindings/spi/renesas,sh-msiof.yaml b/Documentation/devicetree/bindings/spi/renesas,sh-msiof.yaml new file mode 100644 index 000000000000..b6c1dd2a9c5e --- /dev/null +++ b/Documentation/devicetree/bindings/spi/renesas,sh-msiof.yaml @@ -0,0 +1,159 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/renesas,sh-msiof.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas MSIOF SPI controller + +maintainers: + - Geert Uytterhoeven <geert+renesas@glider.be> + +allOf: + - $ref: spi-controller.yaml# + +properties: + compatible: + oneOf: + - items: + - const: renesas,msiof-sh73a0 # SH-Mobile AG5 + - const: renesas,sh-mobile-msiof # generic SH-Mobile compatible + # device + - items: + - enum: + - renesas,msiof-r8a7743 # RZ/G1M + - renesas,msiof-r8a7744 # RZ/G1N + - renesas,msiof-r8a7745 # RZ/G1E + - renesas,msiof-r8a77470 # RZ/G1C + - renesas,msiof-r8a7790 # R-Car H2 + - renesas,msiof-r8a7791 # R-Car M2-W + - renesas,msiof-r8a7792 # R-Car V2H + - renesas,msiof-r8a7793 # R-Car M2-N + - renesas,msiof-r8a7794 # R-Car E2 + - const: renesas,rcar-gen2-msiof # generic R-Car Gen2 and RZ/G1 + # compatible device + - items: + - enum: + - renesas,msiof-r8a774a1 # RZ/G2M + - renesas,msiof-r8a774b1 # RZ/G2N + - renesas,msiof-r8a774c0 # RZ/G2E + - renesas,msiof-r8a7795 # R-Car H3 + - renesas,msiof-r8a7796 # R-Car M3-W + - renesas,msiof-r8a77965 # R-Car M3-N + - renesas,msiof-r8a77970 # R-Car V3M + - renesas,msiof-r8a77980 # R-Car V3H + - renesas,msiof-r8a77990 # R-Car E3 + - renesas,msiof-r8a77995 # R-Car D3 + - const: renesas,rcar-gen3-msiof # generic R-Car Gen3 and RZ/G2 + # compatible device + - items: + - const: renesas,sh-msiof # deprecated + + reg: + minItems: 1 + maxItems: 2 + oneOf: + - items: + - description: CPU and DMA engine registers + - items: + - description: CPU registers + - description: DMA engine registers + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + num-cs: + description: | + Total number of chip selects (default is 1). + Up to 3 native chip selects are supported: + 0: MSIOF_SYNC + 1: MSIOF_SS1 + 2: MSIOF_SS2 + Hardware limitations related to chip selects: + - Native chip selects are always deasserted in between transfers + that are part of the same message. Use cs-gpios to work around + this. + - All slaves using native chip selects must use the same spi-cs-high + configuration. Use cs-gpios to work around this. + - When using GPIO chip selects, at least one native chip select must + be left unused, as it will be driven anyway. + minimum: 1 + maximum: 3 + default: 1 + + dmas: + minItems: 2 + maxItems: 4 + + dma-names: + minItems: 2 + maxItems: 4 + items: + enum: [ tx, rx ] + + renesas,dtdl: + description: delay sync signal (setup) in transmit mode. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: + - 0 # no bit delay + - 50 # 0.5-clock-cycle delay + - 100 # 1-clock-cycle delay + - 150 # 1.5-clock-cycle delay + - 200 # 2-clock-cycle delay + + renesas,syncdl: + description: delay sync signal (hold) in transmit mode + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: + - 0 # no bit delay + - 50 # 0.5-clock-cycle delay + - 100 # 1-clock-cycle delay + - 150 # 1.5-clock-cycle delay + - 200 # 2-clock-cycle delay + - 300 # 3-clock-cycle delay + + renesas,tx-fifo-size: + # deprecated for soctype-specific bindings + description: | + Override the default TX fifo size. Unit is words. Ignored if 0. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - maxItems: 1 + default: 64 + + renesas,rx-fifo-size: + # deprecated for soctype-specific bindings + description: | + Override the default RX fifo size. Unit is words. Ignored if 0. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - maxItems: 1 + default: 64 + +required: + - compatible + - reg + - interrupts + - '#address-cells' + - '#size-cells' + +examples: + - | + #include <dt-bindings/clock/r8a7791-clock.h> + #include <dt-bindings/interrupt-controller/irq.h> + + msiof0: spi@e6e20000 { + compatible = "renesas,msiof-r8a7791", "renesas,rcar-gen2-msiof"; + reg = <0 0xe6e20000 0 0x0064>; + interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>; + dmas = <&dmac0 0x51>, <&dmac0 0x52>; + dma-names = "tx", "rx"; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/spi/sh-hspi.txt b/Documentation/devicetree/bindings/spi/sh-hspi.txt deleted file mode 100644 index b9d1e4d11a77..000000000000 --- a/Documentation/devicetree/bindings/spi/sh-hspi.txt +++ /dev/null @@ -1,26 +0,0 @@ -Renesas HSPI. - -Required properties: -- compatible : "renesas,hspi-<soctype>", "renesas,hspi" as fallback. - Examples with soctypes are: - - "renesas,hspi-r8a7778" (R-Car M1) - - "renesas,hspi-r8a7779" (R-Car H1) -- reg : Offset and length of the register set for the device -- interrupts : Interrupt specifier -- #address-cells : Must be <1> -- #size-cells : Must be <0> - -Pinctrl properties might be needed, too. See -Documentation/devicetree/bindings/pinctrl/renesas,*. - -Example: - - hspi0: spi@fffc7000 { - compatible = "renesas,hspi-r8a7778", "renesas,hspi"; - reg = <0xfffc7000 0x18>; - interrupt-parent = <&gic>; - interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - }; - diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt deleted file mode 100644 index 18e14ee257b2..000000000000 --- a/Documentation/devicetree/bindings/spi/sh-msiof.txt +++ /dev/null @@ -1,105 +0,0 @@ -Renesas MSIOF spi controller - -Required properties: -- compatible : "renesas,msiof-r8a7743" (RZ/G1M) - "renesas,msiof-r8a7744" (RZ/G1N) - "renesas,msiof-r8a7745" (RZ/G1E) - "renesas,msiof-r8a77470" (RZ/G1C) - "renesas,msiof-r8a774a1" (RZ/G2M) - "renesas,msiof-r8a774c0" (RZ/G2E) - "renesas,msiof-r8a7790" (R-Car H2) - "renesas,msiof-r8a7791" (R-Car M2-W) - "renesas,msiof-r8a7792" (R-Car V2H) - "renesas,msiof-r8a7793" (R-Car M2-N) - "renesas,msiof-r8a7794" (R-Car E2) - "renesas,msiof-r8a7795" (R-Car H3) - "renesas,msiof-r8a7796" (R-Car M3-W) - "renesas,msiof-r8a77965" (R-Car M3-N) - "renesas,msiof-r8a77970" (R-Car V3M) - "renesas,msiof-r8a77980" (R-Car V3H) - "renesas,msiof-r8a77990" (R-Car E3) - "renesas,msiof-r8a77995" (R-Car D3) - "renesas,msiof-sh73a0" (SH-Mobile AG5) - "renesas,sh-mobile-msiof" (generic SH-Mobile compatibile device) - "renesas,rcar-gen2-msiof" (generic R-Car Gen2 and RZ/G1 compatible device) - "renesas,rcar-gen3-msiof" (generic R-Car Gen3 and RZ/G2 compatible device) - "renesas,sh-msiof" (deprecated) - - When compatible with the generic version, nodes - must list the SoC-specific version corresponding - to the platform first followed by the generic - version. - -- reg : A list of offsets and lengths of the register sets for - the device. - If only one register set is present, it is to be used - by both the CPU and the DMA engine. - If two register sets are present, the first is to be - used by the CPU, and the second is to be used by the - DMA engine. -- interrupts : Interrupt specifier -- #address-cells : Must be <1> -- #size-cells : Must be <0> - -Optional properties: -- clocks : Must contain a reference to the functional clock. -- num-cs : Total number of chip selects (default is 1). - Up to 3 native chip selects are supported: - 0: MSIOF_SYNC - 1: MSIOF_SS1 - 2: MSIOF_SS2 - Hardware limitations related to chip selects: - - Native chip selects are always deasserted in - between transfers that are part of the same - message. Use cs-gpios to work around this. - - All slaves using native chip selects must use the - same spi-cs-high configuration. Use cs-gpios to - work around this. - - When using GPIO chip selects, at least one native - chip select must be left unused, as it will be - driven anyway. -- dmas : Must contain a list of two references to DMA - specifiers, one for transmission, and one for - reception. -- dma-names : Must contain a list of two DMA names, "tx" and "rx". -- spi-slave : Empty property indicating the SPI controller is used - in slave mode. -- renesas,dtdl : delay sync signal (setup) in transmit mode. - Must contain one of the following values: - 0 (no bit delay) - 50 (0.5-clock-cycle delay) - 100 (1-clock-cycle delay) - 150 (1.5-clock-cycle delay) - 200 (2-clock-cycle delay) - -- renesas,syncdl : delay sync signal (hold) in transmit mode. - Must contain one of the following values: - 0 (no bit delay) - 50 (0.5-clock-cycle delay) - 100 (1-clock-cycle delay) - 150 (1.5-clock-cycle delay) - 200 (2-clock-cycle delay) - 300 (3-clock-cycle delay) - -Optional properties, deprecated for soctype-specific bindings: -- renesas,tx-fifo-size : Overrides the default tx fifo size given in words - (default is 64) -- renesas,rx-fifo-size : Overrides the default rx fifo size given in words - (default is 64) - -Pinctrl properties might be needed, too. See -Documentation/devicetree/bindings/pinctrl/renesas,*. - -Example: - - msiof0: spi@e6e20000 { - compatible = "renesas,msiof-r8a7791", - "renesas,rcar-gen2-msiof"; - reg = <0 0xe6e20000 0 0x0064>; - interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>; - dmas = <&dmac0 0x51>, <&dmac0 0x52>; - dma-names = "tx", "rx"; - #address-cells = <1>; - #size-cells = <0>; - }; diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt index f54c8c36395e..3ed08ee9feba 100644 --- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt +++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt @@ -16,7 +16,8 @@ Required properties: Optional properties: - clock-names : Contains the names of the clocks: "ssi_clk", for the core clock used to generate the external SPI clock. - "pclk", the interface clock, required for register access. + "pclk", the interface clock, required for register access. If a clock domain + used to enable this clock then it should be named "pclk_clkdomain". - cs-gpios : Specifies the gpio pins to be used for chipselects. - num-cs : The number of chipselects. If omitted, this will default to 4. - reg-io-width : The I/O register width (in bytes) implemented by this diff --git a/Documentation/devicetree/bindings/spi/spi-sifive.txt b/Documentation/devicetree/bindings/spi/spi-sifive.txt deleted file mode 100644 index 3f5c6e438972..000000000000 --- a/Documentation/devicetree/bindings/spi/spi-sifive.txt +++ /dev/null @@ -1,37 +0,0 @@ -SiFive SPI controller Device Tree Bindings ------------------------------------------- - -Required properties: -- compatible : Should be "sifive,<chip>-spi" and "sifive,spi<version>". - Supported compatible strings are: - "sifive,fu540-c000-spi" for the SiFive SPI v0 as integrated - onto the SiFive FU540 chip, and "sifive,spi0" for the SiFive - SPI v0 IP block with no chip integration tweaks. - Please refer to sifive-blocks-ip-versioning.txt for details -- reg : Physical base address and size of SPI registers map - A second (optional) range can indicate memory mapped flash -- interrupts : Must contain one entry -- interrupt-parent : Must be core interrupt controller -- clocks : Must reference the frequency given to the controller -- #address-cells : Must be '1', indicating which CS to use -- #size-cells : Must be '0' - -Optional properties: -- sifive,fifo-depth : Depth of hardware queues; defaults to 8 -- sifive,max-bits-per-word : Maximum bits per word; defaults to 8 - -SPI RTL that corresponds to the IP block version numbers can be found here: -https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/spi - -Example: - spi: spi@10040000 { - compatible = "sifive,fu540-c000-spi", "sifive,spi0"; - reg = <0x0 0x10040000 0x0 0x1000 0x0 0x20000000 0x0 0x10000000>; - interrupt-parent = <&plic>; - interrupts = <51>; - clocks = <&tlclk>; - #address-cells = <1>; - #size-cells = <0>; - sifive,fifo-depth = <8>; - sifive,max-bits-per-word = <8>; - }; diff --git a/Documentation/devicetree/bindings/spi/spi-sifive.yaml b/Documentation/devicetree/bindings/spi/spi-sifive.yaml new file mode 100644 index 000000000000..140e4351a19f --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi-sifive.yaml @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/spi-sifive.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SiFive SPI controller + +maintainers: + - Pragnesh Patel <pragnesh.patel@sifive.com> + - Paul Walmsley <paul.walmsley@sifive.com> + - Palmer Dabbelt <palmer@sifive.com> + +allOf: + - $ref: "spi-controller.yaml#" + +properties: + compatible: + items: + - const: sifive,fu540-c000-spi + - const: sifive,spi0 + + description: + Should be "sifive,<chip>-spi" and "sifive,spi<version>". + Supported compatible strings are - + "sifive,fu540-c000-spi" for the SiFive SPI v0 as integrated + onto the SiFive FU540 chip, and "sifive,spi0" for the SiFive + SPI v0 IP block with no chip integration tweaks. + Please refer to sifive-blocks-ip-versioning.txt for details + + SPI RTL that corresponds to the IP block version numbers can be found here - + https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/spi + + reg: + maxItems: 1 + + description: + Physical base address and size of SPI registers map + A second (optional) range can indicate memory mapped flash + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + description: + Must reference the frequency given to the controller + + sifive,fifo-depth: + description: + Depth of hardware queues; defaults to 8 + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - enum: [ 8 ] + - default: 8 + + sifive,max-bits-per-word: + description: + Maximum bits per word; defaults to 8 + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - enum: [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ] + - default: 8 + +required: + - compatible + - reg + - interrupts + - clocks + +examples: + - | + spi: spi@10040000 { + compatible = "sifive,fu540-c000-spi", "sifive,spi0"; + reg = <0x0 0x10040000 0x0 0x1000 0x0 0x20000000 0x0 0x10000000>; + interrupt-parent = <&plic>; + interrupts = <51>; + clocks = <&tlclk>; + #address-cells = <1>; + #size-cells = <0>; + sifive,fifo-depth = <8>; + sifive,max-bits-per-word = <8>; + }; + +... diff --git a/Documentation/devicetree/bindings/spi/spi-stm32-qspi.txt b/Documentation/devicetree/bindings/spi/spi-stm32-qspi.txt deleted file mode 100644 index bfc038b9478d..000000000000 --- a/Documentation/devicetree/bindings/spi/spi-stm32-qspi.txt +++ /dev/null @@ -1,47 +0,0 @@ -* STMicroelectronics Quad Serial Peripheral Interface(QSPI) - -Required properties: -- compatible: should be "st,stm32f469-qspi" -- reg: the first contains the register location and length. - the second contains the memory mapping address and length -- reg-names: should contain the reg names "qspi" "qspi_mm" -- interrupts: should contain the interrupt for the device -- clocks: the phandle of the clock needed by the QSPI controller -- A pinctrl must be defined to set pins in mode of operation for QSPI transfer - -Optional properties: -- resets: must contain the phandle to the reset controller. - -A spi flash (NOR/NAND) must be a child of spi node and could have some -properties. Also see jedec,spi-nor.txt. - -Required properties: -- reg: chip-Select number (QSPI controller may connect 2 flashes) -- spi-max-frequency: max frequency of spi bus - -Optional properties: -- spi-rx-bus-width: see ./spi-bus.txt for the description -- dmas: DMA specifiers for tx and rx dma. See the DMA client binding, -Documentation/devicetree/bindings/dma/dma.txt. -- dma-names: DMA request names should include "tx" and "rx" if present. - -Example: - -qspi: spi@a0001000 { - compatible = "st,stm32f469-qspi"; - reg = <0xa0001000 0x1000>, <0x90000000 0x10000000>; - reg-names = "qspi", "qspi_mm"; - interrupts = <91>; - resets = <&rcc STM32F4_AHB3_RESET(QSPI)>; - clocks = <&rcc 0 STM32F4_AHB3_CLOCK(QSPI)>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_qspi0>; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-rx-bus-width = <4>; - spi-max-frequency = <108000000>; - ... - }; -}; diff --git a/Documentation/devicetree/bindings/spi/spi-xilinx.txt b/Documentation/devicetree/bindings/spi/spi-xilinx.txt index dc924a5f71db..5f4ed3e5c994 100644 --- a/Documentation/devicetree/bindings/spi/spi-xilinx.txt +++ b/Documentation/devicetree/bindings/spi/spi-xilinx.txt @@ -8,7 +8,8 @@ Required properties: number. Optional properties: -- xlnx,num-ss-bits : Number of chip selects used. +- xlnx,num-ss-bits : Number of chip selects used. +- xlnx,num-transfer-bits : Number of bits per transfer. This will be 8 if not specified Example: axi_quad_spi@41e00000 { @@ -17,5 +18,6 @@ Example: interrupts = <0 31 1>; reg = <0x41e00000 0x10000>; xlnx,num-ss-bits = <0x1>; + xlnx,num-transfer-bits = <32>; }; diff --git a/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml new file mode 100644 index 000000000000..3665a5fe6b7f --- /dev/null +++ b/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/st,stm32-qspi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 Quad Serial Peripheral Interface (QSPI) bindings + +maintainers: + - Christophe Kerello <christophe.kerello@st.com> + - Patrice Chotard <patrice.chotard@st.com> + +allOf: + - $ref: "spi-controller.yaml#" + +properties: + compatible: + const: st,stm32f469-qspi + + reg: + items: + - description: registers + - description: memory mapping + + reg-names: + items: + - const: qspi + - const: qspi_mm + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + + resets: + maxItems: 1 + + dmas: + items: + - description: tx DMA channel + - description: rx DMA channel + + dma-names: + items: + - const: tx + - const: rx + +required: + - compatible + - reg + - reg-names + - clocks + - interrupts + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/clock/stm32mp1-clks.h> + #include <dt-bindings/reset/stm32mp1-resets.h> + spi@58003000 { + compatible = "st,stm32f469-qspi"; + reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; + reg-names = "qspi", "qspi_mm"; + interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&mdma1 22 0x10 0x100002 0x0 0x0>, + <&mdma1 22 0x10 0x100008 0x0 0x0>; + dma-names = "tx", "rx"; + clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; + + #address-cells = <1>; + #size-cells = <0>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <108000000>; + }; + }; + +... diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c index 9a6e4923bd69..563440315acd 100644 --- a/arch/arm/plat-pxa/ssp.c +++ b/arch/arm/plat-pxa/ssp.c @@ -89,7 +89,7 @@ void pxa_ssp_free(struct ssp_device *ssp) ssp->use_count--; ssp->label = NULL; } else - dev_err(&ssp->pdev->dev, "device already free\n"); + dev_err(ssp->dev, "device already free\n"); mutex_unlock(&ssp_lock); } EXPORT_SYMBOL(pxa_ssp_free); @@ -118,7 +118,7 @@ static int pxa_ssp_probe(struct platform_device *pdev) if (ssp == NULL) return -ENOMEM; - ssp->pdev = pdev; + ssp->dev = dev; ssp->clk = devm_clk_get(dev, NULL); if (IS_ERR(ssp->clk)) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 1631c255deab..2cd2cc2316c6 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -39,24 +39,24 @@ int adis_write_reg(struct adis *adis, unsigned int reg, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, - .cs_change_delay = adis->data->cs_change_delay, - .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, + .cs_change_delay.value = adis->data->cs_change_delay, + .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, - .cs_change_delay = adis->data->cs_change_delay, - .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, + .cs_change_delay.value = adis->data->cs_change_delay, + .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 4, .bits_per_word = 8, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, - .cs_change_delay = adis->data->cs_change_delay, - .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, + .cs_change_delay.value = adis->data->cs_change_delay, + .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 6, .bits_per_word = 8, @@ -139,16 +139,16 @@ int adis_read_reg(struct adis *adis, unsigned int reg, .len = 2, .cs_change = 1, .delay_usecs = adis->data->write_delay, - .cs_change_delay = adis->data->cs_change_delay, - .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, + .cs_change_delay.value = adis->data->cs_change_delay, + .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 2, .bits_per_word = 8, .len = 2, .cs_change = 1, .delay_usecs = adis->data->read_delay, - .cs_change_delay = adis->data->cs_change_delay, - .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, + .cs_change_delay.value = adis->data->cs_change_delay, + .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 4, .rx_buf = adis->rx, @@ -156,8 +156,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg, .len = 2, .cs_change = 1, .delay_usecs = adis->data->read_delay, - .cs_change_delay = adis->data->cs_change_delay, - .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, + .cs_change_delay.value = adis->data->cs_change_delay, + .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .rx_buf = adis->rx + 2, .bits_per_word = 8, diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6f7fdcbb9151..870f7797b56b 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -80,6 +80,7 @@ config SPI_ARMADA_3700 config SPI_ATMEL tristate "Atmel SPI Controller" depends on ARCH_AT91 || COMPILE_TEST + depends on OF help This selects a driver for the Atmel SPI Controller, present on many AT91 ARM chips. @@ -143,7 +144,7 @@ config SPI_BCM63XX tristate "Broadcom BCM63xx SPI controller" depends on BCM63XX || COMPILE_TEST help - Enable support for the SPI controller on the Broadcom BCM63xx SoCs. + Enable support for the SPI controller on the Broadcom BCM63xx SoCs. config SPI_BCM63XX_HSSPI tristate "Broadcom BCM63XX HS SPI controller driver" @@ -234,11 +235,11 @@ config SPI_DLN2 tristate "Diolan DLN-2 USB SPI adapter" depends on MFD_DLN2 help - If you say yes to this option, support will be included for Diolan - DLN2, a USB to SPI interface. + If you say yes to this option, support will be included for Diolan + DLN2, a USB to SPI interface. - This driver can also be built as a module. If so, the module - will be called spi-dln2. + This driver can also be built as a module. If so, the module + will be called spi-dln2. config SPI_EFM32 tristate "EFM32 SPI controller" @@ -747,10 +748,10 @@ config SPI_SYNQUACER It also supports the new dual-bit and quad-bit SPI protocol. config SPI_MXIC - tristate "Macronix MX25F0A SPI controller" - depends on SPI_MASTER - help - This selects the Macronix MX25F0A SPI controller driver. + tristate "Macronix MX25F0A SPI controller" + depends on SPI_MASTER + help + This selects the Macronix MX25F0A SPI controller driver. config SPI_MXS tristate "Freescale MXS SPI controller" diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index a40bb2ef89dc..88033422a42a 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -132,7 +132,7 @@ static int at91_usart_spi_configure_dma(struct spi_controller *ctlr, dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - ctlr->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + ctlr->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR_OR_NULL(ctlr->dma_tx)) { if (IS_ERR(ctlr->dma_tx)) { err = PTR_ERR(ctlr->dma_tx); @@ -145,7 +145,7 @@ static int at91_usart_spi_configure_dma(struct spi_controller *ctlr, goto at91_usart_spi_error_clear; } - ctlr->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + ctlr->dma_rx = dma_request_chan(dev, "rx"); if (IS_ERR_OR_NULL(ctlr->dma_rx)) { if (IS_ERR(ctlr->dma_rx)) { err = PTR_ERR(ctlr->dma_rx); diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index acf318e7330c..56f0ca361deb 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -222,37 +222,13 @@ | SPI_BF(name, value)) /* Register access macros */ -#ifdef CONFIG_AVR32 -#define spi_readl(port, reg) \ - __raw_readl((port)->regs + SPI_##reg) -#define spi_writel(port, reg, value) \ - __raw_writel((value), (port)->regs + SPI_##reg) - -#define spi_readw(port, reg) \ - __raw_readw((port)->regs + SPI_##reg) -#define spi_writew(port, reg, value) \ - __raw_writew((value), (port)->regs + SPI_##reg) - -#define spi_readb(port, reg) \ - __raw_readb((port)->regs + SPI_##reg) -#define spi_writeb(port, reg, value) \ - __raw_writeb((value), (port)->regs + SPI_##reg) -#else #define spi_readl(port, reg) \ readl_relaxed((port)->regs + SPI_##reg) #define spi_writel(port, reg, value) \ writel_relaxed((value), (port)->regs + SPI_##reg) - -#define spi_readw(port, reg) \ - readw_relaxed((port)->regs + SPI_##reg) #define spi_writew(port, reg, value) \ writew_relaxed((value), (port)->regs + SPI_##reg) -#define spi_readb(port, reg) \ - readb_relaxed((port)->regs + SPI_##reg) -#define spi_writeb(port, reg, value) \ - writeb_relaxed((value), (port)->regs + SPI_##reg) -#endif /* use PIO for small transfers, avoiding DMA setup/teardown overhead and * cache operations; better heuristics consider wordsize and bitrate. */ @@ -299,17 +275,16 @@ struct atmel_spi { bool use_dma; bool use_pdc; - bool use_cs_gpios; bool keep_cs; - bool cs_active; u32 fifo_size; + u8 native_cs_free; + u8 native_cs_for_gpio; }; /* Controller-specific per-slave state */ struct atmel_spi_device { - struct gpio_desc *npcs_pin; u32 csr; }; @@ -336,11 +311,9 @@ static bool atmel_spi_is_v2(struct atmel_spi *as) * transmitted") Not so! Workaround uses nCSx pins as GPIOs; or newer * controllers have CSAAT and friends. * - * Since the CSAAT functionality is a bit weird on newer controllers as - * well, we use GPIO to control nCSx pins on all controllers, updating - * MR.PCS to avoid confusing the controller. Using GPIOs also lets us - * support active-high chipselects despite the controller's belief that - * only active-low devices/systems exists. + * Even controller newer than ar91rm9200, using GPIOs can make sens as + * it lets us support active-high chipselects despite the controller's + * belief that only active-low devices/systems exists. * * However, at91rm9200 has a second erratum whereby nCS0 doesn't work * right when driven with GPIO. ("Mode Fault does not allow more than one @@ -352,30 +325,36 @@ static bool atmel_spi_is_v2(struct atmel_spi *as) static void cs_activate(struct atmel_spi *as, struct spi_device *spi) { struct atmel_spi_device *asd = spi->controller_state; + int chip_select; u32 mr; + if (spi->cs_gpiod) + chip_select = as->native_cs_for_gpio; + else + chip_select = spi->chip_select; + if (atmel_spi_is_v2(as)) { - spi_writel(as, CSR0 + 4 * spi->chip_select, asd->csr); + spi_writel(as, CSR0 + 4 * chip_select, asd->csr); /* For the low SPI version, there is a issue that PDC transfer * on CS1,2,3 needs SPI_CSR0.BITS config as SPI_CSR1,2,3.BITS */ spi_writel(as, CSR0, asd->csr); if (as->caps.has_wdrbt) { spi_writel(as, MR, - SPI_BF(PCS, ~(0x01 << spi->chip_select)) + SPI_BF(PCS, ~(0x01 << chip_select)) | SPI_BIT(WDRBT) | SPI_BIT(MODFDIS) | SPI_BIT(MSTR)); } else { spi_writel(as, MR, - SPI_BF(PCS, ~(0x01 << spi->chip_select)) + SPI_BF(PCS, ~(0x01 << chip_select)) | SPI_BIT(MODFDIS) | SPI_BIT(MSTR)); } mr = spi_readl(as, MR); - if (as->use_cs_gpios) - gpiod_set_value(asd->npcs_pin, 1); + if (spi->cs_gpiod) + gpiod_set_value(spi->cs_gpiod, 1); } else { u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; int i; @@ -390,9 +369,9 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) } mr = spi_readl(as, MR); - mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr); - if (as->use_cs_gpios && spi->chip_select != 0) - gpiod_set_value(asd->npcs_pin, 1); + mr = SPI_BFINS(PCS, ~(1 << chip_select), mr); + if (spi->cs_gpiod) + gpiod_set_value(spi->cs_gpiod, 1); spi_writel(as, MR, mr); } @@ -401,24 +380,29 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) { - struct atmel_spi_device *asd = spi->controller_state; + int chip_select; u32 mr; + if (spi->cs_gpiod) + chip_select = as->native_cs_for_gpio; + else + chip_select = spi->chip_select; + /* only deactivate *this* device; sometimes transfers to * another device may be active when this routine is called. */ mr = spi_readl(as, MR); - if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) { + if (~SPI_BFEXT(PCS, mr) & (1 << chip_select)) { mr = SPI_BFINS(PCS, 0xf, mr); spi_writel(as, MR, mr); } dev_dbg(&spi->dev, "DEactivate NPCS, mr %08x\n", mr); - if (!as->use_cs_gpios) + if (!spi->cs_gpiod) spi_writel(as, CR, SPI_BIT(LASTXFER)); - else if (atmel_spi_is_v2(as) || spi->chip_select != 0) - gpiod_set_value(asd->npcs_pin, 0); + else + gpiod_set_value(spi->cs_gpiod, 0); } static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock) @@ -527,7 +511,7 @@ static int atmel_spi_configure_dma(struct spi_master *master, dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + master->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(master->dma_tx)) { err = PTR_ERR(master->dma_tx); if (err == -EPROBE_DEFER) { @@ -844,6 +828,12 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as, { u32 scbr, csr; unsigned long bus_hz; + int chip_select; + + if (spi->cs_gpiod) + chip_select = as->native_cs_for_gpio; + else + chip_select = spi->chip_select; /* v1 chips start out at half the peripheral bus speed. */ bus_hz = as->spi_clk; @@ -872,9 +862,9 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as, xfer->speed_hz, scbr, bus_hz); return -EINVAL; } - csr = spi_readl(as, CSR0 + 4 * spi->chip_select); + csr = spi_readl(as, CSR0 + 4 * chip_select); csr = SPI_BFINS(SCBR, scbr, csr); - spi_writel(as, CSR0 + 4 * spi->chip_select, csr); + spi_writel(as, CSR0 + 4 * chip_select, csr); return 0; } @@ -1173,40 +1163,105 @@ atmel_spi_pdc_interrupt(int irq, void *dev_id) return ret; } +static int atmel_word_delay_csr(struct spi_device *spi, struct atmel_spi *as) +{ + struct spi_delay *delay = &spi->word_delay; + u32 value = delay->value; + + switch (delay->unit) { + case SPI_DELAY_UNIT_NSECS: + value /= 1000; + break; + case SPI_DELAY_UNIT_USECS: + break; + default: + return -EINVAL; + } + + return (as->spi_clk / 1000000 * value) >> 5; +} + +static void initialize_native_cs_for_gpio(struct atmel_spi *as) +{ + int i; + struct spi_master *master = platform_get_drvdata(as->pdev); + + if (!as->native_cs_free) + return; /* already initialized */ + + if (!master->cs_gpiods) + return; /* No CS GPIO */ + + /* + * On the first version of the controller (AT91RM9200), CS0 + * can't be used associated with GPIO + */ + if (atmel_spi_is_v2(as)) + i = 0; + else + i = 1; + + for (; i < 4; i++) + if (master->cs_gpiods[i]) + as->native_cs_free |= BIT(i); + + if (as->native_cs_free) + as->native_cs_for_gpio = ffs(as->native_cs_free); +} + static int atmel_spi_setup(struct spi_device *spi) { struct atmel_spi *as; struct atmel_spi_device *asd; u32 csr; unsigned int bits = spi->bits_per_word; + int chip_select; + int word_delay_csr; as = spi_master_get_devdata(spi->master); /* see notes above re chipselect */ - if (!atmel_spi_is_v2(as) - && spi->chip_select == 0 - && (spi->mode & SPI_CS_HIGH)) { - dev_dbg(&spi->dev, "setup: can't be active-high\n"); + if (!spi->cs_gpiod && (spi->mode & SPI_CS_HIGH)) { + dev_warn(&spi->dev, "setup: non GPIO CS can't be active-high\n"); return -EINVAL; } + /* Setup() is called during spi_register_controller(aka + * spi_register_master) but after all membmers of the cs_gpiod + * array have been filled, so we can looked for which native + * CS will be free for using with GPIO + */ + initialize_native_cs_for_gpio(as); + + if (spi->cs_gpiod && as->native_cs_free) { + dev_err(&spi->dev, + "No native CS available to support this GPIO CS\n"); + return -EBUSY; + } + + if (spi->cs_gpiod) + chip_select = as->native_cs_for_gpio; + else + chip_select = spi->chip_select; + csr = SPI_BF(BITS, bits - 8); if (spi->mode & SPI_CPOL) csr |= SPI_BIT(CPOL); if (!(spi->mode & SPI_CPHA)) csr |= SPI_BIT(NCPHA); - if (!as->use_cs_gpios) - csr |= SPI_BIT(CSAAT); - /* DLYBS is mostly irrelevant since we manage chipselect using GPIOs. - */ + if (!spi->cs_gpiod) + csr |= SPI_BIT(CSAAT); csr |= SPI_BF(DLYBS, 0); + word_delay_csr = atmel_word_delay_csr(spi, as); + if (word_delay_csr < 0) + return word_delay_csr; + /* DLYBCT adds delays between words. This is useful for slow devices * that need a bit of time to setup the next transfer. */ - csr |= SPI_BF(DLYBCT, - (as->spi_clk / 1000000 * spi->word_delay_usecs) >> 5); + csr |= SPI_BF(DLYBCT, word_delay_csr); asd = spi->controller_state; if (!asd) { @@ -1214,21 +1269,6 @@ static int atmel_spi_setup(struct spi_device *spi) if (!asd) return -ENOMEM; - /* - * If use_cs_gpios is true this means that we have "cs-gpios" - * defined in the device tree node so we should have - * gotten the GPIO lines from the device tree inside the - * SPI core. Warn if this is not the case but continue since - * CS GPIOs are after all optional. - */ - if (as->use_cs_gpios) { - if (!spi->cs_gpiod) { - dev_err(&spi->dev, - "host claims to use CS GPIOs but no CS found in DT by the SPI core\n"); - } - asd->npcs_pin = spi->cs_gpiod; - } - spi->controller_state = asd; } @@ -1239,7 +1279,7 @@ static int atmel_spi_setup(struct spi_device *spi) bits, spi->mode, spi->chip_select, csr); if (!atmel_spi_is_v2(as)) - spi_writel(as, CSR0 + 4 * spi->chip_select, csr); + spi_writel(as, CSR0 + 4 * chip_select, csr); return 0; } @@ -1368,19 +1408,16 @@ static int atmel_spi_one_transfer(struct spi_master *master, && as->use_pdc) atmel_spi_dma_unmap_xfer(master, xfer); - if (xfer->delay_usecs) - udelay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); if (xfer->cs_change) { if (list_is_last(&xfer->transfer_list, &msg->transfers)) { as->keep_cs = true; } else { - as->cs_active = !as->cs_active; - if (as->cs_active) - cs_activate(as, msg->spi); - else - cs_deactivate(as, msg->spi); + cs_deactivate(as, msg->spi); + udelay(10); + cs_activate(as, msg->spi); } } @@ -1403,7 +1440,6 @@ static int atmel_spi_transfer_one_message(struct spi_master *master, atmel_spi_lock(as); cs_activate(as, spi); - as->cs_active = true; as->keep_cs = false; msg->status = 0; @@ -1527,7 +1563,7 @@ static int atmel_spi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); master->dev.of_node = pdev->dev.of_node; master->bus_num = pdev->id; - master->num_chipselect = master->dev.of_node ? 0 : 4; + master->num_chipselect = 4; master->setup = atmel_spi_setup; master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX); master->transfer_one_message = atmel_spi_transfer_one_message; @@ -1555,19 +1591,6 @@ static int atmel_spi_probe(struct platform_device *pdev) atmel_get_caps(as); - /* - * If there are chip selects in the device tree, those will be - * discovered by the SPI core when registering the SPI master - * and assigned to each SPI device. - */ - as->use_cs_gpios = true; - if (atmel_spi_is_v2(as) && - pdev->dev.of_node && - !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) { - as->use_cs_gpios = false; - master->num_chipselect = 4; - } - as->use_dma = false; as->use_pdc = false; if (as->caps.has_dma_support) { @@ -1775,20 +1798,18 @@ static const struct dev_pm_ops atmel_spi_pm_ops = { #define ATMEL_SPI_PM_OPS NULL #endif -#if defined(CONFIG_OF) static const struct of_device_id atmel_spi_dt_ids[] = { { .compatible = "atmel,at91rm9200-spi" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_spi_dt_ids); -#endif static struct platform_driver atmel_spi_driver = { .driver = { .name = "atmel_spi", .pm = ATMEL_SPI_PM_OPS, - .of_match_table = of_match_ptr(atmel_spi_dt_ids), + .of_match_table = atmel_spi_dt_ids, }, .probe = atmel_spi_probe, .remove = atmel_spi_remove, diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 74842f6019ed..eb9b78a90dcf 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -163,10 +163,21 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry, } static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry, - struct spi_engine *spi_engine, unsigned int clk_div, unsigned int delay) + struct spi_engine *spi_engine, unsigned int clk_div, + struct spi_transfer *xfer) { unsigned int spi_clk = clk_get_rate(spi_engine->ref_clk); unsigned int t; + int delay; + + if (xfer->delay_usecs) { + delay = xfer->delay_usecs; + } else { + delay = spi_delay_to_ns(&xfer->delay, xfer); + if (delay < 0) + return; + delay /= 1000; + } if (delay == 0) return; @@ -218,8 +229,7 @@ static int spi_engine_compile_message(struct spi_engine *spi_engine, spi_engine_gen_cs(p, dry, spi, true); spi_engine_gen_xfer(p, dry, xfer); - spi_engine_gen_sleep(p, dry, spi_engine, clk_div, - xfer->delay_usecs); + spi_engine_gen_sleep(p, dry, spi_engine, clk_div, xfer); cs_change = xfer->cs_change; if (list_is_last(&xfer->transfer_list, &msg->transfers)) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 7a3531856491..85bad70f59e3 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -803,7 +803,8 @@ static int bcm_qspi_bspi_exec_mem_op(struct spi_device *spi, return -EIO; from = op->addr.val; - bcm_qspi_chip_select(qspi, spi->chip_select); + if (!spi->cs_gpiod) + bcm_qspi_chip_select(qspi, spi->chip_select); bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0); /* @@ -882,7 +883,8 @@ static int bcm_qspi_transfer_one(struct spi_master *master, int slots; unsigned long timeo = msecs_to_jiffies(100); - bcm_qspi_chip_select(qspi, spi->chip_select); + if (!spi->cs_gpiod) + bcm_qspi_chip_select(qspi, spi->chip_select); qspi->trans_pos.trans = trans; qspi->trans_pos.byte = 0; @@ -1234,6 +1236,7 @@ int bcm_qspi_probe(struct platform_device *pdev, master->cleanup = bcm_qspi_cleanup; master->dev.of_node = dev->of_node; master->num_chipselect = NUM_CHIPSELECT; + master->use_gpio_descriptors = true; qspi->big_endian = of_device_is_big_endian(dev->of_node); diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index b4070c0de3df..fb61a620effc 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -1248,7 +1248,7 @@ static int bcm2835_spi_setup(struct spi_device *spi) /* * Retrieve the corresponding GPIO line used for CS. * The inversion semantics will be handled by the GPIO core - * code, so we pass GPIOS_OUT_LOW for "unasserted" and + * code, so we pass GPIOD_OUT_LOW for "unasserted" and * the correct flag for inversion semantics. The SPI_CS_HIGH * on spi->mode cannot be checked for polarity in this case * as the flag use_gpio_descriptors enforces SPI_CS_HIGH. diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index c6836a931dbf..7327309ea3d5 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -291,8 +291,7 @@ static int bcm63xx_hsspi_transfer_one(struct spi_master *master, msg->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (t->cs_change) bcm63xx_hsspi_set_cs(bs, spi->chip_select, false); diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index fdd7eaa0b8ed..0f1b10a4ef0c 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -368,7 +368,7 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master, } /* CS will be deasserted directly after transfer */ - if (t->delay_usecs) { + if (t->delay_usecs || t->delay.value) { dev_err(&spi->dev, "unable to keep CS asserted after transfer\n"); status = -EINVAL; goto exit; diff --git a/drivers/spi/spi-cavium.c b/drivers/spi/spi-cavium.c index 5aaf21582cb5..6854c3ce423b 100644 --- a/drivers/spi/spi-cavium.c +++ b/drivers/spi/spi-cavium.c @@ -119,8 +119,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p, *rx_buf++ = (u8)v; } - if (xfer->delay_usecs) - udelay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); return xfer->len; } diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index bd46fca3f094..384a3ab6dc2d 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -9,6 +9,7 @@ #include <linux/err.h> #include <linux/interrupt.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/scatterlist.h> @@ -193,6 +194,8 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) goto out; } + pm_runtime_enable(&pdev->dev); + ret = dw_spi_add_host(&pdev->dev, dws); if (ret) goto out; @@ -201,6 +204,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) return 0; out: + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(dwsmmio->pclk); out_clk: clk_disable_unprepare(dwsmmio->clk); @@ -212,6 +216,7 @@ static int dw_spi_mmio_remove(struct platform_device *pdev) struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev); dw_spi_remove_host(&dwsmmio->dws); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(dwsmmio->pclk); clk_disable_unprepare(dwsmmio->clk); @@ -223,6 +228,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = { { .compatible = "mscc,ocelot-spi", .data = dw_spi_mscc_ocelot_init}, { .compatible = "mscc,jaguar2-spi", .data = dw_spi_mscc_jaguar2_init}, { .compatible = "amazon,alpine-dw-apb-ssi", .data = dw_spi_alpine_init}, + { .compatible = "renesas,rzn1-spi", }, { /* end of table */} }; MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match); diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 140644913e6c..12c131b5fb4e 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -7,6 +7,7 @@ #include <linux/interrupt.h> #include <linux/pci.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/module.h> @@ -35,7 +36,7 @@ static struct spi_pci_desc spi_pci_mid_desc_2 = { }; static struct spi_pci_desc spi_pci_ehl_desc = { - .num_cs = 1, + .num_cs = 2, .bus_num = -1, .max_freq = 100000000, }; @@ -57,13 +58,18 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Get basic io resource and map it */ dws->paddr = pci_resource_start(pdev, pci_bar); + pci_set_master(pdev); ret = pcim_iomap_regions(pdev, 1 << pci_bar, pci_name(pdev)); if (ret) return ret; + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + return ret; + dws->regs = pcim_iomap_table(pdev)[pci_bar]; - dws->irq = pdev->irq; + dws->irq = pci_irq_vector(pdev, 0); /* * Specific handling for platforms, like dma setup, @@ -80,12 +86,15 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return ret; } } else { + pci_free_irq_vectors(pdev); return -ENODEV; } ret = dw_spi_add_host(&pdev->dev, dws); - if (ret) + if (ret) { + pci_free_irq_vectors(pdev); return ret; + } /* PCI hook and SPI hook use the same drv data */ pci_set_drvdata(pdev, dws); @@ -93,6 +102,11 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n", pdev->vendor, pdev->device); + pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + pm_runtime_allow(&pdev->dev); + return 0; } @@ -100,7 +114,11 @@ static void spi_pci_remove(struct pci_dev *pdev) { struct dw_spi *dws = pci_get_drvdata(pdev); + pm_runtime_forbid(&pdev->dev); + pm_runtime_get_noresume(&pdev->dev); + dw_spi_remove_host(dws); + pci_free_irq_vectors(pdev); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 9a49e073e8b7..a92aa5cd4fbe 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -308,7 +308,8 @@ static int dw_spi_transfer_one(struct spi_controller *master, cr0 = (transfer->bits_per_word - 1) | (chip->type << SPI_FRF_OFFSET) | ((((spi->mode & SPI_CPOL) ? 1 : 0) << SPI_SCOL_OFFSET) | - (((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET)) + (((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET) | + (((spi->mode & SPI_LOOP) ? 1 : 0) << SPI_SRL_OFFSET)) | (chip->tmode << SPI_TMOD_OFFSET); /* @@ -493,6 +494,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) master->dev.of_node = dev->of_node; master->dev.fwnode = dev->fwnode; master->flags = SPI_MASTER_GPIO_SS; + master->auto_runtime_pm = true; if (dws->set_cs) master->set_cs = dws->set_cs; diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index c9c15881e982..38c7de1f0aa9 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -4,7 +4,6 @@ #include <linux/io.h> #include <linux/scatterlist.h> -#include <linux/gpio.h> /* Register offsets */ #define DW_SPI_CTRL0 0x00 diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c index 00f46c816a56..d3336a63f462 100644 --- a/drivers/spi/spi-falcon.c +++ b/drivers/spi/spi-falcon.c @@ -377,7 +377,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master, m->actual_length += t->len; - WARN_ON(t->delay_usecs || t->cs_change); + WARN_ON(t->delay_usecs || t->delay.value || t->cs_change); spi_flags = 0; } diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c index 858f0544289e..54ad0ac121e5 100644 --- a/drivers/spi/spi-fsl-cpm.c +++ b/drivers/spi/spi-fsl-cpm.c @@ -392,7 +392,8 @@ void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE); dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); cpm_muram_free(cpm_muram_offset(mspi->tx_bd)); - cpm_muram_free(cpm_muram_offset(mspi->pram)); + if (!(mspi->flags & SPI_CPM1)) + cpm_muram_free(cpm_muram_offset(mspi->pram)); fsl_spi_free_dummy_rx(); } EXPORT_SYMBOL_GPL(fsl_spi_cpm_free); diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index bec758e978fb..442cff71a0d2 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -129,6 +129,7 @@ enum dspi_trans_mode { struct fsl_dspi_devtype_data { enum dspi_trans_mode trans_mode; u8 max_clock_factor; + bool ptp_sts_supported; bool xspi_mode; }; @@ -140,12 +141,14 @@ static const struct fsl_dspi_devtype_data vf610_data = { static const struct fsl_dspi_devtype_data ls1021a_v1_data = { .trans_mode = DSPI_TCFQ_MODE, .max_clock_factor = 8, + .ptp_sts_supported = true, .xspi_mode = true, }; static const struct fsl_dspi_devtype_data ls2085a_data = { .trans_mode = DSPI_TCFQ_MODE, .max_clock_factor = 8, + .ptp_sts_supported = true, }; static const struct fsl_dspi_devtype_data coldfire_data = { @@ -654,6 +657,9 @@ static int dspi_rxtx(struct fsl_dspi *dspi) u16 spi_tcnt; u32 spi_tcr; + spi_take_timestamp_post(dspi->ctlr, dspi->cur_transfer, + dspi->tx - dspi->bytes_per_word, !dspi->irq); + /* Get transfer counter (in number of SPI transfers). It was * reset to 0 when transfer(s) were started. */ @@ -672,6 +678,9 @@ static int dspi_rxtx(struct fsl_dspi *dspi) /* Success! */ return 0; + spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer, + dspi->tx, !dspi->irq); + if (trans_mode == DSPI_EOQ_MODE) dspi_eoq_write(dspi); else if (trans_mode == DSPI_TCFQ_MODE) @@ -707,7 +716,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) regmap_read(dspi->regmap, SPI_SR, &spi_sr); regmap_write(dspi->regmap, SPI_SR, spi_sr); - if (!(spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))) + if (!(spi_sr & SPI_SR_EOQF)) return IRQ_NONE; if (dspi_rxtx(dspi) == 0) { @@ -779,6 +788,9 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, SPI_FRAME_EBITS(transfer->bits_per_word) | SPI_CTARE_DTCP(1)); + spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer, + dspi->tx, !dspi->irq); + trans_mode = dspi->devtype_data->trans_mode; switch (trans_mode) { case DSPI_EOQ_MODE: @@ -815,8 +827,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, dev_err(&dspi->pdev->dev, "Waiting for transfer to complete failed!\n"); - if (transfer->delay_usecs) - udelay(transfer->delay_usecs); + spi_transfer_delay_exec(transfer); } out: @@ -1006,6 +1017,25 @@ static void dspi_init(struct fsl_dspi *dspi) SPI_CTARE_FMSZE(0) | SPI_CTARE_DTCP(1)); } +static int dspi_slave_abort(struct spi_master *master) +{ + struct fsl_dspi *dspi = spi_master_get_devdata(master); + + /* + * Terminate all pending DMA transactions for the SPI working + * in SLAVE mode. + */ + dmaengine_terminate_sync(dspi->dma->chan_rx); + dmaengine_terminate_sync(dspi->dma->chan_tx); + + /* Clear the internal DSPI RX and TX FIFO buffers */ + regmap_update_bits(dspi->regmap, SPI_MCR, + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF, + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF); + + return 0; +} + static int dspi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1030,6 +1060,7 @@ static int dspi_probe(struct platform_device *pdev) ctlr->dev.of_node = pdev->dev.of_node; ctlr->cleanup = dspi_cleanup; + ctlr->slave_abort = dspi_slave_abort; ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; pdata = dev_get_platdata(&pdev->dev); @@ -1114,6 +1145,9 @@ static int dspi_probe(struct platform_device *pdev) dspi_init(dspi); + if (dspi->devtype_data->trans_mode == DSPI_TCFQ_MODE) + goto poll_mode; + dspi->irq = platform_get_irq(pdev, 0); if (dspi->irq <= 0) { dev_info(&pdev->dev, @@ -1132,6 +1166,7 @@ static int dspi_probe(struct platform_device *pdev) init_waitqueue_head(&dspi->waitq); poll_mode: + if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) { ret = dspi_request_dma(dspi, res->start); if (ret < 0) { @@ -1143,6 +1178,8 @@ poll_mode: ctlr->max_speed_hz = clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor; + ctlr->ptp_sts_supported = dspi->devtype_data->ptp_sts_supported; + platform_set_drvdata(pdev, ctlr); ret = spi_register_controller(ctlr); diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index f20326714b9d..e60581283a24 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -427,8 +427,7 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) ret = fsl_espi_bufs(spi, trans); - if (trans->delay_usecs) - udelay(trans->delay_usecs); + spi_transfer_delay_exec(trans); return ret; } @@ -437,6 +436,7 @@ static int fsl_espi_do_one_msg(struct spi_master *master, struct spi_message *m) { unsigned int delay_usecs = 0, rx_nbits = 0; + unsigned int delay_nsecs = 0, delay_nsecs1 = 0; struct spi_transfer *t, trans = {}; int ret; @@ -445,8 +445,16 @@ static int fsl_espi_do_one_msg(struct spi_master *master, goto out; list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->delay_usecs > delay_usecs) - delay_usecs = t->delay_usecs; + if (t->delay_usecs) { + if (t->delay_usecs > delay_usecs) { + delay_usecs = t->delay_usecs; + delay_nsecs = delay_usecs * 1000; + } + } else { + delay_nsecs1 = spi_delay_to_ns(&t->delay, t); + if (delay_nsecs1 > delay_nsecs) + delay_nsecs = delay_nsecs1; + } if (t->rx_nbits > rx_nbits) rx_nbits = t->rx_nbits; } @@ -457,7 +465,8 @@ static int fsl_espi_do_one_msg(struct spi_master *master, trans.len = m->frame_length; trans.speed_hz = t->speed_hz; trans.bits_per_word = t->bits_per_word; - trans.delay_usecs = delay_usecs; + trans.delay.value = delay_nsecs; + trans.delay.unit = SPI_DELAY_UNIT_NSECS; trans.rx_nbits = rx_nbits; if (trans.len) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index d08e9324140e..2cc0ddb4a988 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -675,7 +675,7 @@ static int fsl_lpspi_dma_init(struct device *dev, int ret; /* Prepare for TX DMA: */ - controller->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + controller->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(controller->dma_tx)) { ret = PTR_ERR(controller->dma_tx); dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret); @@ -684,7 +684,7 @@ static int fsl_lpspi_dma_init(struct device *dev, } /* Prepare for RX DMA: */ - controller->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + controller->dma_rx = dma_request_chan(dev, "rx"); if (IS_ERR(controller->dma_rx)) { ret = PTR_ERR(controller->dma_rx); dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret); @@ -779,7 +779,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) if (temp_SR & SR_FCF && (temp_IER & IER_FCIE)) { writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR); - complete(&fsl_lpspi->xfer_done); + complete(&fsl_lpspi->xfer_done); return IRQ_HANDLED; } @@ -938,7 +938,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ret = pm_runtime_get_sync(fsl_lpspi->dev); if (ret < 0) { dev_err(fsl_lpspi->dev, "failed to enable clock\n"); - return ret; + goto out_controller_put; } temp = readl(fsl_lpspi->base + IMX7ULP_PARAM); diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index c02e24c01136..79b1558b74b8 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -63,6 +63,16 @@ #define QUADSPI_IPCR 0x08 #define QUADSPI_IPCR_SEQID(x) ((x) << 24) +#define QUADSPI_FLSHCR 0x0c +#define QUADSPI_FLSHCR_TCSS_MASK GENMASK(3, 0) +#define QUADSPI_FLSHCR_TCSH_MASK GENMASK(11, 8) +#define QUADSPI_FLSHCR_TDH_MASK GENMASK(17, 16) + +#define QUADSPI_BUF0CR 0x10 +#define QUADSPI_BUF1CR 0x14 +#define QUADSPI_BUF2CR 0x18 +#define QUADSPI_BUFXCR_INVALID_MSTRID 0xe + #define QUADSPI_BUF3CR 0x1c #define QUADSPI_BUF3CR_ALLMST_MASK BIT(31) #define QUADSPI_BUF3CR_ADATSZ(x) ((x) << 8) @@ -95,6 +105,9 @@ #define QUADSPI_FR 0x160 #define QUADSPI_FR_TFF_MASK BIT(0) +#define QUADSPI_RSER 0x164 +#define QUADSPI_RSER_TFIE BIT(0) + #define QUADSPI_SPTRCLR 0x16c #define QUADSPI_SPTRCLR_IPPTRC BIT(8) #define QUADSPI_SPTRCLR_BFPTRC BIT(0) @@ -112,9 +125,6 @@ #define QUADSPI_LCKER_LOCK BIT(0) #define QUADSPI_LCKER_UNLOCK BIT(1) -#define QUADSPI_RSER 0x164 -#define QUADSPI_RSER_TFIE BIT(0) - #define QUADSPI_LUT_BASE 0x310 #define QUADSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) #define QUADSPI_LUT_REG(idx) \ @@ -181,9 +191,16 @@ */ #define QUADSPI_QUIRK_BASE_INTERNAL BIT(4) +/* + * Controller uses TDH bits in register QUADSPI_FLSHCR. + * They need to be set in accordance with the DDR/SDR mode. + */ +#define QUADSPI_QUIRK_USE_TDH_SETTING BIT(5) + struct fsl_qspi_devtype_data { unsigned int rxfifo; unsigned int txfifo; + int invalid_mstrid; unsigned int ahb_buf_size; unsigned int quirks; bool little_endian; @@ -192,6 +209,7 @@ struct fsl_qspi_devtype_data { static const struct fsl_qspi_devtype_data vybrid_data = { .rxfifo = SZ_128, .txfifo = SZ_64, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, .quirks = QUADSPI_QUIRK_SWAP_ENDIAN, .little_endian = true, @@ -200,6 +218,7 @@ static const struct fsl_qspi_devtype_data vybrid_data = { static const struct fsl_qspi_devtype_data imx6sx_data = { .rxfifo = SZ_128, .txfifo = SZ_512, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, .quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618, .little_endian = true, @@ -208,22 +227,27 @@ static const struct fsl_qspi_devtype_data imx6sx_data = { static const struct fsl_qspi_devtype_data imx7d_data = { .rxfifo = SZ_128, .txfifo = SZ_512, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, - .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK, + .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK | + QUADSPI_QUIRK_USE_TDH_SETTING, .little_endian = true, }; static const struct fsl_qspi_devtype_data imx6ul_data = { .rxfifo = SZ_128, .txfifo = SZ_512, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, - .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK, + .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK | + QUADSPI_QUIRK_USE_TDH_SETTING, .little_endian = true, }; static const struct fsl_qspi_devtype_data ls1021a_data = { .rxfifo = SZ_128, .txfifo = SZ_64, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, .quirks = 0, .little_endian = false, @@ -233,6 +257,7 @@ static const struct fsl_qspi_devtype_data ls2080a_data = { .rxfifo = SZ_128, .txfifo = SZ_64, .ahb_buf_size = SZ_1K, + .invalid_mstrid = 0x0, .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_BASE_INTERNAL, .little_endian = true, }; @@ -275,6 +300,11 @@ static inline int needs_amba_base_offset(struct fsl_qspi *q) return !(q->devtype_data->quirks & QUADSPI_QUIRK_BASE_INTERNAL); } +static inline int needs_tdh_setting(struct fsl_qspi *q) +{ + return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING; +} + /* * An IC bug makes it necessary to rearrange the 32-bit data. * Later chips, such as IMX6SLX, have fixed this bug. @@ -615,6 +645,7 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) void __iomem *base = q->iobase; u32 addr_offset = 0; int err = 0; + int invalid_mstrid = q->devtype_data->invalid_mstrid; mutex_lock(&q->lock); @@ -638,6 +669,10 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) qspi_writel(q, QUADSPI_SPTRCLR_BFPTRC | QUADSPI_SPTRCLR_IPPTRC, base + QUADSPI_SPTRCLR); + qspi_writel(q, invalid_mstrid, base + QUADSPI_BUF0CR); + qspi_writel(q, invalid_mstrid, base + QUADSPI_BUF1CR); + qspi_writel(q, invalid_mstrid, base + QUADSPI_BUF2CR); + fsl_qspi_prepare_lut(q, op); /* @@ -710,6 +745,16 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q) qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, base + QUADSPI_MCR); + /* + * Previous boot stages (BootROM, bootloader) might have used DDR + * mode and did not clear the TDH bits. As we currently use SDR mode + * only, clear the TDH bits if necessary. + */ + if (needs_tdh_setting(q)) + qspi_writel(q, qspi_readl(q, base + QUADSPI_FLSHCR) & + ~QUADSPI_FLSHCR_TDH_MASK, + base + QUADSPI_FLSHCR); + reg = qspi_readl(q, base + QUADSPI_SMPR); qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK | QUADSPI_SMPR_FSPHS_MASK diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 4b80ace1d137..114801a32371 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -416,8 +416,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master, } m->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (cs_change) { ndelay(nsecs); diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 1d3e23ec20a6..7ceb0ba27b75 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -362,19 +362,18 @@ static int spi_gpio_probe(struct platform_device *pdev) struct spi_gpio *spi_gpio; struct device *dev = &pdev->dev; struct spi_bitbang *bb; - const struct of_device_id *of_id; - - of_id = of_match_device(spi_gpio_dt_ids, &pdev->dev); master = spi_alloc_master(dev, sizeof(*spi_gpio)); if (!master) return -ENOMEM; status = devm_add_action_or_reset(&pdev->dev, spi_gpio_put, master); - if (status) + if (status) { + spi_master_put(master); return status; + } - if (of_id) + if (pdev->dev.of_node) status = spi_gpio_probe_dt(pdev, master); else status = spi_gpio_probe_pdata(pdev, master); diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 439b01e4a2c8..f4a8f470aecc 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -673,6 +673,8 @@ static int img_spfi_probe(struct platform_device *pdev) dma_release_channel(spfi->tx_ch); if (spfi->rx_ch) dma_release_channel(spfi->rx_ch); + spfi->tx_ch = NULL; + spfi->rx_ch = NULL; dev_warn(spfi->dev, "Failed to get DMA channels, falling back to PIO mode\n"); } else { master->dma_tx = spfi->tx_ch; diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 09c9a1edb2c6..49f0099db0cb 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1272,7 +1272,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, spi_imx->wml = spi_imx->devtype_data->fifo_size / 2; /* Prepare for TX DMA: */ - master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + master->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(master->dma_tx)) { ret = PTR_ERR(master->dma_tx); dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret); @@ -1281,7 +1281,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, } /* Prepare for RX : */ - master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + master->dma_rx = dma_request_chan(dev, "rx"); if (IS_ERR(master->dma_rx)) { ret = PTR_ERR(master->dma_rx); dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret); diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index 9dfe8b04e688..1fd7ee53d451 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -797,7 +797,6 @@ static int lantiq_ssc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct spi_master *master; - struct resource *res; struct lantiq_ssc_spi *spi; const struct lantiq_ssc_hwcfg *hwcfg; const struct of_device_id *match; @@ -812,12 +811,6 @@ static int lantiq_ssc_probe(struct platform_device *pdev) } hwcfg = match->data; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to get resources\n"); - return -ENXIO; - } - rx_irq = platform_get_irq_byname(pdev, LTQ_SPI_RX_IRQ_NAME); if (rx_irq < 0) return -ENXIO; @@ -839,8 +832,7 @@ static int lantiq_ssc_probe(struct platform_device *pdev) spi->dev = dev; spi->hwcfg = hwcfg; platform_set_drvdata(pdev, spi); - - spi->regbase = devm_ioremap_resource(dev, res); + spi->regbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi->regbase)) { err = PTR_ERR(spi->regbase); goto err_master_put; diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index 6f18d4952767..b6d79cd156fb 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -298,12 +298,18 @@ static struct spi_test spi_tests[] = { { .tx_buf = TX(0), .rx_buf = RX(0), - .delay_usecs = 1000, + .delay = { + .value = 1000, + .unit = SPI_DELAY_UNIT_USECS, + }, }, { .tx_buf = TX(0), .rx_buf = RX(0), - .delay_usecs = 1000, + .delay = { + .value = 1000, + .unit = SPI_DELAY_UNIT_USECS, + }, }, }, }, @@ -537,7 +543,7 @@ static int spi_test_check_elapsed_time(struct spi_device *spi, unsigned long long nbits = (unsigned long long)BITS_PER_BYTE * xfer->len; - delay_usecs += xfer->delay_usecs; + delay_usecs += xfer->delay.value; if (!xfer->speed_hz) continue; estimated_time += div_u64(nbits * NSEC_PER_SEC, xfer->speed_hz); diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 9f0fa9f3116d..e5a46f0eb93b 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -286,7 +286,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) if (!spi_mem_internal_supports_op(mem, op)) return -ENOTSUPP; - if (ctlr->mem_ops) { + if (ctlr->mem_ops && !mem->spi->cs_gpiod) { ret = spi_mem_access_start(mem); if (ret) return ret; diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index a337b842ae8c..ea1b07953d38 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -311,8 +311,7 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master, break; m->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (cs_change) mpc512x_psc_spi_deactivate_cs(spi); diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index c7e478b9b586..17935e71b02f 100644 --- a/drivers/spi/spi-mpc52xx-psc.c +++ b/drivers/spi/spi-mpc52xx-psc.c @@ -234,8 +234,7 @@ static void mpc52xx_psc_spi_work(struct work_struct *work) break; m->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (cs_change) mpc52xx_psc_spi_deactivate_cs(spi); diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 6888a4dcff6d..6783e12c40c2 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -139,7 +139,6 @@ static const struct mtk_spi_compatible mt8183_compat = { * supplies it. */ static const struct mtk_chip_config mtk_default_chip_info = { - .cs_pol = 0, .sample_sel = 0, }; @@ -230,10 +229,12 @@ static int mtk_spi_prepare_message(struct spi_master *master, #endif if (mdata->dev_comp->enhance_timing) { - if (chip_config->cs_pol) + /* set CS polarity */ + if (spi->mode & SPI_CS_HIGH) reg_val |= SPI_CMD_CS_POL; else reg_val &= ~SPI_CMD_CS_POL; + if (chip_config->sample_sel) reg_val |= SPI_CMD_SAMPLE_SEL; else @@ -264,6 +265,9 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable) u32 reg_val; struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + if (spi->mode & SPI_CS_HIGH) + enable = !enable; + reg_val = readl(mdata->base + SPI_CMD_REG); if (!enable) { reg_val |= SPI_CMD_PAUSE_EN; @@ -619,7 +623,6 @@ static int mtk_spi_probe(struct platform_device *pdev) struct spi_master *master; struct mtk_spi *mdata; const struct of_device_id *of_id; - struct resource *res; int i, irq, ret, addr_bits; master = spi_alloc_master(&pdev->dev, sizeof(*mdata)); @@ -647,6 +650,10 @@ static int mtk_spi_probe(struct platform_device *pdev) mdata = spi_master_get_devdata(master); mdata->dev_comp = of_id->data; + + if (mdata->dev_comp->enhance_timing) + master->mode_bits |= SPI_CS_HIGH; + if (mdata->dev_comp->must_tx) master->flags = SPI_MASTER_MUST_TX; @@ -682,15 +689,7 @@ static int mtk_spi_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, master); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENODEV; - dev_err(&pdev->dev, "failed to determine base address\n"); - goto err_put_master; - } - - mdata->base = devm_ioremap_resource(&pdev->dev, res); + mdata->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mdata->base)) { ret = PTR_ERR(mdata->base); goto err_put_master; diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c index f48563c09b97..69491f3a515d 100644 --- a/drivers/spi/spi-mxic.c +++ b/drivers/spi/spi-mxic.c @@ -145,8 +145,8 @@ #define LWR_SUSP_CTRL_EN BIT(31) #define DMAS_CTRL 0x9c -#define DMAS_CTRL_DIR_READ BIT(31) -#define DMAS_CTRL_EN BIT(30) +#define DMAS_CTRL_EN BIT(31) +#define DMAS_CTRL_DIR_READ BIT(30) #define DATA_STROB 0xa0 #define DATA_STROB_EDO_EN BIT(2) @@ -275,7 +275,7 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic) writel(0, mxic->regs + HC_EN); writel(0, mxic->regs + LRD_CFG); writel(0, mxic->regs + LRD_CTRL); - writel(HC_CFG_NIO(1) | HC_CFG_TYPE(0, HC_CFG_TYPE_SPI_NAND) | + writel(HC_CFG_NIO(1) | HC_CFG_TYPE(0, HC_CFG_TYPE_SPI_NOR) | HC_CFG_SLV_ACT(0) | HC_CFG_MAN_CS_EN | HC_CFG_IDLE_SIO_LVL(1), mxic->regs + HC_CFG); } @@ -346,7 +346,7 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem, if (op->addr.nbytes > 7) return false; - return true; + return spi_mem_default_supports_op(mem, op); } static int mxic_spi_mem_exec_op(struct spi_mem *mem, diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index b191d57d1dc0..fe624731c74c 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -293,7 +293,6 @@ static void npcm_pspi_reset_hw(struct npcm_pspi *priv) static irqreturn_t npcm_pspi_handler(int irq, void *dev_id) { struct npcm_pspi *priv = dev_id; - u16 val; u8 stat; stat = ioread8(priv->base + NPCM_PSPI_STAT); @@ -303,7 +302,7 @@ static irqreturn_t npcm_pspi_handler(int irq, void *dev_id) if (priv->tx_buf) { if (stat & NPCM_PSPI_STAT_RBF) { - val = ioread8(NPCM_PSPI_DATA + priv->base); + ioread8(NPCM_PSPI_DATA + priv->base); if (priv->tx_bytes == 0) { npcm_pspi_disable(priv); complete(&priv->xfer_done); diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 501b923f2c27..c36bb1bb464e 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -1027,7 +1027,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) ctlr->dev.of_node = np; - ret = spi_register_controller(ctlr); + ret = devm_spi_register_controller(&pdev->dev, ctlr); if (ret) goto err_destroy_mutex; diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index b955ca8796d2..5c704ba6d8ea 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -128,7 +128,7 @@ static void spi100k_write_data(struct spi_master *master, int len, int data) static int spi100k_read_data(struct spi_master *master, int len) { - int dataH, dataL; + int dataL; struct omap1_spi100k *spi100k = spi_master_get_devdata(master); /* Always do at least 16 bits */ @@ -146,7 +146,7 @@ static int spi100k_read_data(struct spi_master *master, int len) udelay(1000); dataL = readw(spi100k->base + SPI_RX_LSB); - dataH = readw(spi100k->base + SPI_RX_MSB); + readw(spi100k->base + SPI_RX_MSB); spi100k_disable_clock(master); return dataL; @@ -321,8 +321,7 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master, } } - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); /* ignore the "leave it on after last xfer" hint */ diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 848e03e5f42d..7e2292c11d12 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -397,30 +397,26 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi, { struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *mcspi_dma; + struct dma_async_tx_descriptor *tx; mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; - if (mcspi_dma->dma_tx) { - struct dma_async_tx_descriptor *tx; + dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); - dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); - - tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl, - xfer->tx_sg.nents, - DMA_MEM_TO_DEV, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (tx) { - tx->callback = omap2_mcspi_tx_callback; - tx->callback_param = spi; - dmaengine_submit(tx); - } else { - /* FIXME: fall back to PIO? */ - } + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl, + xfer->tx_sg.nents, + DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_tx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ } dma_async_issue_pending(mcspi_dma->dma_tx); omap2_mcspi_set_dma_req(spi, 0, 1); - } static unsigned @@ -439,6 +435,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, int word_len, element_count; struct omap2_mcspi_cs *cs = spi->controller_state; void __iomem *chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; + struct dma_async_tx_descriptor *tx; mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; @@ -462,55 +459,47 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, else /* word_len <= 32 */ element_count = count >> 2; - if (mcspi_dma->dma_rx) { - struct dma_async_tx_descriptor *tx; - dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); + dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); + /* + * Reduce DMA transfer length by one more if McSPI is + * configured in turbo mode. + */ + if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0) + transfer_reduction += es; + + if (transfer_reduction) { + /* Split sgl into two. The second sgl won't be used. */ + sizes[0] = count - transfer_reduction; + sizes[1] = transfer_reduction; + nb_sizes = 2; + } else { /* - * Reduce DMA transfer length by one more if McSPI is - * configured in turbo mode. + * Don't bother splitting the sgl. This essentially + * clones the original sgl. */ - if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0) - transfer_reduction += es; - - if (transfer_reduction) { - /* Split sgl into two. The second sgl won't be used. */ - sizes[0] = count - transfer_reduction; - sizes[1] = transfer_reduction; - nb_sizes = 2; - } else { - /* - * Don't bother splitting the sgl. This essentially - * clones the original sgl. - */ - sizes[0] = count; - nb_sizes = 1; - } + sizes[0] = count; + nb_sizes = 1; + } - ret = sg_split(xfer->rx_sg.sgl, xfer->rx_sg.nents, - 0, nb_sizes, - sizes, - sg_out, out_mapped_nents, - GFP_KERNEL); + ret = sg_split(xfer->rx_sg.sgl, xfer->rx_sg.nents, 0, nb_sizes, + sizes, sg_out, out_mapped_nents, GFP_KERNEL); - if (ret < 0) { - dev_err(&spi->dev, "sg_split failed\n"); - return 0; - } + if (ret < 0) { + dev_err(&spi->dev, "sg_split failed\n"); + return 0; + } - tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, - sg_out[0], - out_mapped_nents[0], - DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (tx) { - tx->callback = omap2_mcspi_rx_callback; - tx->callback_param = spi; - dmaengine_submit(tx); - } else { - /* FIXME: fall back to PIO? */ - } + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, sg_out[0], + out_mapped_nents[0], DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_rx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ } dma_async_issue_pending(mcspi_dma->dma_rx); diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 6643ccdc2508..c7266ef295fd 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -467,8 +467,7 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) if (orion_spi_write_read_8bit(spi, &tx, &rx) < 0) goto out; count--; - if (xfer->word_delay_usecs) - udelay(xfer->word_delay_usecs); + spi_delay_exec(&xfer->word_delay, xfer); } while (count); } else if (word_len == 16) { const u16 *tx = xfer->tx_buf; @@ -478,8 +477,7 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) if (orion_spi_write_read_16bit(spi, &tx, &rx) < 0) goto out; count -= 2; - if (xfer->word_delay_usecs) - udelay(xfer->word_delay_usecs); + spi_delay_exec(&xfer->word_delay, xfer); } while (count); } @@ -772,9 +770,6 @@ static int orion_spi_probe(struct platform_device *pdev) if (status < 0) goto out_rel_pm; - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put_autosuspend(&pdev->dev); - master->dev.of_node = pdev->dev.of_node; status = spi_register_master(master); if (status < 0) diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 69f517ec59c6..156961b4ca86 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -606,25 +606,30 @@ static void pic32_spi_cleanup(struct spi_device *spi) gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); } -static void pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) +static int pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) { struct spi_master *master = pic32s->master; - dma_cap_mask_t mask; + int ret = 0; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); + master->dma_rx = dma_request_chan(dev, "spi-rx"); + if (IS_ERR(master->dma_rx)) { + if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) + ret = -EPROBE_DEFER; + else + dev_warn(dev, "RX channel not found.\n"); - master->dma_rx = dma_request_slave_channel_compat(mask, NULL, NULL, - dev, "spi-rx"); - if (!master->dma_rx) { - dev_warn(dev, "RX channel not found.\n"); + master->dma_rx = NULL; goto out_err; } - master->dma_tx = dma_request_slave_channel_compat(mask, NULL, NULL, - dev, "spi-tx"); - if (!master->dma_tx) { - dev_warn(dev, "TX channel not found.\n"); + master->dma_tx = dma_request_chan(dev, "spi-tx"); + if (IS_ERR(master->dma_tx)) { + if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) + ret = -EPROBE_DEFER; + else + dev_warn(dev, "TX channel not found.\n"); + + master->dma_tx = NULL; goto out_err; } @@ -634,14 +639,20 @@ static void pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) /* DMA chnls allocated and prepared */ set_bit(PIC32F_DMA_PREP, &pic32s->flags); - return; + return 0; out_err: - if (master->dma_rx) + if (master->dma_rx) { dma_release_channel(master->dma_rx); + master->dma_rx = NULL; + } - if (master->dma_tx) + if (master->dma_tx) { dma_release_channel(master->dma_tx); + master->dma_tx = NULL; + } + + return ret; } static void pic32_spi_dma_unprep(struct pic32_spi *pic32s) @@ -776,7 +787,10 @@ static int pic32_spi_probe(struct platform_device *pdev) master->unprepare_transfer_hardware = pic32_spi_unprepare_hardware; /* optional DMA support */ - pic32_spi_dma_prep(pic32s, &pdev->dev); + ret = pic32_spi_dma_prep(pic32s, &pdev->dev); + if (ret) + goto err_bailout; + if (test_bit(PIC32F_DMA_PREP, &pic32s->flags)) master->can_dma = pic32_spi_can_dma; diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 7fedea67159c..66028ebbc336 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -485,12 +485,11 @@ static void giveback(struct pl022 *pl022) struct spi_transfer, transfer_list); /* Delay if requested before any change in chip select */ - if (last_transfer->delay_usecs) - /* - * FIXME: This runs in interrupt context. - * Is this really smart? - */ - udelay(last_transfer->delay_usecs); + /* + * FIXME: This runs in interrupt context. + * Is this really smart? + */ + spi_transfer_delay_exec(last_transfer); if (!last_transfer->cs_change) { struct spi_message *next_msg; @@ -1159,7 +1158,7 @@ static int pl022_dma_autoprobe(struct pl022 *pl022) int err; /* automatically configure DMA channels from platform, normally using DT */ - chan = dma_request_slave_channel_reason(dev, "rx"); + chan = dma_request_chan(dev, "rx"); if (IS_ERR(chan)) { err = PTR_ERR(chan); goto err_no_rxchan; @@ -1167,7 +1166,7 @@ static int pl022_dma_autoprobe(struct pl022 *pl022) pl022->dma_rx_channel = chan; - chan = dma_request_slave_channel_reason(dev, "tx"); + chan = dma_request_chan(dev, "tx"); if (IS_ERR(chan)) { err = PTR_ERR(chan); goto err_no_txchan; @@ -1401,12 +1400,11 @@ static void pump_transfers(unsigned long data) previous = list_entry(transfer->transfer_list.prev, struct spi_transfer, transfer_list); - if (previous->delay_usecs) - /* - * FIXME: This runs in interrupt context. - * Is this really smart? - */ - udelay(previous->delay_usecs); + /* + * FIXME: This runs in interrupt context. + * Is this really smart? + */ + spi_transfer_delay_exec(previous); /* Reselect chip select only if cs_change was requested */ if (previous->cs_change) @@ -1520,8 +1518,7 @@ static void do_polling_transfer(struct pl022 *pl022) previous = list_entry(transfer->transfer_list.prev, struct spi_transfer, transfer_list); - if (previous->delay_usecs) - udelay(previous->delay_usecs); + spi_transfer_delay_exec(previous); if (previous->cs_change) pl022_cs_control(pl022, SSP_CHIP_SELECT); } else { diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index bb6a14d1ab0f..16b6b2ad4e7c 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -4,27 +4,29 @@ * Copyright (C) 2013, Intel Corporation */ +#include <linux/acpi.h> #include <linux/bitops.h> -#include <linux/init.h> -#include <linux/module.h> +#include <linux/clk.h> +#include <linux/delay.h> #include <linux/device.h> -#include <linux/ioport.h> -#include <linux/errno.h> #include <linux/err.h> +#include <linux/errno.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio.h> +#include <linux/init.h> #include <linux/interrupt.h> +#include <linux/ioport.h> #include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/of.h> #include <linux/pci.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/property.h> +#include <linux/slab.h> #include <linux/spi/pxa2xx_spi.h> #include <linux/spi/spi.h> -#include <linux/delay.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h> -#include <linux/slab.h> -#include <linux/clk.h> -#include <linux/pm_runtime.h> -#include <linux/acpi.h> -#include <linux/of_device.h> #include "spi-pxa2xx.h" @@ -1457,6 +1459,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { { PCI_VDEVICE(INTEL, 0x02aa), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x02ab), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x02fb), LPSS_CNL_SSP }, + /* CML-H */ + { PCI_VDEVICE(INTEL, 0x06aa), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x06ab), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x06fb), LPSS_CNL_SSP }, /* TGL-LP */ { PCI_VDEVICE(INTEL, 0xa0aa), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0xa0ab), LPSS_CNL_SSP }, @@ -1476,11 +1482,13 @@ MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match); #ifdef CONFIG_ACPI -static int pxa2xx_spi_get_port_id(struct acpi_device *adev) +static int pxa2xx_spi_get_port_id(struct device *dev) { + struct acpi_device *adev; unsigned int devid; int port_id = -1; + adev = ACPI_COMPANION(dev); if (adev && adev->pnp.unique_id && !kstrtouint(adev->pnp.unique_id, 0, &devid)) port_id = devid; @@ -1489,7 +1497,7 @@ static int pxa2xx_spi_get_port_id(struct acpi_device *adev) #else /* !CONFIG_ACPI */ -static int pxa2xx_spi_get_port_id(struct acpi_device *adev) +static int pxa2xx_spi_get_port_id(struct device *dev) { return -1; } @@ -1510,34 +1518,22 @@ static struct pxa2xx_spi_controller * pxa2xx_spi_init_pdata(struct platform_device *pdev) { struct pxa2xx_spi_controller *pdata; - struct acpi_device *adev; struct ssp_device *ssp; struct resource *res; - const struct acpi_device_id *adev_id = NULL; + struct device *parent = pdev->dev.parent; + struct pci_dev *pcidev = dev_is_pci(parent) ? to_pci_dev(parent) : NULL; const struct pci_device_id *pcidev_id = NULL; - const struct of_device_id *of_id = NULL; enum pxa_ssp_type type; + const void *match; - adev = ACPI_COMPANION(&pdev->dev); - - if (pdev->dev.of_node) - of_id = of_match_device(pdev->dev.driver->of_match_table, - &pdev->dev); - else if (dev_is_pci(pdev->dev.parent)) - pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match, - to_pci_dev(pdev->dev.parent)); - else if (adev) - adev_id = acpi_match_device(pdev->dev.driver->acpi_match_table, - &pdev->dev); - else - return NULL; + if (pcidev) + pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match, pcidev); - if (adev_id) - type = (enum pxa_ssp_type)adev_id->driver_data; + match = device_get_match_data(&pdev->dev); + if (match) + type = (enum pxa_ssp_type)match; else if (pcidev_id) type = (enum pxa_ssp_type)pcidev_id->driver_data; - else if (of_id) - type = (enum pxa_ssp_type)of_id->data; else return NULL; @@ -1545,32 +1541,36 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) if (!pdata) return NULL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return NULL; - ssp = &pdata->ssp; - ssp->phys_base = res->start; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ssp->mmio_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(ssp->mmio_base)) return NULL; + ssp->phys_base = res->start; + #ifdef CONFIG_PCI if (pcidev_id) { - pdata->tx_param = pdev->dev.parent; - pdata->rx_param = pdev->dev.parent; + pdata->tx_param = parent; + pdata->rx_param = parent; pdata->dma_filter = pxa2xx_spi_idma_filter; } #endif ssp->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ssp->clk)) + return NULL; + ssp->irq = platform_get_irq(pdev, 0); + if (ssp->irq < 0) + return NULL; + ssp->type = type; - ssp->pdev = pdev; - ssp->port_id = pxa2xx_spi_get_port_id(adev); + ssp->dev = &pdev->dev; + ssp->port_id = pxa2xx_spi_get_port_id(&pdev->dev); - pdata->is_slave = of_property_read_bool(pdev->dev.of_node, "spi-slave"); + pdata->is_slave = device_property_read_bool(&pdev->dev, "spi-slave"); pdata->num_chipselect = 1; pdata->enable_dma = true; pdata->dma_burst_size = 1; @@ -1602,6 +1602,11 @@ static int pxa2xx_spi_fw_translate_cs(struct spi_controller *controller, return cs; } +static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi) +{ + return MAX_DMA_LEN; +} + static int pxa2xx_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1707,6 +1712,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) } else { controller->can_dma = pxa2xx_spi_can_dma; controller->max_dma_len = MAX_DMA_LEN; + controller->max_transfer_size = + pxa2xx_spi_max_dma_transfer_size; } } diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 2f559e531100..dd3434a407ea 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -932,11 +932,11 @@ static int spi_qup_init_dma(struct spi_master *master, resource_size_t base) int ret; /* allocate dma resources, if available */ - master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + master->dma_rx = dma_request_chan(dev, "rx"); if (IS_ERR(master->dma_rx)) return PTR_ERR(master->dma_rx); - master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + master->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(master->dma_tx)) { ret = PTR_ERR(master->dma_tx); goto err_tx; diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 15f5723d9f95..7222c7689c3c 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1257,9 +1257,9 @@ static int rspi_probe(struct platform_device *pdev) ctlr->flags = ops->flags; ctlr->dev.of_node = pdev->dev.of_node; - ret = platform_get_irq_byname(pdev, "rx"); + ret = platform_get_irq_byname_optional(pdev, "rx"); if (ret < 0) { - ret = platform_get_irq_byname(pdev, "mux"); + ret = platform_get_irq_byname_optional(pdev, "mux"); if (ret < 0) ret = platform_get_irq(pdev, 0); if (ret >= 0) @@ -1270,10 +1270,6 @@ static int rspi_probe(struct platform_device *pdev) if (ret >= 0) rspi->tx_irq = ret; } - if (ret < 0) { - dev_err(&pdev->dev, "platform_get_irq error\n"); - goto error2; - } if (rspi->rx_irq == rspi->tx_irq) { /* Single multiplexed interrupt */ diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 7b7151ec14c8..cf67ea60dc0e 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1154,15 +1154,13 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) if (!is_polling(sdd)) { /* Acquire DMA channels */ - sdd->rx_dma.ch = dma_request_slave_channel_reason(&pdev->dev, - "rx"); + sdd->rx_dma.ch = dma_request_chan(&pdev->dev, "rx"); if (IS_ERR(sdd->rx_dma.ch)) { dev_err(&pdev->dev, "Failed to get RX DMA channel\n"); ret = PTR_ERR(sdd->rx_dma.ch); goto err_disable_io_clk; } - sdd->tx_dma.ch = dma_request_slave_channel_reason(&pdev->dev, - "tx"); + sdd->tx_dma.ch = dma_request_chan(&pdev->dev, "tx"); if (IS_ERR(sdd->tx_dma.ch)) { dev_err(&pdev->dev, "Failed to get TX DMA channel\n"); ret = PTR_ERR(sdd->tx_dma.ch); diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c index 11acddc83304..5497eeb3bf3e 100644 --- a/drivers/spi/spi-sc18is602.c +++ b/drivers/spi/spi-sc18is602.c @@ -211,8 +211,7 @@ static int sc18is602_transfer_one(struct spi_master *master, } status = 0; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); } m->status = status; spi_finalize_current_message(master); diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 7f73f91d412a..a62034e2a7cb 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -190,8 +190,7 @@ static int hspi_transfer_one_message(struct spi_controller *ctlr, msg->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (cs_change) { ndelay(nsecs); diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 35254bdc42c4..f7c1e20432e0 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -357,14 +357,14 @@ static int sifive_spi_probe(struct platform_device *pdev) if (!cs_bits) { dev_err(&pdev->dev, "Could not auto probe CS lines\n"); ret = -EINVAL; - goto put_master; + goto disable_clk; } num_cs = ilog2(cs_bits) + 1; if (num_cs > SIFIVE_SPI_MAX_CS) { dev_err(&pdev->dev, "Invalid number of spi slaves\n"); ret = -EINVAL; - goto put_master; + goto disable_clk; } /* Define our master */ @@ -393,7 +393,7 @@ static int sifive_spi_probe(struct platform_device *pdev) dev_name(&pdev->dev), spi); if (ret) { dev_err(&pdev->dev, "Unable to bind to interrupt\n"); - goto put_master; + goto disable_clk; } dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n", @@ -402,11 +402,13 @@ static int sifive_spi_probe(struct platform_device *pdev) ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "spi_register_master failed\n"); - goto put_master; + goto disable_clk; } return 0; +disable_clk: + clk_disable_unprepare(spi->clk); put_master: spi_master_put(master); @@ -420,6 +422,7 @@ static int sifive_spi_remove(struct platform_device *pdev) /* Disable all the interrupts just in case */ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); + clk_disable_unprepare(spi->clk); return 0; } diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index 61bc43b0fe57..44edaa360405 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -368,7 +368,6 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) { struct spi_controller *ctlr; struct mtk_spi_slave *mdata; - struct resource *res; int irq, ret; ctlr = spi_alloc_slave(&pdev->dev, sizeof(*mdata)); @@ -392,17 +391,8 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctlr); init_completion(&mdata->xfer_done); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENODEV; - dev_err(&pdev->dev, "failed to determine base address\n"); - goto err_put_ctlr; - } - mdata->dev = &pdev->dev; - - mdata->base = devm_ioremap_resource(&pdev->dev, res); + mdata->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mdata->base)) { ret = PTR_ERR(mdata->base); goto err_put_ctlr; diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 9a051286f120..87dadb6b8ebf 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -77,6 +77,7 @@ /* Bits definitions for register REG_WDG_CTRL */ #define BIT_WDG_RUN BIT(1) +#define BIT_WDG_NEW BIT(2) #define BIT_WDG_RST BIT(3) /* Registers definitions for PMIC */ @@ -383,6 +384,10 @@ static int sprd_adi_restart_handler(struct notifier_block *this, /* Unlock the watchdog */ sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, WDG_UNLOCK_KEY); + sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val); + val |= BIT_WDG_NEW; + sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val); + /* Load the watchdog timeout value, 50ms is always enough. */ sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_LOW, WDG_LOAD_VAL & WDG_LOAD_MASK); @@ -393,6 +398,9 @@ static int sprd_adi_restart_handler(struct notifier_block *this, val |= BIT_WDG_RUN | BIT_WDG_RST; sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val); + /* Lock the watchdog */ + sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, ~WDG_UNLOCK_KEY); + mdelay(1000); dev_emerg(sadi->dev, "Unable to restart system\n"); diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c index 8c9021b7f7a9..2ee1feb41681 100644 --- a/drivers/spi/spi-sprd.c +++ b/drivers/spi/spi-sprd.c @@ -669,11 +669,15 @@ static void sprd_spi_set_speed(struct sprd_spi *ss, u32 speed_hz) writel_relaxed(clk_div, ss->base + SPRD_SPI_CLKD); } -static void sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t) +static int sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t) { + struct spi_delay *d = &t->word_delay; u16 word_delay, interval; u32 val; + if (d->unit != SPI_DELAY_UNIT_SCK) + return -EINVAL; + val = readl_relaxed(ss->base + SPRD_SPI_CTL7); val &= ~(SPRD_SPI_SCK_REV | SPRD_SPI_NG_TX | SPRD_SPI_NG_RX); /* Set default chip selection, clock phase and clock polarity */ @@ -686,7 +690,7 @@ static void sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t) * formula as below per datasheet: * interval time (source clock cycles) = interval * 4 + 10. */ - word_delay = clamp_t(u16, t->word_delay, SPRD_SPI_MIN_DELAY_CYCLE, + word_delay = clamp_t(u16, d->value, SPRD_SPI_MIN_DELAY_CYCLE, SPRD_SPI_MAX_DELAY_CYCLE); interval = DIV_ROUND_UP(word_delay - 10, 4); ss->word_delay = interval * 4 + 10; @@ -711,6 +715,8 @@ static void sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t) val &= ~SPRD_SPI_DATA_LINE2_EN; writel_relaxed(val, ss->base + SPRD_SPI_CTL7); + + return 0; } static int sprd_spi_setup_transfer(struct spi_device *sdev, @@ -719,13 +725,16 @@ static int sprd_spi_setup_transfer(struct spi_device *sdev, struct sprd_spi *ss = spi_controller_get_devdata(sdev->controller); u8 bits_per_word = t->bits_per_word; u32 val, mode = 0; + int ret; ss->len = t->len; ss->tx_buf = t->tx_buf; ss->rx_buf = t->rx_buf; ss->hw_mode = sdev->mode; - sprd_spi_init_hw(ss, t); + ret = sprd_spi_init_hw(ss, t); + if (ret) + return ret; /* Set tansfer speed and valid bits */ sprd_spi_set_speed(ss, t->speed_hz); diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index 0c24c494f386..77d26d64541a 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -381,6 +381,7 @@ static int spi_st_probe(struct platform_device *pdev) return 0; clk_disable: + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(spi_st->clk); put_master: spi_master_put(master); @@ -392,6 +393,8 @@ static int spi_st_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct spi_st *spi_st = spi_master_get_devdata(master); + pm_runtime_disable(&pdev->dev); + clk_disable_unprepare(spi_st->clk); pinctrl_pm_select_sleep_state(&pdev->dev); diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 9ac6f9fe13cf..4e726929bb4f 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -528,7 +528,6 @@ static void stm32_qspi_release(struct stm32_qspi *qspi) stm32_qspi_dma_free(qspi); mutex_destroy(&qspi->lock); clk_disable_unprepare(qspi->clk); - spi_master_put(qspi->ctrl); } static int stm32_qspi_probe(struct platform_device *pdev) @@ -626,6 +625,8 @@ static int stm32_qspi_probe(struct platform_device *pdev) err: stm32_qspi_release(qspi); + spi_master_put(qspi->ctrl); + return ret; } diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 39374c2edcf3..fc40ab146c86 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -666,8 +666,7 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, dma_addr_t dma_phys; int ret; - dma_chan = dma_request_slave_channel_reason(tspi->dev, - dma_to_memory ? "rx" : "tx"); + dma_chan = dma_request_chan(tspi->dev, dma_to_memory ? "rx" : "tx"); if (IS_ERR(dma_chan)) { ret = PTR_ERR(dma_chan); if (ret != -EPROBE_DEFER) @@ -723,15 +722,31 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi, dma_release_channel(dma_chan); } -static void tegra_spi_set_hw_cs_timing(struct spi_device *spi, u8 setup_dly, - u8 hold_dly, u8 inactive_dly) +static int tegra_spi_set_hw_cs_timing(struct spi_device *spi, + struct spi_delay *setup, + struct spi_delay *hold, + struct spi_delay *inactive) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); + u8 setup_dly, hold_dly, inactive_dly; u32 setup_hold; u32 spi_cs_timing; u32 inactive_cycles; u8 cs_state; + if ((setup && setup->unit != SPI_DELAY_UNIT_SCK) || + (hold && hold->unit != SPI_DELAY_UNIT_SCK) || + (inactive && inactive->unit != SPI_DELAY_UNIT_SCK)) { + dev_err(&spi->dev, + "Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n", + SPI_DELAY_UNIT_SCK); + return -EINVAL; + } + + setup_dly = setup ? setup->value : 0; + hold_dly = hold ? hold->value : 0; + inactive_dly = inactive ? inactive->value : 0; + setup_dly = min_t(u8, setup_dly, MAX_SETUP_HOLD_CYCLES); hold_dly = min_t(u8, hold_dly, MAX_SETUP_HOLD_CYCLES); if (setup_dly && hold_dly) { @@ -758,6 +773,8 @@ static void tegra_spi_set_hw_cs_timing(struct spi_device *spi, u8 setup_dly, tspi->spi_cs_timing2 = spi_cs_timing; tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING2); } + + return 0; } static u32 tegra_spi_setup_transfer_one(struct spi_device *spi, @@ -984,17 +1001,6 @@ static int tegra_spi_setup(struct spi_device *spi) return 0; } -static void tegra_spi_transfer_delay(int delay) -{ - if (!delay) - return; - - if (delay >= 1000) - mdelay(delay / 1000); - - udelay(delay % 1000); -} - static void tegra_spi_transfer_end(struct spi_device *spi) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); @@ -1098,7 +1104,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, complete_xfer: if (ret < 0 || skip) { tegra_spi_transfer_end(spi); - tegra_spi_transfer_delay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); goto exit; } else if (list_is_last(&xfer->transfer_list, &msg->transfers)) { @@ -1106,11 +1112,11 @@ complete_xfer: tspi->cs_control = spi; else { tegra_spi_transfer_end(spi); - tegra_spi_transfer_delay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); } } else if (xfer->cs_change) { tegra_spi_transfer_end(spi); - tegra_spi_transfer_delay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); } } diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index a841a7250d14..514429379206 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -341,10 +341,11 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master, goto exit; } msg->actual_length += xfer->len; - if (xfer->cs_change && xfer->delay_usecs) { + if (xfer->cs_change && + (xfer->delay_usecs || xfer->delay.value)) { tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND); - udelay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); } } ret = 0; diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 111fffc91435..7f4d932dade7 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -599,8 +599,7 @@ static int tegra_slink_init_dma_param(struct tegra_slink_data *tspi, int ret; struct dma_slave_config dma_sconfig; - dma_chan = dma_request_slave_channel_reason(tspi->dev, - dma_to_memory ? "rx" : "tx"); + dma_chan = dma_request_chan(tspi->dev, dma_to_memory ? "rx" : "tx"); if (IS_ERR(dma_chan)) { ret = PTR_ERR(dma_chan); if (ret != -EPROBE_DEFER) @@ -1073,7 +1072,7 @@ static int tegra_slink_probe(struct platform_device *pdev) ret = clk_enable(tspi->clk); if (ret < 0) { dev_err(&pdev->dev, "Clock enable failed %d\n", ret); - goto exit_free_master; + goto exit_clk_unprepare; } spi_irq = platform_get_irq(pdev, 0); @@ -1146,6 +1145,8 @@ exit_free_irq: free_irq(spi_irq, tspi); exit_clk_disable: clk_disable(tspi->clk); +exit_clk_unprepare: + clk_unprepare(tspi->clk); exit_free_master: spi_master_put(master); return ret; @@ -1159,6 +1160,7 @@ static int tegra_slink_remove(struct platform_device *pdev) free_irq(tspi->irq, tspi); clk_disable(tspi->clk); + clk_unprepare(tspi->clk); if (tspi->tx_dma_chan) tegra_slink_deinit_dma_param(tspi, false); diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index f88cbb94ce12..223353fa2d8a 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1229,12 +1229,7 @@ static void pch_spi_process_messages(struct work_struct *pwork) "%s:data->current_msg->actual_length=%d\n", __func__, data->current_msg->actual_length); - /* check for delay */ - if (data->cur_trans->delay_usecs) { - dev_dbg(&data->master->dev, "%s:delay in usec=%d\n", - __func__, data->cur_trans->delay_usecs); - udelay(data->cur_trans->delay_usecs); - } + spi_transfer_delay_exec(data->cur_trans); spin_lock(&data->lock); diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index 51759d3fd45f..3606232f190f 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -26,7 +26,8 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/gpio.h> +#include <linux/gpio/machine.h> +#include <linux/gpio/consumer.h> #define SPI_FIFO_SIZE 4 @@ -79,7 +80,7 @@ struct txx9spi { void __iomem *membase; int baseclk; struct clk *clk; - int last_chipselect; + struct gpio_desc *last_chipselect; int last_chipselect_val; }; @@ -95,20 +96,22 @@ static void txx9spi_wr(struct txx9spi *c, u32 val, int reg) static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c, int on, unsigned int cs_delay) { - int val = (spi->mode & SPI_CS_HIGH) ? on : !on; - + /* + * The GPIO descriptor will track polarity inversion inside + * gpiolib. + */ if (on) { /* deselect the chip with cs_change hint in last transfer */ - if (c->last_chipselect >= 0) - gpio_set_value(c->last_chipselect, + if (c->last_chipselect) + gpiod_set_value(c->last_chipselect, !c->last_chipselect_val); - c->last_chipselect = spi->chip_select; - c->last_chipselect_val = val; + c->last_chipselect = spi->cs_gpiod; + c->last_chipselect_val = on; } else { - c->last_chipselect = -1; + c->last_chipselect = NULL; ndelay(cs_delay); /* CS Hold Time */ } - gpio_set_value(spi->chip_select, val); + gpiod_set_value(spi->cs_gpiod, on); ndelay(cs_delay); /* CS Setup Time / CS Recovery Time */ } @@ -119,12 +122,6 @@ static int txx9spi_setup(struct spi_device *spi) if (!spi->max_speed_hz) return -EINVAL; - if (gpio_direction_output(spi->chip_select, - !(spi->mode & SPI_CS_HIGH))) { - dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n"); - return -EINVAL; - } - /* deselect chip */ spin_lock(&c->lock); txx9spi_cs_func(spi, c, 0, (NSEC_PER_SEC / 2) / spi->max_speed_hz); @@ -248,8 +245,7 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m) len -= count * wsize; } m->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (!cs_change) continue; @@ -320,6 +316,47 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m) return 0; } +/* + * Chip select uses GPIO only, further the driver is using the chip select + * numer (from the device tree "reg" property, and this can only come from + * device tree since this i MIPS and there is no way to pass platform data) as + * the GPIO number. As the platform has only one GPIO controller (the txx9 GPIO + * chip) it is thus using the chip select number as an offset into that chip. + * This chip has a maximum of 16 GPIOs 0..15 and this is what all platforms + * register. + * + * We modernized this behaviour by explicitly converting that offset to an + * offset on the GPIO chip using a GPIO descriptor machine table of the same + * size as the txx9 GPIO chip with a 1-to-1 mapping of chip select to GPIO + * offset. + * + * This is admittedly a hack, but it is countering the hack of using "reg" to + * contain a GPIO offset when it should be using "cs-gpios" as the SPI bindings + * state. + */ +static struct gpiod_lookup_table txx9spi_cs_gpio_table = { + .dev_id = "spi0", + .table = { + GPIO_LOOKUP_IDX("TXx9", 0, "cs", 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 1, "cs", 1, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 2, "cs", 2, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 3, "cs", 3, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 4, "cs", 4, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 5, "cs", 5, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 6, "cs", 6, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 7, "cs", 7, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 8, "cs", 8, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 9, "cs", 9, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 10, "cs", 10, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 11, "cs", 11, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 12, "cs", 12, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 13, "cs", 13, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 14, "cs", 14, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 15, "cs", 15, GPIO_ACTIVE_LOW), + { }, + }, +}; + static int txx9spi_probe(struct platform_device *dev) { struct spi_master *master; @@ -373,12 +410,14 @@ static int txx9spi_probe(struct platform_device *dev) if (ret) goto exit; - c->last_chipselect = -1; + c->last_chipselect = NULL; dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n", (unsigned long long)res->start, irq, (c->baseclk + 500000) / 1000000); + gpiod_add_lookup_table(&txx9spi_cs_gpio_table); + /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA; @@ -387,6 +426,7 @@ static int txx9spi_probe(struct platform_device *dev) master->transfer = txx9spi_transfer; master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */ master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); + master->use_gpio_descriptors = true; ret = devm_spi_register_master(&dev->dev, master); if (ret) diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c index a3496c46cc1b..1d9b3f03d986 100644 --- a/drivers/spi/spi-xcomm.c +++ b/drivers/spi/spi-xcomm.c @@ -188,8 +188,7 @@ static int spi_xcomm_transfer_one(struct spi_master *master, } status = 0; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); is_first = false; } diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index d5f9d5fbb3e8..8dd2bb99cb4d 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -391,7 +391,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) struct xilinx_spi *xspi; struct xspi_platform_data *pdata; struct resource *res; - int ret, num_cs = 0, bits_per_word = 8; + int ret, num_cs = 0, bits_per_word; struct spi_master *master; u32 tmp; u8 i; @@ -403,6 +403,11 @@ static int xilinx_spi_probe(struct platform_device *pdev) } else { of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits", &num_cs); + ret = of_property_read_u32(pdev->dev.of_node, + "xlnx,num-transfer-bits", + &bits_per_word); + if (ret) + bits_per_word = 8; } if (!num_cs) { diff --git a/drivers/spi/spi-xtensa-xtfpga.c b/drivers/spi/spi-xtensa-xtfpga.c index 86516eb1e143..fc2b5eb7d614 100644 --- a/drivers/spi/spi-xtensa-xtfpga.c +++ b/drivers/spi/spi-xtensa-xtfpga.c @@ -80,7 +80,6 @@ static void xtfpga_spi_chipselect(struct spi_device *spi, int is_on) static int xtfpga_spi_probe(struct platform_device *pdev) { struct xtfpga_spi *xspi; - struct resource *mem; int ret; struct spi_master *master; @@ -97,14 +96,7 @@ static int xtfpga_spi_probe(struct platform_device *pdev) xspi->bitbang.master = master; xspi->bitbang.chipselect = xtfpga_spi_chipselect; xspi->bitbang.txrx_word[SPI_MODE_0] = xtfpga_spi_txrx_word; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "No memory resource\n"); - ret = -ENODEV; - goto err; - } - xspi->regs = devm_ioremap_resource(&pdev->dev, mem); + xspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xspi->regs)) { ret = PTR_ERR(xspi->regs); goto err; diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index 5cf6993ddce5..17641157354d 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -7,7 +7,6 @@ #include <linux/clk.h> #include <linux/delay.h> -#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> @@ -51,7 +50,6 @@ #define ZYNQ_QSPI_CONFIG_BDRATE_MASK GENMASK(5, 3) /* Baud Rate Mask */ #define ZYNQ_QSPI_CONFIG_CPHA_MASK BIT(2) /* Clock Phase Control */ #define ZYNQ_QSPI_CONFIG_CPOL_MASK BIT(1) /* Clock Polarity Control */ -#define ZYNQ_QSPI_CONFIG_SSCTRL_MASK BIT(10) /* Slave Select Mask */ #define ZYNQ_QSPI_CONFIG_FWIDTH_MASK GENMASK(7, 6) /* FIFO width */ #define ZYNQ_QSPI_CONFIG_MSTREN_MASK BIT(0) /* Master Mode */ @@ -61,9 +59,9 @@ * These are the values used in the calculation of baud rate divisor and * setting the slave select. */ -#define ZYNQ_QSPI_BAUD_DIV_MAX GENMASK(2, 0) /* Baud rate maximum */ -#define ZYNQ_QSPI_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift in CR */ -#define ZYNQ_QSPI_SS_SHIFT 10 /* Slave Select field shift in CR */ +#define ZYNQ_QSPI_CONFIG_BAUD_DIV_MAX GENMASK(2, 0) /* Baud rate maximum */ +#define ZYNQ_QSPI_CONFIG_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift */ +#define ZYNQ_QSPI_CONFIG_PCS BIT(10) /* Peripheral Chip Select */ /* * QSPI Interrupt Registers bit Masks @@ -99,9 +97,9 @@ * It is named Linear Configuration but it controls other modes when not in * linear mode also. */ -#define ZYNQ_QSPI_LCFG_TWO_MEM_MASK BIT(30) /* LQSPI Two memories Mask */ -#define ZYNQ_QSPI_LCFG_SEP_BUS_MASK BIT(29) /* LQSPI Separate bus Mask */ -#define ZYNQ_QSPI_LCFG_U_PAGE_MASK BIT(28) /* LQSPI Upper Page Mask */ +#define ZYNQ_QSPI_LCFG_TWO_MEM BIT(30) /* LQSPI Two memories */ +#define ZYNQ_QSPI_LCFG_SEP_BUS BIT(29) /* LQSPI Separate bus */ +#define ZYNQ_QSPI_LCFG_U_PAGE BIT(28) /* LQSPI Upper Page */ #define ZYNQ_QSPI_LCFG_DUMMY_SHIFT 8 @@ -116,8 +114,8 @@ */ #define ZYNQ_QSPI_MODEBITS (SPI_CPOL | SPI_CPHA) -/* Default number of chip selects */ -#define ZYNQ_QSPI_DEFAULT_NUM_CS 1 +/* Maximum number of chip selects */ +#define ZYNQ_QSPI_MAX_NUM_CS 2 /** * struct zynq_qspi - Defines qspi driver instance @@ -161,6 +159,7 @@ static inline void zynq_qspi_write(struct zynq_qspi *xqspi, u32 offset, /** * zynq_qspi_init_hw - Initialize the hardware * @xqspi: Pointer to the zynq_qspi structure + * @num_cs: Number of connected CS (to enable dual memories if needed) * * The default settings of the QSPI controller's configurable parameters on * reset are @@ -178,7 +177,7 @@ static inline void zynq_qspi_write(struct zynq_qspi *xqspi, u32 offset, * - Set the little endian mode of TX FIFO and * - Enable the QSPI controller */ -static void zynq_qspi_init_hw(struct zynq_qspi *xqspi) +static void zynq_qspi_init_hw(struct zynq_qspi *xqspi, unsigned int num_cs) { u32 config_reg; @@ -186,7 +185,12 @@ static void zynq_qspi_init_hw(struct zynq_qspi *xqspi) zynq_qspi_write(xqspi, ZYNQ_QSPI_IDIS_OFFSET, ZYNQ_QSPI_IXR_ALL_MASK); /* Disable linear mode as the boot loader may have used it */ - zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, 0); + config_reg = 0; + /* At the same time, enable dual mode if more than 1 CS is available */ + if (num_cs > 1) + config_reg |= ZYNQ_QSPI_LCFG_TWO_MEM; + + zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, config_reg); /* Clear the RX FIFO */ while (zynq_qspi_read(xqspi, ZYNQ_QSPI_STATUS_OFFSET) & @@ -284,21 +288,28 @@ static void zynq_qspi_txfifo_op(struct zynq_qspi *xqspi, unsigned int size) */ static void zynq_qspi_chipselect(struct spi_device *spi, bool assert) { - struct spi_controller *ctrl = spi->master; - struct zynq_qspi *xqspi = spi_controller_get_devdata(ctrl); + struct spi_controller *ctlr = spi->master; + struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr); u32 config_reg; - config_reg = zynq_qspi_read(xqspi, ZYNQ_QSPI_CONFIG_OFFSET); - if (assert) { - /* Select the slave */ - config_reg &= ~ZYNQ_QSPI_CONFIG_SSCTRL_MASK; - config_reg |= (((~(BIT(spi->chip_select))) << - ZYNQ_QSPI_SS_SHIFT) & - ZYNQ_QSPI_CONFIG_SSCTRL_MASK); - } else { - config_reg |= ZYNQ_QSPI_CONFIG_SSCTRL_MASK; + /* Select the lower (CS0) or upper (CS1) memory */ + if (ctlr->num_chipselect > 1) { + config_reg = zynq_qspi_read(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET); + if (!spi->chip_select) + config_reg &= ~ZYNQ_QSPI_LCFG_U_PAGE; + else + config_reg |= ZYNQ_QSPI_LCFG_U_PAGE; + + zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, config_reg); } + /* Ground the line to assert the CS */ + config_reg = zynq_qspi_read(xqspi, ZYNQ_QSPI_CONFIG_OFFSET); + if (assert) + config_reg &= ~ZYNQ_QSPI_CONFIG_PCS; + else + config_reg |= ZYNQ_QSPI_CONFIG_PCS; + zynq_qspi_write(xqspi, ZYNQ_QSPI_CONFIG_OFFSET, config_reg); } @@ -332,7 +343,7 @@ static int zynq_qspi_config_op(struct zynq_qspi *xqspi, struct spi_device *spi) * ---------------- * 111 - divide by 256 */ - while ((baud_rate_val < ZYNQ_QSPI_BAUD_DIV_MAX) && + while ((baud_rate_val < ZYNQ_QSPI_CONFIG_BAUD_DIV_MAX) && (clk_get_rate(xqspi->refclk) / (2 << baud_rate_val)) > spi->max_speed_hz) baud_rate_val++; @@ -348,7 +359,7 @@ static int zynq_qspi_config_op(struct zynq_qspi *xqspi, struct spi_device *spi) config_reg |= ZYNQ_QSPI_CONFIG_CPOL_MASK; config_reg &= ~ZYNQ_QSPI_CONFIG_BDRATE_MASK; - config_reg |= (baud_rate_val << ZYNQ_QSPI_BAUD_DIV_SHIFT); + config_reg |= (baud_rate_val << ZYNQ_QSPI_CONFIG_BAUD_DIV_SHIFT); zynq_qspi_write(xqspi, ZYNQ_QSPI_CONFIG_OFFSET, config_reg); return 0; @@ -365,10 +376,10 @@ static int zynq_qspi_config_op(struct zynq_qspi *xqspi, struct spi_device *spi) */ static int zynq_qspi_setup_op(struct spi_device *spi) { - struct spi_controller *ctrl = spi->master; - struct zynq_qspi *qspi = spi_controller_get_devdata(ctrl); + struct spi_controller *ctlr = spi->master; + struct zynq_qspi *qspi = spi_controller_get_devdata(ctlr); - if (ctrl->busy) + if (ctlr->busy) return -EBUSY; clk_enable(qspi->refclk); @@ -663,9 +674,6 @@ static int zynq_qspi_probe(struct platform_device *pdev) goto clk_dis_pclk; } - /* QSPI controller initializations */ - zynq_qspi_init_hw(xqspi); - xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq <= 0) { ret = -ENXIO; @@ -681,10 +689,14 @@ static int zynq_qspi_probe(struct platform_device *pdev) ret = of_property_read_u32(np, "num-cs", &num_cs); - if (ret < 0) - ctlr->num_chipselect = ZYNQ_QSPI_DEFAULT_NUM_CS; - else + if (ret < 0) { + ctlr->num_chipselect = 1; + } else if (num_cs > ZYNQ_QSPI_MAX_NUM_CS) { + dev_err(&pdev->dev, "only 2 chip selects are available\n"); + goto remove_master; + } else { ctlr->num_chipselect = num_cs; + } ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; @@ -692,6 +704,10 @@ static int zynq_qspi_probe(struct platform_device *pdev) ctlr->setup = zynq_qspi_setup_op; ctlr->max_speed_hz = clk_get_rate(xqspi->refclk) / 2; ctlr->dev.of_node = np; + + /* QSPI controller initializations */ + zynq_qspi_init_hw(xqspi, ctlr->num_chipselect); + ret = devm_spi_register_controller(&pdev->dev, ctlr); if (ret) { dev_err(&pdev->dev, "spi_register_master failed\n"); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9bb36c32cbf9..5e4c4532f7f3 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -92,7 +92,7 @@ static ssize_t driver_override_store(struct device *dev, if (len) { spi->driver_override = driver_override; } else { - /* Emptry string, disable driver override */ + /* Empty string, disable driver override */ spi->driver_override = NULL; kfree(driver_override); } @@ -469,7 +469,7 @@ static LIST_HEAD(board_list); static LIST_HEAD(spi_controller_list); /* - * Used to protect add/del opertion for board_info list and + * Used to protect add/del operation for board_info list and * spi_controller list, and their matching process * also used to protect object of type struct idr */ @@ -775,6 +775,15 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) static void spi_set_cs(struct spi_device *spi, bool enable) { + bool enable1 = enable; + + if (!spi->controller->set_cs_timing) { + if (enable1) + spi_delay_exec(&spi->controller->cs_setup, NULL); + else + spi_delay_exec(&spi->controller->cs_hold, NULL); + } + if (spi->mode & SPI_CS_HIGH) enable = !enable; @@ -800,6 +809,11 @@ static void spi_set_cs(struct spi_device *spi, bool enable) } else if (spi->controller->set_cs) { spi->controller->set_cs(spi, !enable); } + + if (!spi->controller->set_cs_timing) { + if (!enable1) + spi_delay_exec(&spi->controller->cs_inactive, NULL); + } } #ifdef CONFIG_HAS_DMA @@ -1106,42 +1120,79 @@ static void _spi_transfer_delay_ns(u32 ns) } } -static void _spi_transfer_cs_change_delay(struct spi_message *msg, - struct spi_transfer *xfer) +int spi_delay_to_ns(struct spi_delay *_delay, struct spi_transfer *xfer) { - u32 delay = xfer->cs_change_delay; - u32 unit = xfer->cs_change_delay_unit; + u32 delay = _delay->value; + u32 unit = _delay->unit; u32 hz; - /* return early on "fast" mode - for everything but USECS */ - if (!delay && unit != SPI_DELAY_UNIT_USECS) - return; + if (!delay) + return 0; switch (unit) { case SPI_DELAY_UNIT_USECS: - /* for compatibility use default of 10us */ - if (!delay) - delay = 10000; - else - delay *= 1000; + delay *= 1000; break; case SPI_DELAY_UNIT_NSECS: /* nothing to do here */ break; case SPI_DELAY_UNIT_SCK: + /* clock cycles need to be obtained from spi_transfer */ + if (!xfer) + return -EINVAL; /* if there is no effective speed know, then approximate * by underestimating with half the requested hz */ hz = xfer->effective_speed_hz ?: xfer->speed_hz / 2; + if (!hz) + return -EINVAL; delay *= DIV_ROUND_UP(1000000000, hz); break; default: + return -EINVAL; + } + + return delay; +} +EXPORT_SYMBOL_GPL(spi_delay_to_ns); + +int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer) +{ + int delay; + + if (!_delay) + return -EINVAL; + + delay = spi_delay_to_ns(_delay, xfer); + if (delay < 0) + return delay; + + _spi_transfer_delay_ns(delay); + + return 0; +} +EXPORT_SYMBOL_GPL(spi_delay_exec); + +static void _spi_transfer_cs_change_delay(struct spi_message *msg, + struct spi_transfer *xfer) +{ + u32 delay = xfer->cs_change_delay.value; + u32 unit = xfer->cs_change_delay.unit; + int ret; + + /* return early on "fast" mode - for everything but USECS */ + if (!delay) { + if (unit == SPI_DELAY_UNIT_USECS) + _spi_transfer_delay_ns(10000); + return; + } + + ret = spi_delay_exec(&xfer->cs_change_delay, xfer); + if (ret) { dev_err_once(&msg->spi->dev, "Use of unsupported delay unit %i, using default of 10us\n", - xfer->cs_change_delay_unit); - delay = 10000; + unit); + _spi_transfer_delay_ns(10000); } - /* now sleep for the requested amount of time */ - _spi_transfer_delay_ns(delay); } /* @@ -1212,8 +1263,7 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, if (msg->status != -EINPROGRESS) goto out; - if (xfer->delay_usecs) - _spi_transfer_delay_ns(xfer->delay_usecs * 1000); + spi_transfer_delay_exec(xfer); if (xfer->cs_change) { if (list_is_last(&xfer->transfer_list, @@ -1830,15 +1880,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, spi->mode |= SPI_3WIRE; if (of_property_read_bool(nc, "spi-lsb-first")) spi->mode |= SPI_LSB_FIRST; - - /* - * For descriptors associated with the device, polarity inversion is - * handled in the gpiolib, so all chip selects are "active high" in - * the logical sense, the gpiolib will invert the line if need be. - */ - if (ctlr->use_gpio_descriptors) - spi->mode |= SPI_CS_HIGH; - else if (of_property_read_bool(nc, "spi-cs-high")) + if (of_property_read_bool(nc, "spi-cs-high")) spi->mode |= SPI_CS_HIGH; /* Device DUAL/QUAD mode */ @@ -1902,6 +1944,15 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, } spi->chip_select = value; + /* + * For descriptors associated with the device, polarity inversion is + * handled in the gpiolib, so all gpio chip selects are "active high" + * in the logical sense, the gpiolib will invert the line if need be. + */ + if ((ctlr->use_gpio_descriptors) && ctlr->cs_gpiods && + ctlr->cs_gpiods[spi->chip_select]) + spi->mode |= SPI_CS_HIGH; + /* Device speed */ rc = of_property_read_u32(nc, "spi-max-frequency", &value); if (rc) { @@ -2990,10 +3041,11 @@ struct spi_replaced_transfers *spi_replace_transfers( /* add to list */ list_add(&xfer->transfer_list, rxfer->replaced_after); - /* clear cs_change and delay_usecs for all but the last */ + /* clear cs_change and delay for all but the last */ if (i) { xfer->cs_change = false; xfer->delay_usecs = 0; + xfer->delay.value = 0; } } @@ -3210,7 +3262,29 @@ int spi_setup(struct spi_device *spi) if (spi->controller->setup) status = spi->controller->setup(spi); - spi_set_cs(spi, false); + if (spi->controller->auto_runtime_pm && spi->controller->set_cs) { + status = pm_runtime_get_sync(spi->controller->dev.parent); + if (status < 0) { + pm_runtime_put_noidle(spi->controller->dev.parent); + dev_err(&spi->controller->dev, "Failed to power device: %d\n", + status); + return status; + } + + /* + * We do not want to return positive value from pm_runtime_get, + * there are many instances of devices calling spi_setup() and + * checking for a non-zero return value instead of a negative + * return value. + */ + status = 0; + + spi_set_cs(spi, false); + pm_runtime_mark_last_busy(spi->controller->dev.parent); + pm_runtime_put_autosuspend(spi->controller->dev.parent); + } else { + spi_set_cs(spi, false); + } if (spi->rt && !spi->controller->rt) { spi->controller->rt = true; @@ -3233,18 +3307,71 @@ EXPORT_SYMBOL_GPL(spi_setup); /** * spi_set_cs_timing - configure CS setup, hold, and inactive delays * @spi: the device that requires specific CS timing configuration - * @setup: CS setup time in terms of clock count - * @hold: CS hold time in terms of clock count - * @inactive_dly: CS inactive delay between transfers in terms of clock count + * @setup: CS setup time specified via @spi_delay + * @hold: CS hold time specified via @spi_delay + * @inactive: CS inactive delay between transfers specified via @spi_delay + * + * Return: zero on success, else a negative error code. */ -void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold, - u8 inactive_dly) +int spi_set_cs_timing(struct spi_device *spi, struct spi_delay *setup, + struct spi_delay *hold, struct spi_delay *inactive) { + size_t len; + if (spi->controller->set_cs_timing) - spi->controller->set_cs_timing(spi, setup, hold, inactive_dly); + return spi->controller->set_cs_timing(spi, setup, hold, + inactive); + + if ((setup && setup->unit == SPI_DELAY_UNIT_SCK) || + (hold && hold->unit == SPI_DELAY_UNIT_SCK) || + (inactive && inactive->unit == SPI_DELAY_UNIT_SCK)) { + dev_err(&spi->dev, + "Clock-cycle delays for CS not supported in SW mode\n"); + return -ENOTSUPP; + } + + len = sizeof(struct spi_delay); + + /* copy delays to controller */ + if (setup) + memcpy(&spi->controller->cs_setup, setup, len); + else + memset(&spi->controller->cs_setup, 0, len); + + if (hold) + memcpy(&spi->controller->cs_hold, hold, len); + else + memset(&spi->controller->cs_hold, 0, len); + + if (inactive) + memcpy(&spi->controller->cs_inactive, inactive, len); + else + memset(&spi->controller->cs_inactive, 0, len); + + return 0; } EXPORT_SYMBOL_GPL(spi_set_cs_timing); +static int _spi_xfer_word_delay_update(struct spi_transfer *xfer, + struct spi_device *spi) +{ + int delay1, delay2; + + delay1 = spi_delay_to_ns(&xfer->word_delay, xfer); + if (delay1 < 0) + return delay1; + + delay2 = spi_delay_to_ns(&spi->word_delay, xfer); + if (delay2 < 0) + return delay2; + + if (delay1 < delay2) + memcpy(&xfer->word_delay, &spi->word_delay, + sizeof(xfer->word_delay)); + + return 0; +} + static int __spi_validate(struct spi_device *spi, struct spi_message *message) { struct spi_controller *ctlr = spi->controller; @@ -3380,8 +3507,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) return -EINVAL; } - if (xfer->word_delay_usecs < spi->word_delay_usecs) - xfer->word_delay_usecs = spi->word_delay_usecs; + if (_spi_xfer_word_delay_update(xfer, spi)) + return -EINVAL; } message->status = -EINPROGRESS; diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 255786f2e844..1e217e3e9486 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -265,9 +265,11 @@ static int spidev_message(struct spidev_data *spidev, k_tmp->tx_nbits = u_tmp->tx_nbits; k_tmp->rx_nbits = u_tmp->rx_nbits; k_tmp->bits_per_word = u_tmp->bits_per_word; - k_tmp->delay_usecs = u_tmp->delay_usecs; + k_tmp->delay.value = u_tmp->delay_usecs; + k_tmp->delay.unit = SPI_DELAY_UNIT_USECS; k_tmp->speed_hz = u_tmp->speed_hz; - k_tmp->word_delay_usecs = u_tmp->word_delay_usecs; + k_tmp->word_delay.value = u_tmp->word_delay_usecs; + k_tmp->word_delay.unit = SPI_DELAY_UNIT_USECS; if (!k_tmp->speed_hz) k_tmp->speed_hz = spidev->speed_hz; #ifdef VERBOSE @@ -627,6 +629,9 @@ static int spidev_release(struct inode *inode, struct file *filp) if (dofree) kfree(spidev); } +#ifdef CONFIG_SPI_SLAVE + spi_slave_abort(spidev->spi); +#endif mutex_unlock(&device_list_lock); return 0; diff --git a/include/linux/platform_data/spi-mt65xx.h b/include/linux/platform_data/spi-mt65xx.h index f0e6d6483e62..65fd5ffd257c 100644 --- a/include/linux/platform_data/spi-mt65xx.h +++ b/include/linux/platform_data/spi-mt65xx.h @@ -11,7 +11,6 @@ /* Board specific platform_data */ struct mtk_chip_config { - u32 cs_pol; u32 sample_sel; }; #endif diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h index a5d1837e4f35..6facf27865f9 100644 --- a/include/linux/pxa2xx_ssp.h +++ b/include/linux/pxa2xx_ssp.h @@ -206,7 +206,7 @@ enum pxa_ssp_type { }; struct ssp_device { - struct platform_device *pdev; + struct device *dev; struct list_head node; struct clk *clk; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 27f6b046cf92..98fe8663033a 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -91,6 +91,22 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, SPI_STATISTICS_ADD_TO_FIELD(stats, field, 1) /** + * struct spi_delay - SPI delay information + * @value: Value for the delay + * @unit: Unit for the delay + */ +struct spi_delay { +#define SPI_DELAY_UNIT_USECS 0 +#define SPI_DELAY_UNIT_NSECS 1 +#define SPI_DELAY_UNIT_SCK 2 + u16 value; + u8 unit; +}; + +extern int spi_delay_to_ns(struct spi_delay *_delay, struct spi_transfer *xfer); +extern int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer); + +/** * struct spi_device - Controller side proxy for an SPI slave device * @dev: Driver model representation of the device. * @controller: SPI controller used with the device. @@ -124,7 +140,7 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, * the spi_master. * @cs_gpiod: gpio descriptor of the chipselect line (optional, NULL when * not using a GPIO line) - * @word_delay_usecs: microsecond delay to be inserted between consecutive + * @word_delay: delay to be inserted between consecutive * words of a transfer * * @statistics: statistics for the spi_device @@ -174,7 +190,7 @@ struct spi_device { const char *driver_override; int cs_gpio; /* LEGACY: chip select gpio */ struct gpio_desc *cs_gpiod; /* chip select gpio desc */ - uint8_t word_delay_usecs; /* inter-word delay */ + struct spi_delay word_delay; /* inter-word delay */ /* the statistics */ struct spi_statistics statistics; @@ -391,6 +407,11 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * controller has native support for memory like operations. * @unprepare_message: undo any work done by prepare_message(). * @slave_abort: abort the ongoing transfer request on an SPI slave controller + * @cs_setup: delay to be introduced by the controller after CS is asserted + * @cs_hold: delay to be introduced by the controller before CS is deasserted + * @cs_inactive: delay to be introduced by the controller after CS is + * deasserted. If @cs_change_delay is used from @spi_transfer, then the + * two delays will be added up. * @cs_gpios: LEGACY: array of GPIO descs to use as chip select lines; one per * CS number. Any individual value may be -ENOENT for CS lines that * are not GPIOs (driven by the SPI controller itself). Use the cs_gpiods @@ -509,8 +530,8 @@ struct spi_controller { * to configure specific CS timing through spi_set_cs_timing() after * spi_setup(). */ - void (*set_cs_timing)(struct spi_device *spi, u8 setup_clk_cycles, - u8 hold_clk_cycles, u8 inactive_clk_cycles); + int (*set_cs_timing)(struct spi_device *spi, struct spi_delay *setup, + struct spi_delay *hold, struct spi_delay *inactive); /* bidirectional bulk transfers * @@ -594,6 +615,11 @@ struct spi_controller { /* Optimized handlers for SPI memory-like operations. */ const struct spi_controller_mem_ops *mem_ops; + /* CS delays */ + struct spi_delay cs_setup; + struct spi_delay cs_hold; + struct spi_delay cs_inactive; + /* gpio chip select */ int *cs_gpios; struct gpio_desc **cs_gpiods; @@ -763,13 +789,13 @@ extern void spi_res_release(struct spi_controller *ctlr, * @cs_change: affects chipselect after this transfer completes * @cs_change_delay: delay between cs deassert and assert when * @cs_change is set and @spi_transfer is not the last in @spi_message - * @cs_change_delay_unit: unit of cs_change_delay + * @delay: delay to be introduced after this transfer before + * (optionally) changing the chipselect status, then starting + * the next transfer or completing this @spi_message. * @delay_usecs: microseconds to delay after this transfer before * (optionally) changing the chipselect status, then starting * the next transfer or completing this @spi_message. - * @word_delay_usecs: microseconds to inter word delay after each word size - * (set by bits_per_word) transmission. - * @word_delay: clock cycles to inter word delay after each word size + * @word_delay: inter word delay to be introduced after each word size * (set by bits_per_word) transmission. * @effective_speed_hz: the effective SCK-speed that was used to * transfer this transfer. Set to 0 if the spi bus driver does @@ -883,15 +909,11 @@ struct spi_transfer { #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */ #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */ u8 bits_per_word; - u8 word_delay_usecs; u16 delay_usecs; - u16 cs_change_delay; - u8 cs_change_delay_unit; -#define SPI_DELAY_UNIT_USECS 0 -#define SPI_DELAY_UNIT_NSECS 1 -#define SPI_DELAY_UNIT_SCK 2 + struct spi_delay delay; + struct spi_delay cs_change_delay; + struct spi_delay word_delay; u32 speed_hz; - u16 word_delay; u32 effective_speed_hz; @@ -996,6 +1018,20 @@ spi_transfer_del(struct spi_transfer *t) list_del(&t->transfer_list); } +static inline int +spi_transfer_delay_exec(struct spi_transfer *t) +{ + struct spi_delay d; + + if (t->delay_usecs) { + d.value = t->delay_usecs; + d.unit = SPI_DELAY_UNIT_USECS; + return spi_delay_exec(&d, NULL); + } + + return spi_delay_exec(&t->delay, t); +} + /** * spi_message_init_with_transfers - Initialize spi_message and append transfers * @m: spi_message to be initialized @@ -1043,7 +1079,10 @@ static inline void spi_message_free(struct spi_message *m) kfree(m); } -extern void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold, u8 inactive_dly); +extern int spi_set_cs_timing(struct spi_device *spi, + struct spi_delay *setup, + struct spi_delay *hold, + struct spi_delay *inactive); extern int spi_setup(struct spi_device *spi); extern int spi_async(struct spi_device *spi, struct spi_message *message); diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index e3e5425b5c62..e701637a9ae9 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -177,7 +177,7 @@ static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* we can only change the settings if the port is not in use */ if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) || (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) { - dev_err(&sspa->pdev->dev, + dev_err(sspa->dev, "can't change hardware dai format: stream is in use\n"); return -EINVAL; } diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 5fdd1a24c232..6c5201431f6e 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -52,11 +52,11 @@ struct ssp_priv { static void dump_registers(struct ssp_device *ssp) { - dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n", + dev_dbg(ssp->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n", pxa_ssp_read_reg(ssp, SSCR0), pxa_ssp_read_reg(ssp, SSCR1), pxa_ssp_read_reg(ssp, SSTO)); - dev_dbg(&ssp->pdev->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n", + dev_dbg(ssp->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n", pxa_ssp_read_reg(ssp, SSPSP), pxa_ssp_read_reg(ssp, SSSR), pxa_ssp_read_reg(ssp, SSACD)); } @@ -223,7 +223,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, clk_id = PXA_SSP_CLK_EXT; } - dev_dbg(&ssp->pdev->dev, + dev_dbg(ssp->dev, "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %u\n", cpu_dai->id, clk_id, freq); @@ -316,7 +316,7 @@ static int pxa_ssp_set_pll(struct ssp_priv *priv, unsigned int freq) ssacd |= (0x6 << 4); - dev_dbg(&ssp->pdev->dev, + dev_dbg(ssp->dev, "Using SSACDD %x to supply %uHz\n", val, freq); break; @@ -687,7 +687,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, * - complain loudly and fail if they've not been set up yet. */ if ((sscr0 & SSCR0_MOD) && !ttsa) { - dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); + dev_err(ssp->dev, "No TDM timeslot configured\n"); return -EINVAL; } |