Commit 11ba2822 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'spi/for-5.9' into spi-next

parents 8ade0c2f 1d5cd4e7
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/renesas,rpc-if.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas Reduced Pin Count Interface (RPC-IF)
maintainers:
- Sergei Shtylyov <sergei.shtylyov@gmail.com>
description: |
Renesas RPC-IF allows a SPI flash or HyperFlash connected to the SoC to
be accessed via the external address space read mode or the manual mode.
The flash chip itself should be represented by a subnode of the RPC-IF node.
The flash interface is selected based on the "compatible" property of this
subnode:
- if it contains "jedec,spi-nor", then SPI is used;
- if it contains "cfi-flash", then HyperFlash is used.
allOf:
- $ref: "/schemas/spi/spi-controller.yaml#"
properties:
compatible:
items:
- enum:
- renesas,r8a77970-rpc-if # R-Car V3M
- renesas,r8a77980-rpc-if # R-Car V3H
- renesas,r8a77995-rpc-if # R-Car D3
- const: renesas,rcar-gen3-rpc-if # a generic R-Car gen3 device
reg:
items:
- description: RPC-IF registers
- description: direct mapping read mode area
- description: write buffer area
reg-names:
items:
- const: regs
- const: dirmap
- const: wbuf
clocks:
maxItems: 1
power-domains:
maxItems: 1
resets:
maxItems: 1
patternProperties:
"flash@[0-9a-f]+$":
type: object
properties:
compatible:
enum:
- cfi-flash
- jedec,spi-nor
examples:
- |
#include <dt-bindings/clock/renesas-cpg-mssr.h>
#include <dt-bindings/power/r8a77995-sysc.h>
spi@ee200000 {
compatible = "renesas,r8a77995-rpc-if", "renesas,rcar-gen3-rpc-if";
reg = <0xee200000 0x200>,
<0x08000000 0x4000000>,
<0xee208000 0x100>;
reg-names = "regs", "dirmap", "wbuf";
clocks = <&cpg CPG_MOD 917>;
power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
resets = <&cpg 917>;
#address-cells = <1>;
#size-cells = <0>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <40000000>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <1>;
};
};
* Freescale (Enhanced) Configurable Serial Peripheral Interface
(CSPI/eCSPI) for i.MX
Required properties:
- compatible :
- "fsl,imx1-cspi" for SPI compatible with the one integrated on i.MX1
- "fsl,imx21-cspi" for SPI compatible with the one integrated on i.MX21
- "fsl,imx27-cspi" for SPI compatible with the one integrated on i.MX27
- "fsl,imx31-cspi" for SPI compatible with the one integrated on i.MX31
- "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35
- "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51
- "fsl,imx53-ecspi" for SPI compatible with the one integrated on i.MX53 and later Soc
- "fsl,imx8mq-ecspi" for SPI compatible with the one integrated on i.MX8MQ
- "fsl,imx8mm-ecspi" for SPI compatible with the one integrated on i.MX8MM
- "fsl,imx8mn-ecspi" for SPI compatible with the one integrated on i.MX8MN
- "fsl,imx8mp-ecspi" for SPI compatible with the one integrated on i.MX8MP
- reg : Offset and length of the register set for the device
- interrupts : Should contain CSPI/eCSPI interrupt
- clocks : Clock specifiers for both ipg and per clocks.
- clock-names : Clock names should include both "ipg" and "per"
See the clock consumer binding,
Documentation/devicetree/bindings/clock/clock-bindings.txt
Recommended properties:
- cs-gpios : GPIOs to use as chip selects, see spi-bus.txt. While the native chip
select lines can be used, they appear to always generate a pulse between each
word of a transfer. Most use cases will require GPIO based chip selects to
generate a valid transaction.
Optional properties:
- num-cs : Number of total chip selects, see spi-bus.txt.
- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
Documentation/devicetree/bindings/dma/dma.txt.
- dma-names: DMA request names, if present, should include "tx" and "rx".
- fsl,spi-rdy-drctl: Integer, representing the value of DRCTL, the register
controlling the SPI_READY handling. Note that to enable the DRCTL consideration,
the SPI_READY mode-flag needs to be set too.
Valid values are: 0 (disabled), 1 (edge-triggered burst) and 2 (level-triggered burst).
Obsolete properties:
- fsl,spi-num-chipselects : Contains the number of the chipselect
Example:
ecspi@70010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx51-ecspi";
reg = <0x70010000 0x4000>;
interrupts = <36>;
cs-gpios = <&gpio3 24 0>, /* GPIO3_24 */
<&gpio3 25 0>; /* GPIO3_25 */
dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
dma-names = "rx", "tx";
fsl,spi-rdy-drctl = <1>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/fsl-imx-cspi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale (Enhanced) Configurable Serial Peripheral Interface (CSPI/eCSPI) for i.MX
maintainers:
- Shawn Guo <shawn.guo@linaro.org>
allOf:
- $ref: "/schemas/spi/spi-controller.yaml#"
properties:
compatible:
oneOf:
- const: fsl,imx1-cspi
- const: fsl,imx21-cspi
- const: fsl,imx27-cspi
- const: fsl,imx31-cspi
- const: fsl,imx35-cspi
- const: fsl,imx51-ecspi
- const: fsl,imx53-ecspi
- items:
- enum:
- fsl,imx50-ecspi
- fsl,imx6q-ecspi
- fsl,imx6sx-ecspi
- fsl,imx6sl-ecspi
- fsl,imx6sll-ecspi
- fsl,imx6ul-ecspi
- fsl,imx7d-ecspi
- fsl,imx8mq-ecspi
- fsl,imx8mm-ecspi
- fsl,imx8mn-ecspi
- fsl,imx8mp-ecspi
- const: fsl,imx51-ecspi
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: SoC SPI ipg clock
- description: SoC SPI per clock
clock-names:
items:
- const: ipg
- const: per
dmas:
items:
- description: DMA controller phandle and request line for RX
- description: DMA controller phandle and request line for TX
dma-names:
items:
- const: rx
- const: tx
fsl,spi-rdy-drctl:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Integer, representing the value of DRCTL, the register controlling
the SPI_READY handling. Note that to enable the DRCTL consideration,
the SPI_READY mode-flag needs to be set too.
Valid values are: 0 (disabled), 1 (edge-triggered burst) and 2 (level-triggered burst).
enum: [0, 1, 2]
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/imx5-clock.h>
spi@70010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx51-ecspi";
reg = <0x70010000 0x4000>;
interrupts = <36>;
clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
<&clks IMX5_CLK_ECSPI1_PER_GATE>;
clock-names = "ipg", "per";
};
* Freescale MX233/MX28 SSP/SPI
Required properties:
- compatible: Should be "fsl,<soc>-spi", where soc is "imx23" or "imx28"
- reg: Offset and length of the register set for the device
- interrupts: Should contain SSP ERROR interrupt
- dmas: DMA specifier, consisting of a phandle to DMA controller node
and SSP DMA channel ID.
Refer to dma.txt and fsl-mxs-dma.txt for details.
- dma-names: Must be "rx-tx".
Optional properties:
- clock-frequency : Input clock frequency to the SPI block in Hz.
Default is 160000000 Hz.
Example:
ssp0: ssp@80010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx28-spi";
reg = <0x80010000 0x2000>;
interrupts = <96>;
dmas = <&dma_apbh 0>;
dma-names = "rx-tx";
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/mxs-spi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale MX233/MX28 SSP/SPI
maintainers:
- Marek Vasut <marex@denx.de>
allOf:
- $ref: "/schemas/spi/spi-controller.yaml#"
properties:
compatible:
enum:
- fsl,imx23-spi
- fsl,imx28-spi
reg:
maxItems: 1
interrupts:
maxItems: 1
dmas:
maxItems: 1
dma-names:
const: rx-tx
clock-frequency:
description: input clock frequency to the SPI block in Hz.
default: 160000000
required:
- compatible
- reg
- interrupts
- dmas
- dma-names
unevaluatedProperties: false
examples:
- |
spi@80010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx28-spi";
reg = <0x80010000 0x2000>;
interrupts = <96>;
dmas = <&dma_apbh 0>;
dma-names = "rx-tx";
};
...@@ -21,6 +21,7 @@ properties: ...@@ -21,6 +21,7 @@ properties:
# device # device
- items: - items:
- enum: - enum:
- renesas,msiof-r8a7742 # RZ/G1H
- renesas,msiof-r8a7743 # RZ/G1M - renesas,msiof-r8a7743 # RZ/G1M
- renesas,msiof-r8a7744 # RZ/G1N - renesas,msiof-r8a7744 # RZ/G1N
- renesas,msiof-r8a7745 # RZ/G1E - renesas,msiof-r8a7745 # RZ/G1E
...@@ -37,6 +38,7 @@ properties: ...@@ -37,6 +38,7 @@ properties:
- renesas,msiof-r8a774a1 # RZ/G2M - renesas,msiof-r8a774a1 # RZ/G2M
- renesas,msiof-r8a774b1 # RZ/G2N - renesas,msiof-r8a774b1 # RZ/G2N
- renesas,msiof-r8a774c0 # RZ/G2E - renesas,msiof-r8a774c0 # RZ/G2E
- renesas,msiof-r8a774e1 # RZ/G2H
- renesas,msiof-r8a7795 # R-Car H3 - renesas,msiof-r8a7795 # R-Car H3
- renesas,msiof-r8a7796 # R-Car M3-W - renesas,msiof-r8a7796 # R-Car M3-W
- renesas,msiof-r8a77965 # R-Car M3-N - renesas,msiof-r8a77965 # R-Car M3-N
......
Davinci SPI controller device bindings Davinci SPI controller device bindings
Links on DM: Links on DM:
Keystone 2 - http://www.ti.com/lit/ug/sprugp2a/sprugp2a.pdf Keystone 2 - https://www.ti.com/lit/ug/sprugp2a/sprugp2a.pdf
dm644x - http://www.ti.com/lit/ug/sprue32a/sprue32a.pdf dm644x - https://www.ti.com/lit/ug/sprue32a/sprue32a.pdf
OMAP-L138/da830 - http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf OMAP-L138/da830 - http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf
Required properties: Required properties:
......
* Freescale Low Power SPI (LPSPI) for i.MX
Required properties:
- compatible :
- "fsl,imx7ulp-spi" for LPSPI compatible with the one integrated on i.MX7ULP soc
- "fsl,imx8qxp-spi" for LPSPI compatible with the one integrated on i.MX8QXP soc
- reg : address and length of the lpspi master registers
- interrupt-parent : core interrupt controller
- interrupts : lpspi interrupt
- clocks : lpspi clock specifier. Its number and order need to correspond to the
value in clock-names.
- clock-names : Corresponding to per clock and ipg clock in "clocks"
respectively. In i.MX7ULP, it only has per clk, so use CLK_DUMMY
to fill the "ipg" blank.
- spi-slave : spi slave mode support. In slave mode, add this attribute without
value. In master mode, remove it.
Examples:
lpspi2: lpspi@40290000 {
compatible = "fsl,imx7ulp-spi";
reg = <0x40290000 0x10000>;
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7ULP_CLK_LPSPI2>,
<&clks IMX7ULP_CLK_DUMMY>;
clock-names = "per", "ipg";
spi-slave;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/spi-fsl-lpspi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale Low Power SPI (LPSPI) for i.MX
maintainers:
- Anson Huang <Anson.Huang@nxp.com>
allOf:
- $ref: "/schemas/spi/spi-controller.yaml#"
properties:
compatible:
enum:
- fsl,imx7ulp-spi
- fsl,imx8qxp-spi
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: SoC SPI per clock
- description: SoC SPI ipg clock
clock-names:
items:
- const: per
- const: ipg
fsl,spi-only-use-cs1-sel:
description:
spi common code does not support use of CS signals discontinuously.
i.MX8DXL-EVK board only uses CS1 without using CS0. Therefore, add
this property to re-config the chipselect value in the LPSPI driver.
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/imx7ulp-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
spi@40290000 {
compatible = "fsl,imx7ulp-spi";
reg = <0x40290000 0x10000>;
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7ULP_CLK_LPSPI2>,
<&clks IMX7ULP_CLK_DUMMY>;
clock-names = "per", "ipg";
spi-slave;
fsl,spi-only-use-cs1-sel;
};
Lantiq Synchronous Serial Controller (SSC) SPI master driver Lantiq Synchronous Serial Controller (SSC) SPI master driver
Required properties: Required properties:
- compatible: "lantiq,ase-spi", "lantiq,falcon-spi", "lantiq,xrx100-spi" - compatible: "lantiq,ase-spi", "lantiq,falcon-spi", "lantiq,xrx100-spi",
"intel,lgm-spi"
- #address-cells: see spi-bus.txt - #address-cells: see spi-bus.txt
- #size-cells: see spi-bus.txt - #size-cells: see spi-bus.txt
- reg: address and length of the spi master registers - reg: address and length of the spi master registers
- interrupts: should contain the "spi_rx", "spi_tx" and "spi_err" interrupt. - interrupts:
For compatible "intel,lgm-ssc" - the common interrupt number for
all of tx rx & err interrupts.
or
For rest of the compatibles, should contain the "spi_rx", "spi_tx" and
"spi_err" interrupt.
Optional properties: Optional properties:
...@@ -27,3 +33,14 @@ spi: spi@e100800 { ...@@ -27,3 +33,14 @@ spi: spi@e100800 {
num-cs = <6>; num-cs = <6>;
base-cs = <1>; base-cs = <1>;
}; };
ssc0: spi@e0800000 {
compatible = "intel,lgm-spi";
reg = <0xe0800000 0x400>;
interrupt-parent = <&ioapic1>;
interrupts = <35 1>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&cgu0 LGM_CLK_NGI>, <&cgu0 LGM_GCLK_SSC0>;
clock-names = "freq", "gate";
};
...@@ -11,6 +11,7 @@ Required properties: ...@@ -11,6 +11,7 @@ Required properties:
- mediatek,mt8135-spi: for mt8135 platforms - mediatek,mt8135-spi: for mt8135 platforms
- mediatek,mt8173-spi: for mt8173 platforms - mediatek,mt8173-spi: for mt8173 platforms
- mediatek,mt8183-spi: for mt8183 platforms - mediatek,mt8183-spi: for mt8183 platforms
- "mediatek,mt8192-spi", "mediatek,mt6765-spi": for mt8192 platforms
- "mediatek,mt8516-spi", "mediatek,mt2712-spi": for mt8516 platforms - "mediatek,mt8516-spi", "mediatek,mt2712-spi": for mt8516 platforms
- #address-cells: should be 1. - #address-cells: should be 1.
......
...@@ -6,7 +6,7 @@ Supported chips: ...@@ -6,7 +6,7 @@ Supported chips:
* NXP SI18IS602/602B/603 * NXP SI18IS602/602B/603
Datasheet: http://www.nxp.com/documents/data_sheet/SC18IS602_602B_603.pdf Datasheet: https://www.nxp.com/documents/data_sheet/SC18IS602_602B_603.pdf
Author: Author:
Guenter Roeck <linux@roeck-us.net> Guenter Roeck <linux@roeck-us.net>
......
...@@ -75,11 +75,11 @@ extern const struct imx_mxc_w1_data imx27_mxc_w1_data; ...@@ -75,11 +75,11 @@ extern const struct imx_mxc_w1_data imx27_mxc_w1_data;
imx_add_mxc_w1(&imx27_mxc_w1_data) imx_add_mxc_w1(&imx27_mxc_w1_data)
extern const struct imx_spi_imx_data imx27_cspi_data[]; extern const struct imx_spi_imx_data imx27_cspi_data[];
#define imx27_add_cspi(id, pdata) \ #define imx27_add_cspi(id, gtable) \
imx_add_spi_imx(&imx27_cspi_data[id], pdata) imx_add_spi_imx(&imx27_cspi_data[id], gtable)
#define imx27_add_spi_imx0(pdata) imx27_add_cspi(0, pdata) #define imx27_add_spi_imx0(gtable) imx27_add_cspi(0, gtable)
#define imx27_add_spi_imx1(pdata) imx27_add_cspi(1, pdata) #define imx27_add_spi_imx1(gtable) imx27_add_cspi(1, gtable)
#define imx27_add_spi_imx2(pdata) imx27_add_cspi(2, pdata) #define imx27_add_spi_imx2(gtable) imx27_add_cspi(2, gtable)
extern const struct imx_pata_imx_data imx27_pata_imx_data; extern const struct imx_pata_imx_data imx27_pata_imx_data;
#define imx27_add_pata_imx() \ #define imx27_add_pata_imx() \
......
...@@ -69,11 +69,11 @@ extern const struct imx_mxc_w1_data imx31_mxc_w1_data; ...@@ -69,11 +69,11 @@ extern const struct imx_mxc_w1_data imx31_mxc_w1_data;
imx_add_mxc_w1(&imx31_mxc_w1_data) imx_add_mxc_w1(&imx31_mxc_w1_data)
extern const struct imx_spi_imx_data imx31_cspi_data[]; extern const struct imx_spi_imx_data imx31_cspi_data[];
#define imx31_add_cspi(id, pdata) \ #define imx31_add_cspi(id, gtable) \
imx_add_spi_imx(&imx31_cspi_data[id], pdata) imx_add_spi_imx(&imx31_cspi_data[id], gtable)
#define imx31_add_spi_imx0(pdata) imx31_add_cspi(0, pdata) #define imx31_add_spi_imx0(gtable) imx31_add_cspi(0, gtable)
#define imx31_add_spi_imx1(pdata) imx31_add_cspi(1, pdata) #define imx31_add_spi_imx1(gtable) imx31_add_cspi(1, gtable)
#define imx31_add_spi_imx2(pdata) imx31_add_cspi(2, pdata) #define imx31_add_spi_imx2(gtable) imx31_add_cspi(2, gtable)
extern const struct imx_pata_imx_data imx31_pata_imx_data; extern const struct imx_pata_imx_data imx31_pata_imx_data;
#define imx31_add_pata_imx() \ #define imx31_add_pata_imx() \
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/gpio/machine.h>
#include <linux/platform_data/dma-imx-sdma.h> #include <linux/platform_data/dma-imx-sdma.h>
extern struct device mxc_aips_bus; extern struct device mxc_aips_bus;
...@@ -276,7 +277,6 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx( ...@@ -276,7 +277,6 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
const struct imx_sdhci_esdhc_imx_data *data, const struct imx_sdhci_esdhc_imx_data *data,
const struct esdhc_platform_data *pdata); const struct esdhc_platform_data *pdata);
#include <linux/platform_data/spi-imx.h>
struct imx_spi_imx_data { struct imx_spi_imx_data {
const char *devid; const char *devid;
int id; int id;
...@@ -285,8 +285,7 @@ struct imx_spi_imx_data { ...@@ -285,8 +285,7 @@ struct imx_spi_imx_data {
int irq; int irq;
}; };
struct platform_device *__init imx_add_spi_imx( struct platform_device *__init imx_add_spi_imx(
const struct imx_spi_imx_data *data, const struct imx_spi_imx_data *data, struct gpiod_lookup_table *gtable);
const struct spi_imx_master *pdata);
struct platform_device *imx_add_imx_dma(char *name, resource_size_t iobase, struct platform_device *imx_add_imx_dma(char *name, resource_size_t iobase,
int irq); int irq);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Copyright (C) 2009-2010 Pengutronix * Copyright (C) 2009-2010 Pengutronix
* Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
*/ */
#include <linux/gpio/machine.h>
#include "../hardware.h" #include "../hardware.h"
#include "devices-common.h" #include "devices-common.h"
...@@ -57,8 +58,7 @@ const struct imx_spi_imx_data imx35_cspi_data[] __initconst = { ...@@ -57,8 +58,7 @@ const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
#endif /* ifdef CONFIG_SOC_IMX35 */ #endif /* ifdef CONFIG_SOC_IMX35 */
struct platform_device *__init imx_add_spi_imx( struct platform_device *__init imx_add_spi_imx(
const struct imx_spi_imx_data *data, const struct imx_spi_imx_data *data, struct gpiod_lookup_table *gtable)
const struct spi_imx_master *pdata)
{ {
struct resource res[] = { struct resource res[] = {
{ {
...@@ -71,7 +71,8 @@ struct platform_device *__init imx_add_spi_imx( ...@@ -71,7 +71,8 @@ struct platform_device *__init imx_add_spi_imx(
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
}; };
if (gtable)
gpiod_add_lookup_table(gtable);
return imx_add_platform_device(data->devid, data->id, return imx_add_platform_device(data->devid, data->id,
res, ARRAY_SIZE(res), pdata, sizeof(*pdata)); res, ARRAY_SIZE(res), NULL, 0);
} }
...@@ -303,18 +303,34 @@ static struct imx_ssi_platform_data mx27_3ds_ssi_pdata = { ...@@ -303,18 +303,34 @@ static struct imx_ssi_platform_data mx27_3ds_ssi_pdata = {
}; };
/* SPI */ /* SPI */
static int spi1_chipselect[] = {SPI1_SS0}; static struct gpiod_lookup_table mx27_spi1_gpiod_table = {
.dev_id = "imx27-cspi.0", /* Actual device name for spi1 */
static const struct spi_imx_master spi1_pdata __initconst = { .table = {
.chipselect = spi1_chipselect, /*
.num_chipselect = ARRAY_SIZE(spi1_chipselect), * The i.MX27 has the i.MX21 GPIO controller, the SPI1 CS GPIO
* SPI1_SS0 is numbered IMX_GPIO_NR(4, 28).
*
* This is in "bank 4" which is subtracted by one in the macro
* so this is actually bank 3 on "imx21-gpio.3".
*/
GPIO_LOOKUP_IDX("imx21-gpio.3", 28, "cs", 0, GPIO_ACTIVE_LOW),
{ },
},
}; };
static int spi2_chipselect[] = {SPI2_SS0}; static struct gpiod_lookup_table mx27_spi2_gpiod_table = {
.dev_id = "imx27-cspi.1", /* Actual device name for spi2 */
static const struct spi_imx_master spi2_pdata __initconst = { .table = {
.chipselect = spi2_chipselect, /*
.num_chipselect = ARRAY_SIZE(spi2_chipselect), * The i.MX27 has the i.MX21 GPIO controller, the SPI2 CS GPIO
* SPI2_SS0 is numbered IMX_GPIO_NR(4, 21).
*
* This is in "bank 4" which is subtracted by one in the macro
* so this is actually bank 3 on "imx21-gpio.3".
*/
GPIO_LOOKUP_IDX("imx21-gpio.3", 21, "cs", 0, GPIO_ACTIVE_LOW),
{ },
},
}; };
static struct imx_fb_videomode mx27_3ds_modes[] = { static struct imx_fb_videomode mx27_3ds_modes[] = {
...@@ -397,8 +413,8 @@ static void __init mx27pdk_init(void) ...@@ -397,8 +413,8 @@ static void __init mx27pdk_init(void)
imx27_add_imx_keypad(&mx27_3ds_keymap_data); imx27_add_imx_keypad(&mx27_3ds_keymap_data);
imx27_add_imx2_wdt(); imx27_add_imx2_wdt();
imx27_add_spi_imx1(&spi2_pdata); imx27_add_spi_imx1(&mx27_spi2_gpiod_table);
imx27_add_spi_imx0(&spi1_pdata); imx27_add_spi_imx0(&mx27_spi1_gpiod_table);
imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data); imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
imx27_add_imx_fb(&mx27_3ds_fb_data); imx27_add_imx_fb(&mx27_3ds_fb_data);
......
...@@ -378,15 +378,6 @@ static struct imx_ssi_platform_data mx31_3ds_ssi_pdata = { ...@@ -378,15 +378,6 @@ static struct imx_ssi_platform_data mx31_3ds_ssi_pdata = {
.flags = IMX_SSI_DMA | IMX_SSI_NET, .flags = IMX_SSI_DMA | IMX_SSI_NET,
}; };
/* SPI */
static const struct spi_imx_master spi0_pdata __initconst = {
.num_chipselect = 3,
};
static const struct spi_imx_master spi1_pdata __initconst = {
.num_chipselect = 3,
};
static struct spi_board_info mx31_3ds_spi_devs[] __initdata = { static struct spi_board_info mx31_3ds_spi_devs[] __initdata = {
{ {
.modalias = "mc13783", .modalias = "mc13783",
...@@ -561,14 +552,14 @@ static void __init mx31_3ds_init(void) ...@@ -561,14 +552,14 @@ static void __init mx31_3ds_init(void)
imx31_add_imx_uart0(&uart_pdata); imx31_add_imx_uart0(&uart_pdata);
imx31_add_mxc_nand(&mx31_3ds_nand_board_info); imx31_add_mxc_nand(&mx31_3ds_nand_board_info);
imx31_add_spi_imx1(&spi1_pdata); imx31_add_spi_imx1(NULL);
imx31_add_imx_keypad(&mx31_3ds_keymap_data); imx31_add_imx_keypad(&mx31_3ds_keymap_data);
imx31_add_imx2_wdt(); imx31_add_imx2_wdt();
imx31_add_imx_i2c0(&mx31_3ds_i2c0_data); imx31_add_imx_i2c0(&mx31_3ds_i2c0_data);
imx31_add_spi_imx0(&spi0_pdata); imx31_add_spi_imx0(NULL);
imx31_add_ipu_core(); imx31_add_ipu_core();
imx31_add_mx3_sdc_fb(&mx3fb_pdata); imx31_add_mx3_sdc_fb(&mx3fb_pdata);
......
...@@ -215,16 +215,6 @@ static void __init lilly1131_usb_init(void) ...@@ -215,16 +215,6 @@ static void __init lilly1131_usb_init(void)
imx31_add_mxc_ehci_hs(2, &usbh2_pdata); imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
} }
/* SPI */
static const struct spi_imx_master spi0_pdata __initconst = {
.num_chipselect = 3,
};
static const struct spi_imx_master spi1_pdata __initconst = {
.num_chipselect = 3,
};
static struct mc13xxx_platform_data mc13783_pdata __initdata = { static struct mc13xxx_platform_data mc13783_pdata __initdata = {
.flags = MC13XXX_USE_RTC | MC13XXX_USE_TOUCHSCREEN, .flags = MC13XXX_USE_RTC | MC13XXX_USE_TOUCHSCREEN,
}; };
...@@ -281,8 +271,8 @@ static void __init mx31lilly_board_init(void) ...@@ -281,8 +271,8 @@ static void __init mx31lilly_board_init(void)
mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS1__SS1, "SPI2_SS1"); mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS1__SS1, "SPI2_SS1");
mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS2__SS2, "SPI2_SS2"); mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS2__SS2, "SPI2_SS2");
imx31_add_spi_imx0(&spi0_pdata); imx31_add_spi_imx0(NULL);
imx31_add_spi_imx1(&spi1_pdata); imx31_add_spi_imx1(NULL);
regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
} }
......
...@@ -73,11 +73,6 @@ static const struct imxuart_platform_data uart_pdata __initconst = { ...@@ -73,11 +73,6 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS, .flags = IMXUART_HAVE_RTSCTS,
}; };
/* SPI */
static const struct spi_imx_master spi0_pdata __initconst = {
.num_chipselect = 3,
};
static const struct mxc_nand_platform_data static const struct mxc_nand_platform_data
mx31lite_nand_board_info __initconst = { mx31lite_nand_board_info __initconst = {
.width = 1, .width = 1,
...@@ -111,16 +106,6 @@ static struct platform_device smsc911x_device = { ...@@ -111,16 +106,6 @@ static struct platform_device smsc911x_device = {
}, },
}; };
/*
* SPI
*
* The MC13783 is the only hard-wired SPI device on the module.
*/
static const struct spi_imx_master spi1_pdata __initconst = {
.num_chipselect = 1,
};
static struct mc13xxx_platform_data mc13783_pdata __initdata = { static struct mc13xxx_platform_data mc13783_pdata __initdata = {
.flags = MC13XXX_USE_RTC, .flags = MC13XXX_USE_RTC,
}; };
...@@ -246,13 +231,13 @@ static void __init mx31lite_init(void) ...@@ -246,13 +231,13 @@ static void __init mx31lite_init(void)
"mx31lite"); "mx31lite");
imx31_add_imx_uart0(&uart_pdata); imx31_add_imx_uart0(&uart_pdata);
imx31_add_spi_imx0(&spi0_pdata); imx31_add_spi_imx0(NULL);
/* NOR and NAND flash */ /* NOR and NAND flash */
platform_device_register(&physmap_flash_device); platform_device_register(&physmap_flash_device);
imx31_add_mxc_nand(&mx31lite_nand_board_info); imx31_add_mxc_nand(&mx31lite_nand_board_info);
imx31_add_spi_imx1(&spi1_pdata); imx31_add_spi_imx1(NULL);
regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
} }
......
...@@ -143,10 +143,6 @@ static const struct imxi2c_platform_data moboard_i2c1_data __initconst = { ...@@ -143,10 +143,6 @@ static const struct imxi2c_platform_data moboard_i2c1_data __initconst = {
.bitrate = 100000, .bitrate = 100000,
}; };
static const struct spi_imx_master moboard_spi1_pdata __initconst = {
.num_chipselect = 3,
};
static struct regulator_consumer_supply sdhc_consumers[] = { static struct regulator_consumer_supply sdhc_consumers[] = {
{ {
.dev_name = "imx31-mmc.0", .dev_name = "imx31-mmc.0",
...@@ -287,10 +283,6 @@ static struct spi_board_info moboard_spi_board_info[] __initdata = { ...@@ -287,10 +283,6 @@ static struct spi_board_info moboard_spi_board_info[] __initdata = {
}, },
}; };
static const struct spi_imx_master moboard_spi2_pdata __initconst = {
.num_chipselect = 2,
};
#define SDHC1_CD IOMUX_TO_GPIO(MX31_PIN_ATA_CS0) #define SDHC1_CD IOMUX_TO_GPIO(MX31_PIN_ATA_CS0)
#define SDHC1_WP IOMUX_TO_GPIO(MX31_PIN_ATA_CS1) #define SDHC1_WP IOMUX_TO_GPIO(MX31_PIN_ATA_CS1)
...@@ -514,8 +506,8 @@ static void __init mx31moboard_init(void) ...@@ -514,8 +506,8 @@ static void __init mx31moboard_init(void)
imx31_add_imx_i2c0(&moboard_i2c0_data); imx31_add_imx_i2c0(&moboard_i2c0_data);
imx31_add_imx_i2c1(&moboard_i2c1_data); imx31_add_imx_i2c1(&moboard_i2c1_data);
imx31_add_spi_imx1(&moboard_spi1_pdata); imx31_add_spi_imx1(NULL);
imx31_add_spi_imx2(&moboard_spi2_pdata); imx31_add_spi_imx2(NULL);
mx31moboard_init_cam(); mx31moboard_init_cam();
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/ulpi.h> #include <linux/usb/ulpi.h>
...@@ -188,11 +189,19 @@ static struct spi_board_info pca100_spi_board_info[] __initdata = { ...@@ -188,11 +189,19 @@ static struct spi_board_info pca100_spi_board_info[] __initdata = {
}, },
}; };
static int pca100_spi_cs[] = {SPI1_SS0, SPI1_SS1}; static struct gpiod_lookup_table pca100_spi0_gpiod_table = {
.dev_id = "imx27-cspi.0", /* Actual device name for spi0 */
static const struct spi_imx_master pca100_spi0_data __initconst = { .table = {
.chipselect = pca100_spi_cs, /*
.num_chipselect = ARRAY_SIZE(pca100_spi_cs), * The i.MX27 has the i.MX21 GPIO controller, port D is
* bank 3 and thus named "imx21-gpio.3".
* SPI1_SS0 is GPIO_PORTD + 28
* SPI1_SS1 is GPIO_PORTD + 27
*/
GPIO_LOOKUP_IDX("imx21-gpio.3", 28, "cs", 0, GPIO_ACTIVE_LOW),
GPIO_LOOKUP_IDX("imx21-gpio.3", 27, "cs", 1, GPIO_ACTIVE_LOW),
{ },
},
}; };
static void pca100_ac97_warm_reset(struct snd_ac97 *ac97) static void pca100_ac97_warm_reset(struct snd_ac97 *ac97)
...@@ -362,7 +371,7 @@ static void __init pca100_init(void) ...@@ -362,7 +371,7 @@ static void __init pca100_init(void)
mxc_gpio_mode(GPIO_PORTD | 27 | GPIO_GPIO | GPIO_IN); mxc_gpio_mode(GPIO_PORTD | 27 | GPIO_GPIO | GPIO_IN);
spi_register_board_info(pca100_spi_board_info, spi_register_board_info(pca100_spi_board_info,
ARRAY_SIZE(pca100_spi_board_info)); ARRAY_SIZE(pca100_spi_board_info));
imx27_add_spi_imx0(&pca100_spi0_data); imx27_add_spi_imx0(&pca100_spi0_gpiod_table);
imx27_add_imx_fb(&pca100_fb_data); imx27_add_imx_fb(&pca100_fb_data);
......
...@@ -52,11 +52,6 @@ static struct spi_board_info pcm037_spi_dev[] = { ...@@ -52,11 +52,6 @@ static struct spi_board_info pcm037_spi_dev[] = {
}, },
}; };
/* Platform Data for MXC CSPI */
static const struct spi_imx_master pcm037_spi1_pdata __initconst = {
.num_chipselect = 2,
};
/* GPIO-keys input device */ /* GPIO-keys input device */
static struct gpio_keys_button pcm037_gpio_keys[] = { static struct gpio_keys_button pcm037_gpio_keys[] = {
{ {
...@@ -163,7 +158,7 @@ int __init pcm037_eet_init_devices(void) ...@@ -163,7 +158,7 @@ int __init pcm037_eet_init_devices(void)
/* SPI */ /* SPI */
spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev)); spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev));
imx31_add_spi_imx0(&pcm037_spi1_pdata); imx31_add_spi_imx0(NULL);
imx_add_gpio_keys(&pcm037_gpio_keys_platform_data); imx_add_gpio_keys(&pcm037_gpio_keys_platform_data);
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
/** /**
* of_gpio_spi_cs_get_count() - special GPIO counting for SPI * of_gpio_spi_cs_get_count() - special GPIO counting for SPI
* Some elder GPIO controllers need special quirks. Currently we handle * Some elder GPIO controllers need special quirks. Currently we handle
* the Freescale GPIO controller with bindings that doesn't use the * the Freescale and PPC GPIO controller with bindings that doesn't use the
* established "cs-gpios" for chip selects but instead rely on * established "cs-gpios" for chip selects but instead rely on
* "gpios" for the chip select lines. If we detect this, we redirect * "gpios" for the chip select lines. If we detect this, we redirect
* the counting of "cs-gpios" to count "gpios" transparent to the * the counting of "cs-gpios" to count "gpios" transparent to the
...@@ -41,7 +41,8 @@ static int of_gpio_spi_cs_get_count(struct device *dev, const char *con_id) ...@@ -41,7 +41,8 @@ static int of_gpio_spi_cs_get_count(struct device *dev, const char *con_id)
if (!con_id || strcmp(con_id, "cs")) if (!con_id || strcmp(con_id, "cs"))
return 0; return 0;
if (!of_device_is_compatible(np, "fsl,spi") && if (!of_device_is_compatible(np, "fsl,spi") &&
!of_device_is_compatible(np, "aeroflexgaisler,spictrl")) !of_device_is_compatible(np, "aeroflexgaisler,spictrl") &&
!of_device_is_compatible(np, "ibm,ppc4xx-spi"))
return 0; return 0;
return of_gpio_named_count(np, "gpios"); return of_gpio_named_count(np, "gpios");
} }
...@@ -405,9 +406,10 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev, ...@@ -405,9 +406,10 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
if (!IS_ENABLED(CONFIG_SPI_MASTER)) if (!IS_ENABLED(CONFIG_SPI_MASTER))
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
/* Allow this specifically for Freescale devices */ /* Allow this specifically for Freescale and PPC devices */
if (!of_device_is_compatible(np, "fsl,spi") && if (!of_device_is_compatible(np, "fsl,spi") &&
!of_device_is_compatible(np, "aeroflexgaisler,spictrl")) !of_device_is_compatible(np, "aeroflexgaisler,spictrl") &&
!of_device_is_compatible(np, "ibm,ppc4xx-spi"))
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
/* Allow only if asking for "cs-gpios" */ /* Allow only if asking for "cs-gpios" */
if (!con_id || strcmp(con_id, "cs")) if (!con_id || strcmp(con_id, "cs"))
......
...@@ -174,6 +174,15 @@ config PL353_SMC ...@@ -174,6 +174,15 @@ config PL353_SMC
This driver is for the ARM PL351/PL353 Static Memory This driver is for the ARM PL351/PL353 Static Memory
Controller(SMC) module. Controller(SMC) module.
config RENESAS_RPCIF
tristate "Renesas RPC-IF driver"
depends on ARCH_RENESAS
select REGMAP_MMIO
help
This supports Renesas R-Car Gen3 RPC-IF which provides either SPI
host or HyperFlash. You'll have to select individual components
under the corresponding menu.
source "drivers/memory/samsung/Kconfig" source "drivers/memory/samsung/Kconfig"
source "drivers/memory/tegra/Kconfig" source "drivers/memory/tegra/Kconfig"
......
...@@ -22,6 +22,7 @@ obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o ...@@ -22,6 +22,7 @@ obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o
obj-$(CONFIG_MTK_SMI) += mtk-smi.o obj-$(CONFIG_MTK_SMI) += mtk-smi.o
obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o
obj-$(CONFIG_PL353_SMC) += pl353-smc.o obj-$(CONFIG_PL353_SMC) += pl353-smc.o
obj-$(CONFIG_RENESAS_RPCIF) += renesas-rpc-if.o
obj-$(CONFIG_SAMSUNG_MC) += samsung/ obj-$(CONFIG_SAMSUNG_MC) += samsung/
obj-$(CONFIG_TEGRA_MC) += tegra/ obj-$(CONFIG_TEGRA_MC) += tegra/
......
This diff is collapsed.
...@@ -9,17 +9,6 @@ config SPI_ASPEED_SMC ...@@ -9,17 +9,6 @@ config SPI_ASPEED_SMC
and support for the SPI flash memory controller (SPI) for and support for the SPI flash memory controller (SPI) for
the host firmware. The implementation only supports SPI NOR. the host firmware. The implementation only supports SPI NOR.
config SPI_CADENCE_QUADSPI
tristate "Cadence Quad SPI controller"
depends on OF && (ARM || ARM64 || COMPILE_TEST)
help
Enable support for the Cadence Quad SPI Flash controller.
Cadence QSPI is a specialized controller for connecting an SPI
Flash over 1/2/4-bit wide bus. Enable this option if you have a
device with a Cadence QSPI controller and want to access the
Flash as an MTD device.
config SPI_HISI_SFC config SPI_HISI_SFC
tristate "Hisilicon FMC SPI NOR Flash Controller(SFC)" tristate "Hisilicon FMC SPI NOR Flash Controller(SFC)"
depends on ARCH_HISI || COMPILE_TEST depends on ARCH_HISI || COMPILE_TEST
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_SPI_ASPEED_SMC) += aspeed-smc.o obj-$(CONFIG_SPI_ASPEED_SMC) += aspeed-smc.o
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
......
...@@ -59,6 +59,7 @@ comment "SPI Master Controller Drivers" ...@@ -59,6 +59,7 @@ comment "SPI Master Controller Drivers"
config SPI_ALTERA config SPI_ALTERA
tristate "Altera SPI Controller" tristate "Altera SPI Controller"
select REGMAP_MMIO
help help
This is the driver for the Altera SPI Controller. This is the driver for the Altera SPI Controller.
...@@ -102,7 +103,7 @@ config SPI_AT91_USART ...@@ -102,7 +103,7 @@ config SPI_AT91_USART
config SPI_ATMEL_QUADSPI config SPI_ATMEL_QUADSPI
tristate "Atmel Quad SPI Controller" tristate "Atmel Quad SPI Controller"
depends on ARCH_AT91 || (ARM && COMPILE_TEST && !ARCH_EBSA110) depends on ARCH_AT91 || COMPILE_TEST
depends on OF && HAS_IOMEM depends on OF && HAS_IOMEM
help help
This enables support for the Quad SPI controller in master mode. This enables support for the Quad SPI controller in master mode.
...@@ -149,13 +150,13 @@ config SPI_BCM2835AUX ...@@ -149,13 +150,13 @@ config SPI_BCM2835AUX
config SPI_BCM63XX config SPI_BCM63XX
tristate "Broadcom BCM63xx SPI controller" tristate "Broadcom BCM63xx SPI controller"
depends on BCM63XX || COMPILE_TEST depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST
help 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 config SPI_BCM63XX_HSSPI
tristate "Broadcom BCM63XX HS SPI controller driver" tristate "Broadcom BCM63XX HS SPI controller driver"
depends on BCM63XX || ARCH_BCM_63XX || COMPILE_TEST depends on BCM63XX || BMIPS_GENERIC || ARCH_BCM_63XX || COMPILE_TEST
help help
This enables support for the High Speed SPI controller present on This enables support for the High Speed SPI controller present on
newer Broadcom BCM63XX SoCs. newer Broadcom BCM63XX SoCs.
...@@ -168,7 +169,7 @@ config SPI_BCM_QSPI ...@@ -168,7 +169,7 @@ config SPI_BCM_QSPI
help help
Enables support for the Broadcom SPI flash and MSPI controller. Enables support for the Broadcom SPI flash and MSPI controller.
Select this option for any one of BRCMSTB, iProc NSP and NS2 SoCs Select this option for any one of BRCMSTB, iProc NSP and NS2 SoCs
based platforms. This driver works for both SPI master for spi-nor based platforms. This driver works for both SPI master for SPI NOR
flash device as well as MSPI device. flash device as well as MSPI device.
config SPI_BITBANG config SPI_BITBANG
...@@ -200,6 +201,17 @@ config SPI_CADENCE ...@@ -200,6 +201,17 @@ config SPI_CADENCE
This selects the Cadence SPI controller master driver This selects the Cadence SPI controller master driver
used by Xilinx Zynq and ZynqMP. used by Xilinx Zynq and ZynqMP.
config SPI_CADENCE_QUADSPI
tristate "Cadence Quad SPI controller"
depends on OF && (ARM || ARM64 || COMPILE_TEST)
help
Enable support for the Cadence Quad SPI Flash controller.
Cadence QSPI is a specialized controller for connecting an SPI
Flash over 1/2/4-bit wide bus. Enable this option if you have a
device with a Cadence QSPI controller and want to access the
Flash as an MTD device.
config SPI_CLPS711X config SPI_CLPS711X
tristate "CLPS711X host SPI controller" tristate "CLPS711X host SPI controller"
depends on ARCH_CLPS711X || COMPILE_TEST depends on ARCH_CLPS711X || COMPILE_TEST
...@@ -299,11 +311,11 @@ config SPI_FSL_QUADSPI ...@@ -299,11 +311,11 @@ config SPI_FSL_QUADSPI
supports the high-level SPI memory interface. supports the high-level SPI memory interface.
config SPI_HISI_SFC_V3XX config SPI_HISI_SFC_V3XX
tristate "HiSilicon SPI-NOR Flash Controller for Hi16XX chipsets" tristate "HiSilicon SPI NOR Flash Controller for Hi16XX chipsets"
depends on (ARM64 && ACPI) || COMPILE_TEST depends on (ARM64 && ACPI) || COMPILE_TEST
depends on HAS_IOMEM depends on HAS_IOMEM
help help
This enables support for HiSilicon v3xx SPI-NOR flash controller This enables support for HiSilicon v3xx SPI NOR flash controller
found in hi16xx chipsets. found in hi16xx chipsets.
config SPI_NXP_FLEXSPI config SPI_NXP_FLEXSPI
...@@ -465,9 +477,9 @@ config SPI_MTK_NOR ...@@ -465,9 +477,9 @@ config SPI_MTK_NOR
depends on ARCH_MEDIATEK || COMPILE_TEST depends on ARCH_MEDIATEK || COMPILE_TEST
help help
This enables support for SPI NOR controller found on MediaTek This enables support for SPI NOR controller found on MediaTek
ARM SoCs. This is a controller specifically for SPI-NOR flash. ARM SoCs. This is a controller specifically for SPI NOR flash.
It can perform generic SPI transfers up to 6 bytes via generic It can perform generic SPI transfers up to 6 bytes via generic
SPI interface as well as several SPI-NOR specific instructions SPI interface as well as several SPI NOR specific instructions
via SPI MEM interface. via SPI MEM interface.
config SPI_NPCM_FIU config SPI_NPCM_FIU
...@@ -489,11 +501,11 @@ config SPI_NPCM_PSPI ...@@ -489,11 +501,11 @@ config SPI_NPCM_PSPI
config SPI_LANTIQ_SSC config SPI_LANTIQ_SSC
tristate "Lantiq SSC SPI controller" tristate "Lantiq SSC SPI controller"
depends on LANTIQ || COMPILE_TEST depends on LANTIQ || X86 || COMPILE_TEST
help help
This driver supports the Lantiq SSC SPI controller in master This driver supports the Lantiq SSC SPI controller in master
mode. This controller is found on Intel (former Lantiq) SoCs like mode. This controller is found on Intel (former Lantiq) SoCs like
the Danube, Falcon, xRX200, xRX300. the Danube, Falcon, xRX200, xRX300, Lightning Mountain.
config SPI_OC_TINY config SPI_OC_TINY
tristate "OpenCores tiny SPI" tristate "OpenCores tiny SPI"
...@@ -605,6 +617,12 @@ config SPI_RB4XX ...@@ -605,6 +617,12 @@ config SPI_RB4XX
help help
SPI controller driver for the Mikrotik RB4xx series boards. SPI controller driver for the Mikrotik RB4xx series boards.
config SPI_RPCIF
tristate "Renesas RPC-IF SPI driver"
depends on RENESAS_RPCIF
help
SPI driver for Renesas R-Car Gen3 RPC-IF.
config SPI_RSPI config SPI_RSPI
tristate "Renesas RSPI/QSPI controller" tristate "Renesas RSPI/QSPI controller"
depends on SUPERH || ARCH_RENESAS || COMPILE_TEST depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
......
...@@ -31,6 +31,7 @@ obj-$(CONFIG_SPI_BCM_QSPI) += spi-iproc-qspi.o spi-brcmstb-qspi.o spi-bcm-qspi. ...@@ -31,6 +31,7 @@ obj-$(CONFIG_SPI_BCM_QSPI) += spi-iproc-qspi.o spi-brcmstb-qspi.o spi-bcm-qspi.
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
obj-$(CONFIG_SPI_CADENCE) += spi-cadence.o obj-$(CONFIG_SPI_CADENCE) += spi-cadence.o
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += spi-cadence-quadspi.o
obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
...@@ -92,6 +93,7 @@ obj-$(CONFIG_SPI_QCOM_QSPI) += spi-qcom-qspi.o ...@@ -92,6 +93,7 @@ obj-$(CONFIG_SPI_QCOM_QSPI) += spi-qcom-qspi.o
obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_QUP) += spi-qup.o
obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
spi-s3c24xx-hw-y := spi-s3c24xx.o spi-s3c24xx-hw-y := spi-s3c24xx.o
......
...@@ -285,6 +285,12 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem, ...@@ -285,6 +285,12 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem,
op->dummy.nbytes == 0) op->dummy.nbytes == 0)
return false; return false;
/* DTR ops not supported. */
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
return false;
if (op->cmd.nbytes != 1)
return false;
return true; return true;
} }
...@@ -424,10 +430,10 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) ...@@ -424,10 +430,10 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
/* Send/Receive data */ /* Send/Receive data */
if (op->data.dir == SPI_MEM_DATA_IN) if (op->data.dir == SPI_MEM_DATA_IN)
_memcpy_fromio(op->data.buf.in, aq->mem + offset, memcpy_fromio(op->data.buf.in, aq->mem + offset,
op->data.nbytes); op->data.nbytes);
else else
_memcpy_toio(aq->mem + offset, op->data.buf.out, memcpy_toio(aq->mem + offset, op->data.buf.out,
op->data.nbytes); op->data.nbytes);
/* Release the chip-select */ /* Release the chip-select */
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/altera.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -40,19 +41,61 @@ ...@@ -40,19 +41,61 @@
#define ALTERA_SPI_CONTROL_IE_MSK 0x100 #define ALTERA_SPI_CONTROL_IE_MSK 0x100
#define ALTERA_SPI_CONTROL_SSO_MSK 0x400 #define ALTERA_SPI_CONTROL_SSO_MSK 0x400
#define ALTERA_SPI_MAX_CS 32
enum altera_spi_type {
ALTERA_SPI_TYPE_UNKNOWN,
ALTERA_SPI_TYPE_SUBDEV,
};
struct altera_spi { struct altera_spi {
void __iomem *base;
int irq; int irq;
int len; int len;
int count; int count;
int bytes_per_word; int bytes_per_word;
unsigned long imr; u32 imr;
/* data buffers */ /* data buffers */
const unsigned char *tx; const unsigned char *tx;
unsigned char *rx; unsigned char *rx;
struct regmap *regmap;
u32 regoff;
struct device *dev;
};
static const struct regmap_config spi_altera_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.fast_io = true,
}; };
static int altr_spi_writel(struct altera_spi *hw, unsigned int reg,
unsigned int val)
{
int ret;
ret = regmap_write(hw->regmap, hw->regoff + reg, val);
if (ret)
dev_err(hw->dev, "fail to write reg 0x%x val 0x%x: %d\n",
reg, val, ret);
return ret;
}
static int altr_spi_readl(struct altera_spi *hw, unsigned int reg,
unsigned int *val)
{
int ret;
ret = regmap_read(hw->regmap, hw->regoff + reg, val);
if (ret)
dev_err(hw->dev, "fail to read reg 0x%x: %d\n", reg, ret);
return ret;
}
static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev) static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
{ {
return spi_master_get_devdata(sdev->master); return spi_master_get_devdata(sdev->master);
...@@ -64,12 +107,13 @@ static void altera_spi_set_cs(struct spi_device *spi, bool is_high) ...@@ -64,12 +107,13 @@ static void altera_spi_set_cs(struct spi_device *spi, bool is_high)
if (is_high) { if (is_high) {
hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK; hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
writel(0, hw->base + ALTERA_SPI_SLAVE_SEL); altr_spi_writel(hw, ALTERA_SPI_SLAVE_SEL, 0);
} else { } else {
writel(BIT(spi->chip_select), hw->base + ALTERA_SPI_SLAVE_SEL); altr_spi_writel(hw, ALTERA_SPI_SLAVE_SEL,
BIT(spi->chip_select));
hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK; hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
} }
} }
...@@ -86,17 +130,24 @@ static void altera_spi_tx_word(struct altera_spi *hw) ...@@ -86,17 +130,24 @@ static void altera_spi_tx_word(struct altera_spi *hw)
txd = (hw->tx[hw->count * 2] txd = (hw->tx[hw->count * 2]
| (hw->tx[hw->count * 2 + 1] << 8)); | (hw->tx[hw->count * 2 + 1] << 8));
break; break;
case 4:
txd = (hw->tx[hw->count * 4]
| (hw->tx[hw->count * 4 + 1] << 8)
| (hw->tx[hw->count * 4 + 2] << 16)
| (hw->tx[hw->count * 4 + 3] << 24));
break;
} }
} }
writel(txd, hw->base + ALTERA_SPI_TXDATA); altr_spi_writel(hw, ALTERA_SPI_TXDATA, txd);
} }
static void altera_spi_rx_word(struct altera_spi *hw) static void altera_spi_rx_word(struct altera_spi *hw)
{ {
unsigned int rxd; unsigned int rxd;
rxd = readl(hw->base + ALTERA_SPI_RXDATA); altr_spi_readl(hw, ALTERA_SPI_RXDATA, &rxd);
if (hw->rx) { if (hw->rx) {
switch (hw->bytes_per_word) { switch (hw->bytes_per_word) {
case 1: case 1:
...@@ -106,6 +157,13 @@ static void altera_spi_rx_word(struct altera_spi *hw) ...@@ -106,6 +157,13 @@ static void altera_spi_rx_word(struct altera_spi *hw)
hw->rx[hw->count * 2] = rxd; hw->rx[hw->count * 2] = rxd;
hw->rx[hw->count * 2 + 1] = rxd >> 8; hw->rx[hw->count * 2 + 1] = rxd >> 8;
break; break;
case 4:
hw->rx[hw->count * 4] = rxd;
hw->rx[hw->count * 4 + 1] = rxd >> 8;
hw->rx[hw->count * 4 + 2] = rxd >> 16;
hw->rx[hw->count * 4 + 3] = rxd >> 24;
break;
} }
} }
...@@ -116,6 +174,7 @@ static int altera_spi_txrx(struct spi_master *master, ...@@ -116,6 +174,7 @@ static int altera_spi_txrx(struct spi_master *master,
struct spi_device *spi, struct spi_transfer *t) struct spi_device *spi, struct spi_transfer *t)
{ {
struct altera_spi *hw = spi_master_get_devdata(master); struct altera_spi *hw = spi_master_get_devdata(master);
u32 val;
hw->tx = t->tx_buf; hw->tx = t->tx_buf;
hw->rx = t->rx_buf; hw->rx = t->rx_buf;
...@@ -126,7 +185,7 @@ static int altera_spi_txrx(struct spi_master *master, ...@@ -126,7 +185,7 @@ static int altera_spi_txrx(struct spi_master *master,
if (hw->irq >= 0) { if (hw->irq >= 0) {
/* enable receive interrupt */ /* enable receive interrupt */
hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK; hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
/* send the first byte */ /* send the first byte */
altera_spi_tx_word(hw); altera_spi_tx_word(hw);
...@@ -134,9 +193,13 @@ static int altera_spi_txrx(struct spi_master *master, ...@@ -134,9 +193,13 @@ static int altera_spi_txrx(struct spi_master *master,
while (hw->count < hw->len) { while (hw->count < hw->len) {
altera_spi_tx_word(hw); altera_spi_tx_word(hw);
while (!(readl(hw->base + ALTERA_SPI_STATUS) & for (;;) {
ALTERA_SPI_STATUS_RRDY_MSK)) altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
if (val & ALTERA_SPI_STATUS_RRDY_MSK)
break;
cpu_relax(); cpu_relax();
}
altera_spi_rx_word(hw); altera_spi_rx_word(hw);
} }
...@@ -158,7 +221,7 @@ static irqreturn_t altera_spi_irq(int irq, void *dev) ...@@ -158,7 +221,7 @@ static irqreturn_t altera_spi_irq(int irq, void *dev)
} else { } else {
/* disable receive interrupt */ /* disable receive interrupt */
hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK; hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
spi_finalize_current_transfer(master); spi_finalize_current_transfer(master);
} }
...@@ -168,9 +231,14 @@ static irqreturn_t altera_spi_irq(int irq, void *dev) ...@@ -168,9 +231,14 @@ static irqreturn_t altera_spi_irq(int irq, void *dev)
static int altera_spi_probe(struct platform_device *pdev) static int altera_spi_probe(struct platform_device *pdev)
{ {
const struct platform_device_id *platid = platform_get_device_id(pdev);
struct altera_spi_platform_data *pdata = dev_get_platdata(&pdev->dev);
enum altera_spi_type type = ALTERA_SPI_TYPE_UNKNOWN;
struct altera_spi *hw; struct altera_spi *hw;
struct spi_master *master; struct spi_master *master;
int err = -ENODEV; int err = -ENODEV;
u32 val;
u16 i;
master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi)); master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi));
if (!master) if (!master)
...@@ -178,27 +246,72 @@ static int altera_spi_probe(struct platform_device *pdev) ...@@ -178,27 +246,72 @@ static int altera_spi_probe(struct platform_device *pdev)
/* setup the master state. */ /* setup the master state. */
master->bus_num = pdev->id; master->bus_num = pdev->id;
if (pdata) {
if (pdata->num_chipselect > ALTERA_SPI_MAX_CS) {
dev_err(&pdev->dev,
"Invalid number of chipselect: %hu\n",
pdata->num_chipselect);
return -EINVAL;
}
master->num_chipselect = pdata->num_chipselect;
master->mode_bits = pdata->mode_bits;
master->bits_per_word_mask = pdata->bits_per_word_mask;
} else {
master->num_chipselect = 16; master->num_chipselect = 16;
master->mode_bits = SPI_CS_HIGH; master->mode_bits = SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
}
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
master->transfer_one = altera_spi_txrx; master->transfer_one = altera_spi_txrx;
master->set_cs = altera_spi_set_cs; master->set_cs = altera_spi_set_cs;
hw = spi_master_get_devdata(master); hw = spi_master_get_devdata(master);
hw->dev = &pdev->dev;
if (platid)
type = platid->driver_data;
/* find and map our resources */ /* find and map our resources */
hw->base = devm_platform_ioremap_resource(pdev, 0); if (type == ALTERA_SPI_TYPE_SUBDEV) {
if (IS_ERR(hw->base)) { struct resource *regoff;
err = PTR_ERR(hw->base);
hw->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!hw->regmap) {
dev_err(&pdev->dev, "get regmap failed\n");
goto exit;
}
regoff = platform_get_resource(pdev, IORESOURCE_REG, 0);
if (regoff)
hw->regoff = regoff->start;
} else {
void __iomem *res;
res = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(res)) {
err = PTR_ERR(res);
goto exit; goto exit;
} }
hw->regmap = devm_regmap_init_mmio(&pdev->dev, res,
&spi_altera_config);
if (IS_ERR(hw->regmap)) {
dev_err(&pdev->dev, "regmap mmio init failed\n");
err = PTR_ERR(hw->regmap);
goto exit;
}
}
/* program defaults into the registers */ /* program defaults into the registers */
hw->imr = 0; /* disable spi interrupts */ hw->imr = 0; /* disable spi interrupts */
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
writel(0, hw->base + ALTERA_SPI_STATUS); /* clear status reg */ altr_spi_writel(hw, ALTERA_SPI_STATUS, 0); /* clear status reg */
if (readl(hw->base + ALTERA_SPI_STATUS) & ALTERA_SPI_STATUS_RRDY_MSK) altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
readl(hw->base + ALTERA_SPI_RXDATA); /* flush rxdata */ if (val & ALTERA_SPI_STATUS_RRDY_MSK)
altr_spi_readl(hw, ALTERA_SPI_RXDATA, &val); /* flush rxdata */
/* irq is optional */ /* irq is optional */
hw->irq = platform_get_irq(pdev, 0); hw->irq = platform_get_irq(pdev, 0);
if (hw->irq >= 0) { if (hw->irq >= 0) {
...@@ -211,7 +324,17 @@ static int altera_spi_probe(struct platform_device *pdev) ...@@ -211,7 +324,17 @@ static int altera_spi_probe(struct platform_device *pdev)
err = devm_spi_register_master(&pdev->dev, master); err = devm_spi_register_master(&pdev->dev, master);
if (err) if (err)
goto exit; goto exit;
dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
if (pdata) {
for (i = 0; i < pdata->num_devices; i++) {
if (!spi_new_device(master, pdata->devices + i))
dev_warn(&pdev->dev,
"unable to create SPI device: %s\n",
pdata->devices[i].modalias);
}
}
dev_info(&pdev->dev, "regoff %u, irq %d\n", hw->regoff, hw->irq);
return 0; return 0;
exit: exit:
...@@ -228,6 +351,13 @@ static const struct of_device_id altera_spi_match[] = { ...@@ -228,6 +351,13 @@ static const struct of_device_id altera_spi_match[] = {
MODULE_DEVICE_TABLE(of, altera_spi_match); MODULE_DEVICE_TABLE(of, altera_spi_match);
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
static const struct platform_device_id altera_spi_ids[] = {
{ DRV_NAME, ALTERA_SPI_TYPE_UNKNOWN },
{ "subdev_spi_altera", ALTERA_SPI_TYPE_SUBDEV },
{ }
};
MODULE_DEVICE_TABLE(platform, altera_spi_ids);
static struct platform_driver altera_spi_driver = { static struct platform_driver altera_spi_driver = {
.probe = altera_spi_probe, .probe = altera_spi_probe,
.driver = { .driver = {
...@@ -235,6 +365,7 @@ static struct platform_driver altera_spi_driver = { ...@@ -235,6 +365,7 @@ static struct platform_driver altera_spi_driver = {
.pm = NULL, .pm = NULL,
.of_match_table = of_match_ptr(altera_spi_match), .of_match_table = of_match_ptr(altera_spi_match),
}, },
.id_table = altera_spi_ids,
}; };
module_platform_driver(altera_spi_driver); module_platform_driver(altera_spi_driver);
......
...@@ -294,11 +294,13 @@ static int amd_spi_probe(struct platform_device *pdev) ...@@ -294,11 +294,13 @@ static int amd_spi_probe(struct platform_device *pdev)
return err; return err;
} }
#ifdef CONFIG_ACPI
static const struct acpi_device_id spi_acpi_match[] = { static const struct acpi_device_id spi_acpi_match[] = {
{ "AMDI0061", 0 }, { "AMDI0061", 0 },
{}, {},
}; };
MODULE_DEVICE_TABLE(acpi, spi_acpi_match); MODULE_DEVICE_TABLE(acpi, spi_acpi_match);
#endif
static struct platform_driver amd_spi_driver = { static struct platform_driver amd_spi_driver = {
.driver = { .driver = {
......
...@@ -681,13 +681,6 @@ static const struct dev_pm_ops at91_usart_spi_pm_ops = { ...@@ -681,13 +681,6 @@ static const struct dev_pm_ops at91_usart_spi_pm_ops = {
at91_usart_spi_runtime_resume, NULL) at91_usart_spi_runtime_resume, NULL)
}; };
static const struct of_device_id at91_usart_spi_dt_ids[] = {
{ .compatible = "microchip,at91sam9g45-usart-spi"},
{ /* sentinel */}
};
MODULE_DEVICE_TABLE(of, at91_usart_spi_dt_ids);
static struct platform_driver at91_usart_spi_driver = { static struct platform_driver at91_usart_spi_driver = {
.driver = { .driver = {
.name = "at91_usart_spi", .name = "at91_usart_spi",
......
...@@ -1546,10 +1546,9 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1546,10 +1546,9 @@ static int atmel_spi_probe(struct platform_device *pdev)
return PTR_ERR(clk); return PTR_ERR(clk);
/* setup spi core then atmel-specific driver state */ /* setup spi core then atmel-specific driver state */
ret = -ENOMEM;
master = spi_alloc_master(&pdev->dev, sizeof(*as)); master = spi_alloc_master(&pdev->dev, sizeof(*as));
if (!master) if (!master)
goto out_free; return -ENOMEM;
/* the spi->mode bits understood by this driver: */ /* the spi->mode bits understood by this driver: */
master->use_gpio_descriptors = true; master->use_gpio_descriptors = true;
...@@ -1678,7 +1677,6 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1678,7 +1677,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
clk_disable_unprepare(clk); clk_disable_unprepare(clk);
out_free_irq: out_free_irq:
out_unmap_regs: out_unmap_regs:
out_free:
spi_master_put(master); spi_master_put(master);
return ret; return ret;
} }
......
...@@ -86,6 +86,7 @@ MODULE_PARM_DESC(polling_limit_us, ...@@ -86,6 +86,7 @@ MODULE_PARM_DESC(polling_limit_us,
* @clk: core clock, divided to calculate serial clock * @clk: core clock, divided to calculate serial clock
* @irq: interrupt, signals TX FIFO empty or RX FIFO ¾ full * @irq: interrupt, signals TX FIFO empty or RX FIFO ¾ full
* @tfr: SPI transfer currently processed * @tfr: SPI transfer currently processed
* @ctlr: SPI controller reverse lookup
* @tx_buf: pointer whence next transmitted byte is read * @tx_buf: pointer whence next transmitted byte is read
* @rx_buf: pointer where next received byte is written * @rx_buf: pointer where next received byte is written
* @tx_len: remaining bytes to transmit * @tx_len: remaining bytes to transmit
...@@ -125,6 +126,7 @@ struct bcm2835_spi { ...@@ -125,6 +126,7 @@ struct bcm2835_spi {
struct clk *clk; struct clk *clk;
int irq; int irq;
struct spi_transfer *tfr; struct spi_transfer *tfr;
struct spi_controller *ctlr;
const u8 *tx_buf; const u8 *tx_buf;
u8 *rx_buf; u8 *rx_buf;
int tx_len; int tx_len;
...@@ -243,13 +245,13 @@ static inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count) ...@@ -243,13 +245,13 @@ static inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count)
bs->rx_len -= count; bs->rx_len -= count;
while (count > 0) { do {
val = bcm2835_rd(bs, BCM2835_SPI_FIFO); val = bcm2835_rd(bs, BCM2835_SPI_FIFO);
len = min(count, 4); len = min(count, 4);
memcpy(bs->rx_buf, &val, len); memcpy(bs->rx_buf, &val, len);
bs->rx_buf += len; bs->rx_buf += len;
count -= 4; count -= 4;
} } while (count > 0);
} }
/** /**
...@@ -269,7 +271,7 @@ static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) ...@@ -269,7 +271,7 @@ static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count)
bs->tx_len -= count; bs->tx_len -= count;
while (count > 0) { do {
if (bs->tx_buf) { if (bs->tx_buf) {
len = min(count, 4); len = min(count, 4);
memcpy(&val, bs->tx_buf, len); memcpy(&val, bs->tx_buf, len);
...@@ -279,7 +281,7 @@ static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) ...@@ -279,7 +281,7 @@ static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count)
} }
bcm2835_wr(bs, BCM2835_SPI_FIFO, val); bcm2835_wr(bs, BCM2835_SPI_FIFO, val);
count -= 4; count -= 4;
} } while (count > 0);
} }
/** /**
...@@ -308,12 +310,11 @@ static inline void bcm2835_rd_fifo_blind(struct bcm2835_spi *bs, int count) ...@@ -308,12 +310,11 @@ static inline void bcm2835_rd_fifo_blind(struct bcm2835_spi *bs, int count)
count = min(count, bs->rx_len); count = min(count, bs->rx_len);
bs->rx_len -= count; bs->rx_len -= count;
while (count) { do {
val = bcm2835_rd(bs, BCM2835_SPI_FIFO); val = bcm2835_rd(bs, BCM2835_SPI_FIFO);
if (bs->rx_buf) if (bs->rx_buf)
*bs->rx_buf++ = val; *bs->rx_buf++ = val;
count--; } while (--count);
}
} }
/** /**
...@@ -328,16 +329,14 @@ static inline void bcm2835_wr_fifo_blind(struct bcm2835_spi *bs, int count) ...@@ -328,16 +329,14 @@ static inline void bcm2835_wr_fifo_blind(struct bcm2835_spi *bs, int count)
count = min(count, bs->tx_len); count = min(count, bs->tx_len);
bs->tx_len -= count; bs->tx_len -= count;
while (count) { do {
val = bs->tx_buf ? *bs->tx_buf++ : 0; val = bs->tx_buf ? *bs->tx_buf++ : 0;
bcm2835_wr(bs, BCM2835_SPI_FIFO, val); bcm2835_wr(bs, BCM2835_SPI_FIFO, val);
count--; } while (--count);
}
} }
static void bcm2835_spi_reset_hw(struct spi_controller *ctlr) static void bcm2835_spi_reset_hw(struct bcm2835_spi *bs)
{ {
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
/* Disable SPI interrupts and transfer */ /* Disable SPI interrupts and transfer */
...@@ -363,8 +362,7 @@ static void bcm2835_spi_reset_hw(struct spi_controller *ctlr) ...@@ -363,8 +362,7 @@ static void bcm2835_spi_reset_hw(struct spi_controller *ctlr)
static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
{ {
struct spi_controller *ctlr = dev_id; struct bcm2835_spi *bs = dev_id;
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
/* /*
...@@ -386,9 +384,9 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) ...@@ -386,9 +384,9 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
if (!bs->rx_len) { if (!bs->rx_len) {
/* Transfer complete - reset SPI HW */ /* Transfer complete - reset SPI HW */
bcm2835_spi_reset_hw(ctlr); bcm2835_spi_reset_hw(bs);
/* wake up the framework */ /* wake up the framework */
complete(&ctlr->xfer_completion); complete(&bs->ctlr->xfer_completion);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -607,7 +605,7 @@ static void bcm2835_spi_dma_rx_done(void *data) ...@@ -607,7 +605,7 @@ static void bcm2835_spi_dma_rx_done(void *data)
bcm2835_spi_undo_prologue(bs); bcm2835_spi_undo_prologue(bs);
/* reset fifo and HW */ /* reset fifo and HW */
bcm2835_spi_reset_hw(ctlr); bcm2835_spi_reset_hw(bs);
/* and mark as completed */; /* and mark as completed */;
complete(&ctlr->xfer_completion); complete(&ctlr->xfer_completion);
...@@ -641,7 +639,7 @@ static void bcm2835_spi_dma_tx_done(void *data) ...@@ -641,7 +639,7 @@ static void bcm2835_spi_dma_tx_done(void *data)
dmaengine_terminate_async(ctlr->dma_rx); dmaengine_terminate_async(ctlr->dma_rx);
bcm2835_spi_undo_prologue(bs); bcm2835_spi_undo_prologue(bs);
bcm2835_spi_reset_hw(ctlr); bcm2835_spi_reset_hw(bs);
complete(&ctlr->xfer_completion); complete(&ctlr->xfer_completion);
} }
...@@ -825,14 +823,14 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, ...@@ -825,14 +823,14 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
if (!bs->rx_buf && !bs->tx_dma_active && if (!bs->rx_buf && !bs->tx_dma_active &&
cmpxchg(&bs->rx_dma_active, true, false)) { cmpxchg(&bs->rx_dma_active, true, false)) {
dmaengine_terminate_async(ctlr->dma_rx); dmaengine_terminate_async(ctlr->dma_rx);
bcm2835_spi_reset_hw(ctlr); bcm2835_spi_reset_hw(bs);
} }
/* wait for wakeup in framework */ /* wait for wakeup in framework */
return 1; return 1;
err_reset_hw: err_reset_hw:
bcm2835_spi_reset_hw(ctlr); bcm2835_spi_reset_hw(bs);
bcm2835_spi_undo_prologue(bs); bcm2835_spi_undo_prologue(bs);
return ret; return ret;
} }
...@@ -1074,7 +1072,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_controller *ctlr, ...@@ -1074,7 +1072,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_controller *ctlr,
} }
/* Transfer complete - reset SPI HW */ /* Transfer complete - reset SPI HW */
bcm2835_spi_reset_hw(ctlr); bcm2835_spi_reset_hw(bs);
/* and return without waiting for completion */ /* and return without waiting for completion */
return 0; return 0;
} }
...@@ -1084,7 +1082,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, ...@@ -1084,7 +1082,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
struct spi_transfer *tfr) struct spi_transfer *tfr)
{ {
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
unsigned long spi_hz, clk_hz, cdiv, spi_used_hz; unsigned long spi_hz, clk_hz, cdiv;
unsigned long hz_per_byte, byte_limit; unsigned long hz_per_byte, byte_limit;
u32 cs = bs->prepare_cs[spi->chip_select]; u32 cs = bs->prepare_cs[spi->chip_select];
...@@ -1104,7 +1102,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, ...@@ -1104,7 +1102,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
} else { } else {
cdiv = 0; /* 0 is the slowest we can go */ cdiv = 0; /* 0 is the slowest we can go */
} }
spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536); tfr->effective_speed_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
/* handle all the 3-wire mode */ /* handle all the 3-wire mode */
...@@ -1124,7 +1122,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, ...@@ -1124,7 +1122,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
* per 300,000 Hz of bus clock. * per 300,000 Hz of bus clock.
*/ */
hz_per_byte = polling_limit_us ? (9 * 1000000) / polling_limit_us : 0; hz_per_byte = polling_limit_us ? (9 * 1000000) / polling_limit_us : 0;
byte_limit = hz_per_byte ? spi_used_hz / hz_per_byte : 1; byte_limit = hz_per_byte ? tfr->effective_speed_hz / hz_per_byte : 1;
/* run in polling mode for short transfers */ /* run in polling mode for short transfers */
if (tfr->len < byte_limit) if (tfr->len < byte_limit)
...@@ -1182,7 +1180,7 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr, ...@@ -1182,7 +1180,7 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr,
bcm2835_spi_undo_prologue(bs); bcm2835_spi_undo_prologue(bs);
/* and reset */ /* and reset */
bcm2835_spi_reset_hw(ctlr); bcm2835_spi_reset_hw(bs);
} }
static int chip_match_name(struct gpio_chip *chip, void *data) static int chip_match_name(struct gpio_chip *chip, void *data)
...@@ -1311,6 +1309,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ...@@ -1311,6 +1309,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
ctlr->dev.of_node = pdev->dev.of_node; ctlr->dev.of_node = pdev->dev.of_node;
bs = spi_controller_get_devdata(ctlr); bs = spi_controller_get_devdata(ctlr);
bs->ctlr = ctlr;
bs->regs = devm_platform_ioremap_resource(pdev, 0); bs->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bs->regs)) { if (IS_ERR(bs->regs)) {
...@@ -1345,7 +1344,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ...@@ -1345,7 +1344,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0, err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
dev_name(&pdev->dev), ctlr); dev_name(&pdev->dev), bs);
if (err) { if (err) {
dev_err(&pdev->dev, "could not request IRQ: %d\n", err); dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
goto out_dma_release; goto out_dma_release;
......
...@@ -345,7 +345,7 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, ...@@ -345,7 +345,7 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
struct spi_transfer *tfr) struct spi_transfer *tfr)
{ {
struct bcm2835aux_spi *bs = spi_master_get_devdata(master); struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
unsigned long spi_hz, clk_hz, speed, spi_used_hz; unsigned long spi_hz, clk_hz, speed;
unsigned long hz_per_byte, byte_limit; unsigned long hz_per_byte, byte_limit;
/* calculate the registers to handle /* calculate the registers to handle
...@@ -374,7 +374,7 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, ...@@ -374,7 +374,7 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
/* set the new speed */ /* set the new speed */
bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT; bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
spi_used_hz = clk_hz / (2 * (speed + 1)); tfr->effective_speed_hz = clk_hz / (2 * (speed + 1));
/* set transmit buffers and length */ /* set transmit buffers and length */
bs->tx_buf = tfr->tx_buf; bs->tx_buf = tfr->tx_buf;
...@@ -391,7 +391,7 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, ...@@ -391,7 +391,7 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
* 30 µs per 300,000 Hz of bus clock. * 30 µs per 300,000 Hz of bus clock.
*/ */
hz_per_byte = polling_limit_us ? (9 * 1000000) / polling_limit_us : 0; hz_per_byte = polling_limit_us ? (9 * 1000000) / polling_limit_us : 0;
byte_limit = hz_per_byte ? spi_used_hz / hz_per_byte : 1; byte_limit = hz_per_byte ? tfr->effective_speed_hz / hz_per_byte : 1;
/* run in polling mode for short transfers */ /* run in polling mode for short transfers */
if (tfr->len < byte_limit) if (tfr->len < byte_limit)
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/reset.h>
#define HSSPI_GLOBAL_CTRL_REG 0x0 #define HSSPI_GLOBAL_CTRL_REG 0x0
#define GLOBAL_CTRL_CS_POLARITY_SHIFT 0 #define GLOBAL_CTRL_CS_POLARITY_SHIFT 0
...@@ -334,6 +335,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) ...@@ -334,6 +335,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
struct clk *clk, *pll_clk = NULL; struct clk *clk, *pll_clk = NULL;
int irq, ret; int irq, ret;
u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS; u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS;
struct reset_control *reset;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
...@@ -348,10 +350,20 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) ...@@ -348,10 +350,20 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
if (IS_ERR(clk)) if (IS_ERR(clk))
return PTR_ERR(clk); return PTR_ERR(clk);
reset = devm_reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(reset))
return PTR_ERR(reset);
ret = clk_prepare_enable(clk); ret = clk_prepare_enable(clk);
if (ret) if (ret)
return ret; return ret;
ret = reset_control_reset(reset);
if (ret) {
dev_err(dev, "unable to reset device: %d\n", ret);
goto out_disable_clk;
}
rate = clk_get_rate(clk); rate = clk_get_rate(clk);
if (!rate) { if (!rate) {
pll_clk = devm_clk_get(dev, "pll"); pll_clk = devm_clk_get(dev, "pll");
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/reset.h>
/* BCM 6338/6348 SPI core */ /* BCM 6338/6348 SPI core */
#define SPI_6348_RSET_SIZE 64 #define SPI_6348_RSET_SIZE 64
...@@ -493,6 +494,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) ...@@ -493,6 +494,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
struct bcm63xx_spi *bs; struct bcm63xx_spi *bs;
int ret; int ret;
u32 num_cs = BCM63XX_SPI_MAX_CS; u32 num_cs = BCM63XX_SPI_MAX_CS;
struct reset_control *reset;
if (dev->of_node) { if (dev->of_node) {
const struct of_device_id *match; const struct of_device_id *match;
...@@ -529,6 +531,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) ...@@ -529,6 +531,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
return PTR_ERR(clk); return PTR_ERR(clk);
} }
reset = devm_reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(reset))
return PTR_ERR(reset);
master = spi_alloc_master(dev, sizeof(*bs)); master = spi_alloc_master(dev, sizeof(*bs));
if (!master) { if (!master) {
dev_err(dev, "out of memory\n"); dev_err(dev, "out of memory\n");
...@@ -579,6 +585,12 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) ...@@ -579,6 +585,12 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
if (ret) if (ret)
goto out_err; goto out_err;
ret = reset_control_reset(reset);
if (ret) {
dev_err(dev, "unable to reset device: %d\n", ret);
goto out_clk_disable;
}
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
/* register and we are done */ /* register and we are done */
......
...@@ -174,7 +174,7 @@ int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -174,7 +174,7 @@ int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
} }
EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer); EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer);
/** /*
* spi_bitbang_setup - default setup for per-word I/O loops * spi_bitbang_setup - default setup for per-word I/O loops
*/ */
int spi_bitbang_setup(struct spi_device *spi) int spi_bitbang_setup(struct spi_device *spi)
...@@ -208,7 +208,7 @@ int spi_bitbang_setup(struct spi_device *spi) ...@@ -208,7 +208,7 @@ int spi_bitbang_setup(struct spi_device *spi)
} }
EXPORT_SYMBOL_GPL(spi_bitbang_setup); EXPORT_SYMBOL_GPL(spi_bitbang_setup);
/** /*
* spi_bitbang_cleanup - default cleanup for per-word I/O loops * spi_bitbang_cleanup - default cleanup for per-word I/O loops
*/ */
void spi_bitbang_cleanup(struct spi_device *spi) void spi_bitbang_cleanup(struct spi_device *spi)
...@@ -427,7 +427,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) ...@@ -427,7 +427,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
} }
EXPORT_SYMBOL_GPL(spi_bitbang_start); EXPORT_SYMBOL_GPL(spi_bitbang_start);
/** /*
* spi_bitbang_stop - stops the task providing spi communication * spi_bitbang_stop - stops the task providing spi communication
*/ */
void spi_bitbang_stop(struct spi_bitbang *bitbang) void spi_bitbang_stop(struct spi_bitbang *bitbang)
......
...@@ -556,7 +556,7 @@ static int cdns_spi_probe(struct platform_device *pdev) ...@@ -556,7 +556,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
master->set_cs = cdns_spi_chipselect; master->set_cs = cdns_spi_chipselect;
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
master->mode_bits = SPI_CPOL | SPI_CPHA; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
/* Set to default valid value */ /* Set to default valid value */
master->max_speed_hz = clk_get_rate(xspi->ref_clk) / 4; master->max_speed_hz = clk_get_rate(xspi->ref_clk) / 4;
......
...@@ -64,6 +64,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev, ...@@ -64,6 +64,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
p->sys_freq = SYS_FREQ_DEFAULT; p->sys_freq = SYS_FREQ_DEFAULT;
dev_info(dev, "Set system clock to %u\n", p->sys_freq); dev_info(dev, "Set system clock to %u\n", p->sys_freq);
master->flags = SPI_MASTER_HALF_DUPLEX;
master->num_chipselect = 4; master->num_chipselect = 4;
master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH |
SPI_LSB_FIRST | SPI_3WIRE; SPI_LSB_FIRST | SPI_3WIRE;
......
...@@ -387,7 +387,7 @@ static int mcfqspi_probe(struct platform_device *pdev) ...@@ -387,7 +387,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
status = PTR_ERR(mcfqspi->clk); status = PTR_ERR(mcfqspi->clk);
goto fail0; goto fail0;
} }
clk_enable(mcfqspi->clk); clk_prepare_enable(mcfqspi->clk);
master->bus_num = pdata->bus_num; master->bus_num = pdata->bus_num;
master->num_chipselect = pdata->num_chipselect; master->num_chipselect = pdata->num_chipselect;
...@@ -425,7 +425,7 @@ static int mcfqspi_probe(struct platform_device *pdev) ...@@ -425,7 +425,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
mcfqspi_cs_teardown(mcfqspi); mcfqspi_cs_teardown(mcfqspi);
fail1: fail1:
clk_disable(mcfqspi->clk); clk_disable_unprepare(mcfqspi->clk);
fail0: fail0:
spi_master_put(master); spi_master_put(master);
......
...@@ -236,7 +236,8 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -236,7 +236,8 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
/** /**
* davinci_spi_get_prescale - Calculates the correct prescale value * davinci_spi_get_prescale - Calculates the correct prescale value
* @maxspeed_hz: the maximum rate the SPI clock can run at * @dspi: the controller data
* @max_speed_hz: the maximum rate the SPI clock can run at
* *
* This function calculates the prescale value that generates a clock rate * This function calculates the prescale value that generates a clock rate
* less than or equal to the specified maximum. * less than or equal to the specified maximum.
...@@ -711,7 +712,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -711,7 +712,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
/** /**
* dummy_thread_fn - dummy thread function * dummy_thread_fn - dummy thread function
* @irq: IRQ number for this SPI Master * @irq: IRQ number for this SPI Master
* @context_data: structure for SPI Master controller davinci_spi * @data: structure for SPI Master controller davinci_spi
* *
* This is to satisfy the request_threaded_irq() API so that the irq * This is to satisfy the request_threaded_irq() API so that the irq
* handler is called in interrupt context. * handler is called in interrupt context.
...@@ -724,7 +725,7 @@ static irqreturn_t dummy_thread_fn(s32 irq, void *data) ...@@ -724,7 +725,7 @@ static irqreturn_t dummy_thread_fn(s32 irq, void *data)
/** /**
* davinci_spi_irq - Interrupt handler for SPI Master Controller * davinci_spi_irq - Interrupt handler for SPI Master Controller
* @irq: IRQ number for this SPI Master * @irq: IRQ number for this SPI Master
* @context_data: structure for SPI Master controller davinci_spi * @data: structure for SPI Master controller davinci_spi
* *
* ISR will determine that interrupt arrives either for READ or WRITE command. * ISR will determine that interrupt arrives either for READ or WRITE command.
* According to command it will do the appropriate action. It will check * According to command it will do the appropriate action. It will check
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* For more information about the SPI controller see documentation on Cirrus * For more information about the SPI controller see documentation on Cirrus
* Logic web site: * Logic web site:
* http://www.cirrus.com/en/pubs/manual/EP93xx_Users_Guide_UM1.pdf * https://www.cirrus.com/en/pubs/manual/EP93xx_Users_Guide_UM1.pdf
*/ */
#include <linux/io.h> #include <linux/io.h>
...@@ -214,7 +214,7 @@ static void ep93xx_do_read(struct spi_master *master) ...@@ -214,7 +214,7 @@ static void ep93xx_do_read(struct spi_master *master)
/** /**
* ep93xx_spi_read_write() - perform next RX/TX transfer * ep93xx_spi_read_write() - perform next RX/TX transfer
* @espi: ep93xx SPI controller struct * @master: SPI master
* *
* This function transfers next bytes (or half-words) to/from RX/TX FIFOs. If * This function transfers next bytes (or half-words) to/from RX/TX FIFOs. If
* called several times, the whole transfer will be completed. Returns * called several times, the whole transfer will be completed. Returns
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
...@@ -19,11 +18,9 @@ ...@@ -19,11 +18,9 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/platform_data/dma-imx.h> #include <linux/platform_data/dma-imx.h>
#include <linux/platform_data/spi-imx.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
...@@ -101,6 +98,7 @@ struct fsl_lpspi_data { ...@@ -101,6 +98,7 @@ struct fsl_lpspi_data {
struct clk *clk_ipg; struct clk *clk_ipg;
struct clk *clk_per; struct clk *clk_per;
bool is_slave; bool is_slave;
bool is_only_cs1;
bool is_first_byte; bool is_first_byte;
void *rx_buf; void *rx_buf;
...@@ -122,8 +120,6 @@ struct fsl_lpspi_data { ...@@ -122,8 +120,6 @@ struct fsl_lpspi_data {
bool usedma; bool usedma;
struct completion dma_rx_completion; struct completion dma_rx_completion;
struct completion dma_tx_completion; struct completion dma_tx_completion;
int chipselect[];
}; };
static const struct of_device_id fsl_lpspi_dt_ids[] = { static const struct of_device_id fsl_lpspi_dt_ids[] = {
...@@ -224,20 +220,6 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller) ...@@ -224,20 +220,6 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller)
return 0; return 0;
} }
static int fsl_lpspi_prepare_message(struct spi_controller *controller,
struct spi_message *msg)
{
struct fsl_lpspi_data *fsl_lpspi =
spi_controller_get_devdata(controller);
struct spi_device *spi = msg->spi;
int gpio = fsl_lpspi->chipselect[spi->chip_select];
if (gpio_is_valid(gpio))
gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
return 0;
}
static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
{ {
u8 txfifo_cnt; u8 txfifo_cnt;
...@@ -276,10 +258,9 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi) ...@@ -276,10 +258,9 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi)
temp |= fsl_lpspi->config.bpw - 1; temp |= fsl_lpspi->config.bpw - 1;
temp |= (fsl_lpspi->config.mode & 0x3) << 30; temp |= (fsl_lpspi->config.mode & 0x3) << 30;
temp |= (fsl_lpspi->config.chip_select & 0x3) << 24;
if (!fsl_lpspi->is_slave) { if (!fsl_lpspi->is_slave) {
temp |= fsl_lpspi->config.prescale << 27; temp |= fsl_lpspi->config.prescale << 27;
temp |= (fsl_lpspi->config.chip_select & 0x3) << 24;
/* /*
* Set TCR_CONT will keep SS asserted after current transfer. * Set TCR_CONT will keep SS asserted after current transfer.
* For the first transfer, clear TCR_CONTC to assert SS. * For the first transfer, clear TCR_CONTC to assert SS.
...@@ -440,6 +421,9 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller, ...@@ -440,6 +421,9 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller,
fsl_lpspi->config.mode = spi->mode; fsl_lpspi->config.mode = spi->mode;
fsl_lpspi->config.bpw = t->bits_per_word; fsl_lpspi->config.bpw = t->bits_per_word;
fsl_lpspi->config.speed_hz = t->speed_hz; fsl_lpspi->config.speed_hz = t->speed_hz;
if (fsl_lpspi->is_only_cs1)
fsl_lpspi->config.chip_select = 1;
else
fsl_lpspi->config.chip_select = spi->chip_select; fsl_lpspi->config.chip_select = spi->chip_select;
if (!fsl_lpspi->config.speed_hz) if (!fsl_lpspi->config.speed_hz)
...@@ -831,13 +815,10 @@ static int fsl_lpspi_init_rpm(struct fsl_lpspi_data *fsl_lpspi) ...@@ -831,13 +815,10 @@ static int fsl_lpspi_init_rpm(struct fsl_lpspi_data *fsl_lpspi)
static int fsl_lpspi_probe(struct platform_device *pdev) static int fsl_lpspi_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node;
struct fsl_lpspi_data *fsl_lpspi; struct fsl_lpspi_data *fsl_lpspi;
struct spi_controller *controller; struct spi_controller *controller;
struct spi_imx_master *lpspi_platform_info =
dev_get_platdata(&pdev->dev);
struct resource *res; struct resource *res;
int i, ret, irq; int ret, irq;
u32 temp; u32 temp;
bool is_slave; bool is_slave;
...@@ -857,6 +838,8 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ...@@ -857,6 +838,8 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
fsl_lpspi = spi_controller_get_devdata(controller); fsl_lpspi = spi_controller_get_devdata(controller);
fsl_lpspi->dev = &pdev->dev; fsl_lpspi->dev = &pdev->dev;
fsl_lpspi->is_slave = is_slave; fsl_lpspi->is_slave = is_slave;
fsl_lpspi->is_only_cs1 = of_property_read_bool((&pdev->dev)->of_node,
"fsl,spi-only-use-cs1-sel");
controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
controller->transfer_one = fsl_lpspi_transfer_one; controller->transfer_one = fsl_lpspi_transfer_one;
...@@ -867,35 +850,8 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ...@@ -867,35 +850,8 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
controller->dev.of_node = pdev->dev.of_node; controller->dev.of_node = pdev->dev.of_node;
controller->bus_num = pdev->id; controller->bus_num = pdev->id;
controller->slave_abort = fsl_lpspi_slave_abort; controller->slave_abort = fsl_lpspi_slave_abort;
if (!fsl_lpspi->is_slave)
ret = devm_spi_register_controller(&pdev->dev, controller); controller->use_gpio_descriptors = true;
if (ret < 0) {
dev_err(&pdev->dev, "spi_register_controller error.\n");
goto out_controller_put;
}
if (!fsl_lpspi->is_slave) {
for (i = 0; i < controller->num_chipselect; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
if (!gpio_is_valid(cs_gpio) && lpspi_platform_info)
cs_gpio = lpspi_platform_info->chipselect[i];
fsl_lpspi->chipselect[i] = cs_gpio;
if (!gpio_is_valid(cs_gpio))
continue;
ret = devm_gpio_request(&pdev->dev,
fsl_lpspi->chipselect[i],
DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev, "can't get cs gpios\n");
goto out_controller_put;
}
}
controller->cs_gpios = fsl_lpspi->chipselect;
controller->prepare_message = fsl_lpspi_prepare_message;
}
init_completion(&fsl_lpspi->xfer_done); init_completion(&fsl_lpspi->xfer_done);
...@@ -954,10 +910,21 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ...@@ -954,10 +910,21 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret); dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret);
ret = devm_spi_register_controller(&pdev->dev, controller);
if (ret < 0) {
dev_err(&pdev->dev, "spi_register_controller error.\n");
goto out_pm_get;
}
pm_runtime_mark_last_busy(fsl_lpspi->dev);
pm_runtime_put_autosuspend(fsl_lpspi->dev);
return 0; return 0;
out_pm_get: out_pm_get:
pm_runtime_put_noidle(fsl_lpspi->dev); pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
pm_runtime_put_sync(fsl_lpspi->dev);
pm_runtime_disable(fsl_lpspi->dev);
out_controller_put: out_controller_put:
spi_controller_put(controller); spi_controller_put(controller);
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Yogesh Gaur <yogeshnarayan.gaur@nxp.com> * Yogesh Gaur <yogeshnarayan.gaur@nxp.com>
* Suresh Gupta <suresh.gupta@nxp.com> * Suresh Gupta <suresh.gupta@nxp.com>
* *
* Based on the original fsl-quadspi.c spi-nor driver: * Based on the original fsl-quadspi.c SPI NOR driver:
* Author: Freescale Semiconductor, Inc. * Author: Freescale Semiconductor, Inc.
* *
*/ */
......
...@@ -90,7 +90,7 @@ static void fsl_spi_change_mode(struct spi_device *spi) ...@@ -90,7 +90,7 @@ static void fsl_spi_change_mode(struct spi_device *spi)
{ {
struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
struct spi_mpc8xxx_cs *cs = spi->controller_state; struct spi_mpc8xxx_cs *cs = spi->controller_state;
struct fsl_spi_reg *reg_base = mspi->reg_base; struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
__be32 __iomem *mode = &reg_base->mode; __be32 __iomem *mode = &reg_base->mode;
unsigned long flags; unsigned long flags;
...@@ -291,7 +291,7 @@ static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi, ...@@ -291,7 +291,7 @@ static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
struct spi_transfer *t, unsigned int len) struct spi_transfer *t, unsigned int len)
{ {
u32 word; u32 word;
struct fsl_spi_reg *reg_base = mspi->reg_base; struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
mspi->count = len; mspi->count = len;
...@@ -309,7 +309,7 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t, ...@@ -309,7 +309,7 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
bool is_dma_mapped) bool is_dma_mapped)
{ {
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
struct fsl_spi_reg *reg_base; struct fsl_spi_reg __iomem *reg_base;
unsigned int len = t->len; unsigned int len = t->len;
u8 bits_per_word; u8 bits_per_word;
int ret; int ret;
...@@ -440,7 +440,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master, ...@@ -440,7 +440,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
static int fsl_spi_setup(struct spi_device *spi) static int fsl_spi_setup(struct spi_device *spi)
{ {
struct mpc8xxx_spi *mpc8xxx_spi; struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_spi_reg *reg_base; struct fsl_spi_reg __iomem *reg_base;
int retval; int retval;
u32 hw_mode; u32 hw_mode;
struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi); struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi);
...@@ -495,7 +495,7 @@ static void fsl_spi_cleanup(struct spi_device *spi) ...@@ -495,7 +495,7 @@ static void fsl_spi_cleanup(struct spi_device *spi)
static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
{ {
struct fsl_spi_reg *reg_base = mspi->reg_base; struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
/* We need handle RX first */ /* We need handle RX first */
if (events & SPIE_NE) { if (events & SPIE_NE) {
...@@ -530,7 +530,7 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data) ...@@ -530,7 +530,7 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
struct mpc8xxx_spi *mspi = context_data; struct mpc8xxx_spi *mspi = context_data;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
u32 events; u32 events;
struct fsl_spi_reg *reg_base = mspi->reg_base; struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
/* Get interrupt events(tx/rx) */ /* Get interrupt events(tx/rx) */
events = mpc8xxx_spi_read_reg(&reg_base->event); events = mpc8xxx_spi_read_reg(&reg_base->event);
...@@ -550,7 +550,7 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data) ...@@ -550,7 +550,7 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
{ {
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base; struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
u32 slvsel; u32 slvsel;
u16 cs = spi->chip_select; u16 cs = spi->chip_select;
...@@ -568,7 +568,7 @@ static void fsl_spi_grlib_probe(struct device *dev) ...@@ -568,7 +568,7 @@ static void fsl_spi_grlib_probe(struct device *dev)
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base; struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
int mbits; int mbits;
u32 capabilities; u32 capabilities;
...@@ -594,7 +594,7 @@ static struct spi_master *fsl_spi_probe(struct device *dev, ...@@ -594,7 +594,7 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master; struct spi_master *master;
struct mpc8xxx_spi *mpc8xxx_spi; struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_spi_reg *reg_base; struct fsl_spi_reg __iomem *reg_base;
u32 regval; u32 regval;
int ret = 0; int ret = 0;
......
...@@ -51,7 +51,6 @@ ...@@ -51,7 +51,6 @@
/* M_CMD OP codes for SPI */ /* M_CMD OP codes for SPI */
#define SPI_TX_ONLY 1 #define SPI_TX_ONLY 1
#define SPI_RX_ONLY 2 #define SPI_RX_ONLY 2
#define SPI_FULL_DUPLEX 3
#define SPI_TX_RX 7 #define SPI_TX_RX 7
#define SPI_CS_ASSERT 8 #define SPI_CS_ASSERT 8
#define SPI_CS_DEASSERT 9 #define SPI_CS_DEASSERT 9
...@@ -63,13 +62,6 @@ ...@@ -63,13 +62,6 @@
#define TIMESTAMP_AFTER BIT(3) #define TIMESTAMP_AFTER BIT(3)
#define POST_CMD_DELAY BIT(4) #define POST_CMD_DELAY BIT(4)
enum spi_m_cmd_opcode {
CMD_NONE,
CMD_XFER,
CMD_CS,
CMD_CANCEL,
};
struct spi_geni_master { struct spi_geni_master {
struct geni_se se; struct geni_se se;
struct device *dev; struct device *dev;
...@@ -81,11 +73,13 @@ struct spi_geni_master { ...@@ -81,11 +73,13 @@ struct spi_geni_master {
unsigned int tx_rem_bytes; unsigned int tx_rem_bytes;
unsigned int rx_rem_bytes; unsigned int rx_rem_bytes;
const struct spi_transfer *cur_xfer; const struct spi_transfer *cur_xfer;
struct completion xfer_done; struct completion cs_done;
struct completion cancel_done;
struct completion abort_done;
unsigned int oversampling; unsigned int oversampling;
spinlock_t lock; spinlock_t lock;
enum spi_m_cmd_opcode cur_mcmd;
int irq; int irq;
bool cs_flag;
}; };
static int get_spi_clk_cfg(unsigned int speed_hz, static int get_spi_clk_cfg(unsigned int speed_hz,
...@@ -122,24 +116,26 @@ static void handle_fifo_timeout(struct spi_master *spi, ...@@ -122,24 +116,26 @@ static void handle_fifo_timeout(struct spi_master *spi,
struct spi_message *msg) struct spi_message *msg)
{ {
struct spi_geni_master *mas = spi_master_get_devdata(spi); struct spi_geni_master *mas = spi_master_get_devdata(spi);
unsigned long time_left, flags; unsigned long time_left;
struct geni_se *se = &mas->se; struct geni_se *se = &mas->se;
spin_lock_irqsave(&mas->lock, flags); spin_lock_irq(&mas->lock);
reinit_completion(&mas->xfer_done); reinit_completion(&mas->cancel_done);
mas->cur_mcmd = CMD_CANCEL;
geni_se_cancel_m_cmd(se);
writel(0, se->base + SE_GENI_TX_WATERMARK_REG); writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
spin_unlock_irqrestore(&mas->lock, flags); mas->cur_xfer = NULL;
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ); geni_se_cancel_m_cmd(se);
spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->cancel_done, HZ);
if (time_left) if (time_left)
return; return;
spin_lock_irqsave(&mas->lock, flags); spin_lock_irq(&mas->lock);
reinit_completion(&mas->xfer_done); reinit_completion(&mas->abort_done);
geni_se_abort_m_cmd(se); geni_se_abort_m_cmd(se);
spin_unlock_irqrestore(&mas->lock, flags); spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
time_left = wait_for_completion_timeout(&mas->abort_done, HZ);
if (!time_left) if (!time_left)
dev_err(mas->dev, "Failed to cancel/abort m_cmd\n"); dev_err(mas->dev, "Failed to cancel/abort m_cmd\n");
} }
...@@ -151,18 +147,24 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) ...@@ -151,18 +147,24 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
struct geni_se *se = &mas->se; struct geni_se *se = &mas->se;
unsigned long time_left; unsigned long time_left;
reinit_completion(&mas->xfer_done);
pm_runtime_get_sync(mas->dev);
if (!(slv->mode & SPI_CS_HIGH)) if (!(slv->mode & SPI_CS_HIGH))
set_flag = !set_flag; set_flag = !set_flag;
mas->cur_mcmd = CMD_CS; if (set_flag == mas->cs_flag)
return;
mas->cs_flag = set_flag;
pm_runtime_get_sync(mas->dev);
spin_lock_irq(&mas->lock);
reinit_completion(&mas->cs_done);
if (set_flag) if (set_flag)
geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0); geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0);
else else
geni_se_setup_m_cmd(se, SPI_CS_DEASSERT, 0); geni_se_setup_m_cmd(se, SPI_CS_DEASSERT, 0);
spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ); time_left = wait_for_completion_timeout(&mas->cs_done, HZ);
if (!time_left) if (!time_left)
handle_fifo_timeout(spi, NULL); handle_fifo_timeout(spi, NULL);
...@@ -283,7 +285,7 @@ static int spi_geni_init(struct spi_geni_master *mas) ...@@ -283,7 +285,7 @@ static int spi_geni_init(struct spi_geni_master *mas)
* Hardware programming guide suggests to configure * Hardware programming guide suggests to configure
* RX FIFO RFR level to fifo_depth-2. * RX FIFO RFR level to fifo_depth-2.
*/ */
geni_se_init(se, 0x0, mas->tx_fifo_depth - 2); geni_se_init(se, mas->tx_fifo_depth / 2, mas->tx_fifo_depth - 2);
/* Transmit an entire FIFO worth of data per IRQ */ /* Transmit an entire FIFO worth of data per IRQ */
mas->tx_wm = 1; mas->tx_wm = 1;
ver = geni_se_get_qup_hw_version(se); ver = geni_se_get_qup_hw_version(se);
...@@ -307,6 +309,21 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, ...@@ -307,6 +309,21 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
u32 spi_tx_cfg, len; u32 spi_tx_cfg, len;
struct geni_se *se = &mas->se; struct geni_se *se = &mas->se;
/*
* Ensure that our interrupt handler isn't still running from some
* prior command before we start messing with the hardware behind
* its back. We don't need to _keep_ the lock here since we're only
* worried about racing with out interrupt handler. The SPI core
* already handles making sure that we're not trying to do two
* transfers at once or setting a chip select and doing a transfer
* concurrently.
*
* NOTE: we actually _can't_ hold the lock here because possibly we
* might call clk_set_rate() which needs to be able to sleep.
*/
spin_lock_irq(&mas->lock);
spin_unlock_irq(&mas->lock);
spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG); spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG);
if (xfer->bits_per_word != mas->cur_bits_per_word) { if (xfer->bits_per_word != mas->cur_bits_per_word) {
spi_setup_word_len(mas, mode, xfer->bits_per_word); spi_setup_word_len(mas, mode, xfer->bits_per_word);
...@@ -340,12 +357,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, ...@@ -340,12 +357,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
mas->tx_rem_bytes = 0; mas->tx_rem_bytes = 0;
mas->rx_rem_bytes = 0; mas->rx_rem_bytes = 0;
if (xfer->tx_buf && xfer->rx_buf)
m_cmd = SPI_FULL_DUPLEX;
else if (xfer->tx_buf)
m_cmd = SPI_TX_ONLY;
else if (xfer->rx_buf)
m_cmd = SPI_RX_ONLY;
spi_tx_cfg &= ~CS_TOGGLE; spi_tx_cfg &= ~CS_TOGGLE;
...@@ -356,17 +367,24 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, ...@@ -356,17 +367,24 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
len &= TRANS_LEN_MSK; len &= TRANS_LEN_MSK;
mas->cur_xfer = xfer; mas->cur_xfer = xfer;
if (m_cmd & SPI_TX_ONLY) { if (xfer->tx_buf) {
m_cmd |= SPI_TX_ONLY;
mas->tx_rem_bytes = xfer->len; mas->tx_rem_bytes = xfer->len;
writel(len, se->base + SE_SPI_TX_TRANS_LEN); writel(len, se->base + SE_SPI_TX_TRANS_LEN);
} }
if (m_cmd & SPI_RX_ONLY) { if (xfer->rx_buf) {
m_cmd |= SPI_RX_ONLY;
writel(len, se->base + SE_SPI_RX_TRANS_LEN); writel(len, se->base + SE_SPI_RX_TRANS_LEN);
mas->rx_rem_bytes = xfer->len; mas->rx_rem_bytes = xfer->len;
} }
writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG); writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG);
mas->cur_mcmd = CMD_XFER;
/*
* Lock around right before we start the transfer since our
* interrupt could come in at any time now.
*/
spin_lock_irq(&mas->lock);
geni_se_setup_m_cmd(se, m_cmd, FRAGMENTATION); geni_se_setup_m_cmd(se, m_cmd, FRAGMENTATION);
/* /*
...@@ -376,6 +394,7 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, ...@@ -376,6 +394,7 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
*/ */
if (m_cmd & SPI_TX_ONLY) if (m_cmd & SPI_TX_ONLY)
writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG); writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG);
spin_unlock_irq(&mas->lock);
} }
static int spi_geni_transfer_one(struct spi_master *spi, static int spi_geni_transfer_one(struct spi_master *spi,
...@@ -477,13 +496,17 @@ static irqreturn_t geni_spi_isr(int irq, void *data) ...@@ -477,13 +496,17 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
struct spi_geni_master *mas = spi_master_get_devdata(spi); struct spi_geni_master *mas = spi_master_get_devdata(spi);
struct geni_se *se = &mas->se; struct geni_se *se = &mas->se;
u32 m_irq; u32 m_irq;
unsigned long flags;
if (mas->cur_mcmd == CMD_NONE) m_irq = readl(se->base + SE_GENI_M_IRQ_STATUS);
if (!m_irq)
return IRQ_NONE; return IRQ_NONE;
spin_lock_irqsave(&mas->lock, flags); if (m_irq & (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |
m_irq = readl(se->base + SE_GENI_M_IRQ_STATUS); M_RX_FIFO_RD_ERR_EN | M_RX_FIFO_WR_ERR_EN |
M_TX_FIFO_RD_ERR_EN | M_TX_FIFO_WR_ERR_EN))
dev_warn(mas->dev, "Unexpected IRQ err status %#010x\n", m_irq);
spin_lock(&mas->lock);
if ((m_irq & M_RX_FIFO_WATERMARK_EN) || (m_irq & M_RX_FIFO_LAST_EN)) if ((m_irq & M_RX_FIFO_WATERMARK_EN) || (m_irq & M_RX_FIFO_LAST_EN))
geni_spi_handle_rx(mas); geni_spi_handle_rx(mas);
...@@ -492,20 +515,20 @@ static irqreturn_t geni_spi_isr(int irq, void *data) ...@@ -492,20 +515,20 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
geni_spi_handle_tx(mas); geni_spi_handle_tx(mas);
if (m_irq & M_CMD_DONE_EN) { if (m_irq & M_CMD_DONE_EN) {
if (mas->cur_mcmd == CMD_XFER) if (mas->cur_xfer) {
spi_finalize_current_transfer(spi); spi_finalize_current_transfer(spi);
else if (mas->cur_mcmd == CMD_CS) mas->cur_xfer = NULL;
complete(&mas->xfer_done);
mas->cur_mcmd = CMD_NONE;
/* /*
* If this happens, then a CMD_DONE came before all the Tx * If this happens, then a CMD_DONE came before all the
* buffer bytes were sent out. This is unusual, log this * Tx buffer bytes were sent out. This is unusual, log
* condition and disable the WM interrupt to prevent the * this condition and disable the WM interrupt to
* system from stalling due an interrupt storm. * prevent the system from stalling due an interrupt
* If this happens when all Rx bytes haven't been received, log * storm.
* the condition. *
* The only known time this can happen is if bits_per_word != 8 * If this happens when all Rx bytes haven't been
* and some registers that expect xfer lengths in num spi_words * received, log the condition. The only known time
* this can happen is if bits_per_word != 8 and some
* registers that expect xfer lengths in num spi_words
* weren't written correctly. * weren't written correctly.
*/ */
if (mas->tx_rem_bytes) { if (mas->tx_rem_bytes) {
...@@ -516,15 +539,33 @@ static irqreturn_t geni_spi_isr(int irq, void *data) ...@@ -516,15 +539,33 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
if (mas->rx_rem_bytes) if (mas->rx_rem_bytes)
dev_err(mas->dev, "Premature done. rx_rem = %d bpw%d\n", dev_err(mas->dev, "Premature done. rx_rem = %d bpw%d\n",
mas->rx_rem_bytes, mas->cur_bits_per_word); mas->rx_rem_bytes, mas->cur_bits_per_word);
} else {
complete(&mas->cs_done);
} }
if ((m_irq & M_CMD_CANCEL_EN) || (m_irq & M_CMD_ABORT_EN)) {
mas->cur_mcmd = CMD_NONE;
complete(&mas->xfer_done);
} }
if (m_irq & M_CMD_CANCEL_EN)
complete(&mas->cancel_done);
if (m_irq & M_CMD_ABORT_EN)
complete(&mas->abort_done);
/*
* It's safe or a good idea to Ack all of our our interrupts at the
* end of the function. Specifically:
* - M_CMD_DONE_EN / M_RX_FIFO_LAST_EN: Edge triggered interrupts and
* clearing Acks. Clearing at the end relies on nobody else having
* started a new transfer yet or else we could be clearing _their_
* done bit, but everyone grabs the spinlock before starting a new
* transfer.
* - M_RX_FIFO_WATERMARK_EN / M_TX_FIFO_WATERMARK_EN: These appear
* to be "latched level" interrupts so it's important to clear them
* _after_ you've handled the condition and always safe to do so
* since they'll re-assert if they're still happening.
*/
writel(m_irq, se->base + SE_GENI_M_IRQ_CLEAR); writel(m_irq, se->base + SE_GENI_M_IRQ_CLEAR);
spin_unlock_irqrestore(&mas->lock, flags);
spin_unlock(&mas->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -574,8 +615,12 @@ static int spi_geni_probe(struct platform_device *pdev) ...@@ -574,8 +615,12 @@ static int spi_geni_probe(struct platform_device *pdev)
spi->handle_err = handle_fifo_timeout; spi->handle_err = handle_fifo_timeout;
spi->set_cs = spi_geni_set_cs; spi->set_cs = spi_geni_set_cs;
init_completion(&mas->xfer_done); init_completion(&mas->cs_done);
init_completion(&mas->cancel_done);
init_completion(&mas->abort_done);
spin_lock_init(&mas->lock); spin_lock_init(&mas->lock);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 250);
pm_runtime_enable(dev); pm_runtime_enable(dev);
ret = spi_geni_init(mas); ret = spi_geni_init(mas);
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/gpio.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
...@@ -102,10 +101,6 @@ struct img_spfi { ...@@ -102,10 +101,6 @@ struct img_spfi {
bool rx_dma_busy; bool rx_dma_busy;
}; };
struct img_spfi_device_data {
bool gpio_requested;
};
static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg) static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg)
{ {
return readl(spfi->regs + reg); return readl(spfi->regs + reg);
...@@ -442,54 +437,6 @@ static int img_spfi_unprepare(struct spi_master *master, ...@@ -442,54 +437,6 @@ static int img_spfi_unprepare(struct spi_master *master,
return 0; return 0;
} }
static int img_spfi_setup(struct spi_device *spi)
{
int ret = -EINVAL;
struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
if (!spfi_data) {
spfi_data = kzalloc(sizeof(*spfi_data), GFP_KERNEL);
if (!spfi_data)
return -ENOMEM;
spfi_data->gpio_requested = false;
spi_set_ctldata(spi, spfi_data);
}
if (!spfi_data->gpio_requested) {
ret = gpio_request_one(spi->cs_gpio,
(spi->mode & SPI_CS_HIGH) ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
dev_name(&spi->dev));
if (ret)
dev_err(&spi->dev, "can't request chipselect gpio %d\n",
spi->cs_gpio);
else
spfi_data->gpio_requested = true;
} else {
if (gpio_is_valid(spi->cs_gpio)) {
int mode = ((spi->mode & SPI_CS_HIGH) ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH);
ret = gpio_direction_output(spi->cs_gpio, mode);
if (ret)
dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n",
spi->cs_gpio, ret);
}
}
return ret;
}
static void img_spfi_cleanup(struct spi_device *spi)
{
struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
if (spfi_data) {
if (spfi_data->gpio_requested)
gpio_free(spi->cs_gpio);
kfree(spfi_data);
spi_set_ctldata(spi, NULL);
}
}
static void img_spfi_config(struct spi_master *master, struct spi_device *spi, static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
...@@ -659,12 +606,11 @@ static int img_spfi_probe(struct platform_device *pdev) ...@@ -659,12 +606,11 @@ static int img_spfi_probe(struct platform_device *pdev)
master->max_speed_hz = max_speed_hz; master->max_speed_hz = max_speed_hz;
} }
master->setup = img_spfi_setup;
master->cleanup = img_spfi_cleanup;
master->transfer_one = img_spfi_transfer_one; master->transfer_one = img_spfi_transfer_one;
master->prepare_message = img_spfi_prepare; master->prepare_message = img_spfi_prepare;
master->unprepare_message = img_spfi_unprepare; master->unprepare_message = img_spfi_unprepare;
master->handle_err = img_spfi_handle_err; master->handle_err = img_spfi_handle_err;
master->use_gpio_descriptors = true;
spfi->tx_ch = dma_request_chan(spfi->dev, "tx"); spfi->tx_ch = dma_request_chan(spfi->dev, "tx");
if (IS_ERR(spfi->tx_ch)) { if (IS_ERR(spfi->tx_ch)) {
......
This diff is collapsed.
This diff is collapsed.
...@@ -885,10 +885,10 @@ static int spi_test_run_iter(struct spi_device *spi, ...@@ -885,10 +885,10 @@ static int spi_test_run_iter(struct spi_device *spi,
/** /**
* spi_test_execute_msg - default implementation to run a test * spi_test_execute_msg - default implementation to run a test
* *
* spi: @spi_device on which to run the @spi_message * @spi: @spi_device on which to run the @spi_message
* test: the test to execute, which already contains @msg * @test: the test to execute, which already contains @msg
* tx: the tx buffer allocated for the test sequence * @tx: the tx buffer allocated for the test sequence
* rx: the rx buffer allocated for the test sequence * @rx: the rx buffer allocated for the test sequence
* *
* Returns: error code of spi_sync as well as basic error checking * Returns: error code of spi_sync as well as basic error checking
*/ */
...@@ -957,10 +957,10 @@ EXPORT_SYMBOL_GPL(spi_test_execute_msg); ...@@ -957,10 +957,10 @@ EXPORT_SYMBOL_GPL(spi_test_execute_msg);
* including all the relevant iterations on: * including all the relevant iterations on:
* length and buffer alignment * length and buffer alignment
* *
* spi: the spi_device to send the messages to * @spi: the spi_device to send the messages to
* test: the test which we need to execute * @test: the test which we need to execute
* tx: the tx buffer allocated for the test sequence * @tx: the tx buffer allocated for the test sequence
* rx: the rx buffer allocated for the test sequence * @rx: the rx buffer allocated for the test sequence
* *
* Returns: status code of spi_sync or other failures * Returns: status code of spi_sync or other failures
*/ */
......
...@@ -156,6 +156,12 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, ...@@ -156,6 +156,12 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,
op->data.dir == SPI_MEM_DATA_OUT)) op->data.dir == SPI_MEM_DATA_OUT))
return false; return false;
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
return false;
if (op->cmd.nbytes != 1)
return false;
return true; return true;
} }
EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
...@@ -170,7 +176,7 @@ static bool spi_mem_buswidth_is_valid(u8 buswidth) ...@@ -170,7 +176,7 @@ static bool spi_mem_buswidth_is_valid(u8 buswidth)
static int spi_mem_check_op(const struct spi_mem_op *op) static int spi_mem_check_op(const struct spi_mem_op *op)
{ {
if (!op->cmd.buswidth) if (!op->cmd.buswidth || !op->cmd.nbytes)
return -EINVAL; return -EINVAL;
if ((op->addr.nbytes && !op->addr.buswidth) || if ((op->addr.nbytes && !op->addr.buswidth) ||
...@@ -306,8 +312,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) ...@@ -306,8 +312,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
return ret; return ret;
} }
tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes + tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
op->dummy.nbytes;
/* /*
* Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so * Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so
...@@ -322,7 +327,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) ...@@ -322,7 +327,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
tmpbuf[0] = op->cmd.opcode; tmpbuf[0] = op->cmd.opcode;
xfers[xferpos].tx_buf = tmpbuf; xfers[xferpos].tx_buf = tmpbuf;
xfers[xferpos].len = sizeof(op->cmd.opcode); xfers[xferpos].len = op->cmd.nbytes;
xfers[xferpos].tx_nbits = op->cmd.buswidth; xfers[xferpos].tx_nbits = op->cmd.buswidth;
spi_message_add_tail(&xfers[xferpos], &msg); spi_message_add_tail(&xfers[xferpos], &msg);
xferpos++; xferpos++;
...@@ -424,8 +429,7 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) ...@@ -424,8 +429,7 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
return ctlr->mem_ops->adjust_op_size(mem, op); return ctlr->mem_ops->adjust_op_size(mem, op);
if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) { if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) {
len = sizeof(op->cmd.opcode) + op->addr.nbytes + len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
op->dummy.nbytes;
if (len > spi_max_transfer_size(mem->spi)) if (len > spi_max_transfer_size(mem->spi))
return -EINVAL; return -EINVAL;
......
...@@ -362,8 +362,6 @@ static void meson_spicc_setup_xfer(struct meson_spicc_device *spicc, ...@@ -362,8 +362,6 @@ static void meson_spicc_setup_xfer(struct meson_spicc_device *spicc,
static void meson_spicc_reset_fifo(struct meson_spicc_device *spicc) static void meson_spicc_reset_fifo(struct meson_spicc_device *spicc)
{ {
u32 data;
if (spicc->data->has_oen) if (spicc->data->has_oen)
writel_bits_relaxed(SPICC_ENH_MAIN_CLK_AO, writel_bits_relaxed(SPICC_ENH_MAIN_CLK_AO,
SPICC_ENH_MAIN_CLK_AO, SPICC_ENH_MAIN_CLK_AO,
...@@ -373,7 +371,7 @@ static void meson_spicc_reset_fifo(struct meson_spicc_device *spicc) ...@@ -373,7 +371,7 @@ static void meson_spicc_reset_fifo(struct meson_spicc_device *spicc)
spicc->base + SPICC_TESTREG); spicc->base + SPICC_TESTREG);
while (meson_spicc_rxready(spicc)) while (meson_spicc_rxready(spicc))
data = readl_relaxed(spicc->base + SPICC_RXDATA); readl_relaxed(spicc->base + SPICC_RXDATA);
if (spicc->data->has_oen) if (spicc->data->has_oen)
writel_bits_relaxed(SPICC_ENH_MAIN_CLK_AO, 0, writel_bits_relaxed(SPICC_ENH_MAIN_CLK_AO, 0,
......
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
* @master: the SPI master * @master: the SPI master
* @regmap: regmap for device registers * @regmap: regmap for device registers
* @clk: input clock of the built-in baud rate generator * @clk: input clock of the built-in baud rate generator
* @device: the device structure * @dev: the device structure
*/ */
struct meson_spifc { struct meson_spifc {
struct spi_master *master; struct spi_master *master;
......
...@@ -171,6 +171,9 @@ static const struct of_device_id mtk_spi_of_match[] = { ...@@ -171,6 +171,9 @@ static const struct of_device_id mtk_spi_of_match[] = {
{ .compatible = "mediatek,mt8183-spi", { .compatible = "mediatek,mt8183-spi",
.data = (void *)&mt8183_compat, .data = (void *)&mt8183_compat,
}, },
{ .compatible = "mediatek,mt8192-spi",
.data = (void *)&mt6765_compat,
},
{} {}
}; };
MODULE_DEVICE_TABLE(of, mtk_spi_of_match); MODULE_DEVICE_TABLE(of, mtk_spi_of_match);
......
...@@ -195,7 +195,7 @@ static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) ...@@ -195,7 +195,7 @@ static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
} }
} }
len = MTK_NOR_PRG_MAX_SIZE - sizeof(op->cmd.opcode) - op->addr.nbytes - len = MTK_NOR_PRG_MAX_SIZE - op->cmd.nbytes - op->addr.nbytes -
op->dummy.nbytes; op->dummy.nbytes;
if (op->data.nbytes > len) if (op->data.nbytes > len)
op->data.nbytes = len; op->data.nbytes = len;
...@@ -211,6 +211,12 @@ static bool mtk_nor_supports_op(struct spi_mem *mem, ...@@ -211,6 +211,12 @@ static bool mtk_nor_supports_op(struct spi_mem *mem,
if (op->cmd.buswidth != 1) if (op->cmd.buswidth != 1)
return false; return false;
/* DTR ops not supported. */
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
return false;
if (op->cmd.nbytes != 1)
return false;
if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) { if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) {
if ((op->data.dir == SPI_MEM_DATA_IN) && mtk_nor_match_read(op)) if ((op->data.dir == SPI_MEM_DATA_IN) && mtk_nor_match_read(op))
return true; return true;
...@@ -219,7 +225,7 @@ static bool mtk_nor_supports_op(struct spi_mem *mem, ...@@ -219,7 +225,7 @@ static bool mtk_nor_supports_op(struct spi_mem *mem,
(op->dummy.buswidth == 0) && (op->dummy.buswidth == 0) &&
(op->data.buswidth == 1); (op->data.buswidth == 1);
} }
len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
if ((len > MTK_NOR_PRG_MAX_SIZE) || if ((len > MTK_NOR_PRG_MAX_SIZE) ||
((op->data.nbytes) && (len == MTK_NOR_PRG_MAX_SIZE))) ((op->data.nbytes) && (len == MTK_NOR_PRG_MAX_SIZE)))
return false; return false;
......
...@@ -356,6 +356,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, ...@@ -356,6 +356,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
int nio = 1, i, ret; int nio = 1, i, ret;
u32 ss_ctrl; u32 ss_ctrl;
u8 addr[8]; u8 addr[8];
u8 opcode = op->cmd.opcode;
ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz); ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz);
if (ret) if (ret)
...@@ -393,7 +394,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, ...@@ -393,7 +394,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT, writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT,
mxic->regs + HC_CFG); mxic->regs + HC_CFG);
ret = mxic_spi_data_xfer(mxic, &op->cmd.opcode, NULL, 1); ret = mxic_spi_data_xfer(mxic, &opcode, NULL, 1);
if (ret) if (ret)
goto out; goto out;
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Nuvoton Technology corporation. // Copyright (c) 2019 Nuvoton Technology corporation.
#include <linux/bits.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -177,7 +178,6 @@ enum { ...@@ -177,7 +178,6 @@ enum {
#define MAP_SIZE_16MB 0x1000000 #define MAP_SIZE_16MB 0x1000000
#define MAP_SIZE_8MB 0x800000 #define MAP_SIZE_8MB 0x800000
#define NUM_BITS_IN_BYTE 8
#define FIU_DRD_MAX_DUMMY_NUMBER 3 #define FIU_DRD_MAX_DUMMY_NUMBER 3
#define NPCM_MAX_CHIP_NUM 4 #define NPCM_MAX_CHIP_NUM 4
#define CHUNK_SIZE 16 #define CHUNK_SIZE 16
...@@ -252,8 +252,8 @@ static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu, ...@@ -252,8 +252,8 @@ static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu,
fiu->drd_op.addr.buswidth = op->addr.buswidth; fiu->drd_op.addr.buswidth = op->addr.buswidth;
regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
NPCM_FIU_DRD_CFG_DBW, NPCM_FIU_DRD_CFG_DBW,
((op->dummy.nbytes * ilog2(op->addr.buswidth)) ((op->dummy.nbytes * ilog2(op->addr.buswidth)) / BITS_PER_BYTE)
/ NUM_BITS_IN_BYTE) << NPCM_FIU_DRD_DBW_SHIFT); << NPCM_FIU_DRD_DBW_SHIFT);
fiu->drd_op.dummy.nbytes = op->dummy.nbytes; fiu->drd_op.dummy.nbytes = op->dummy.nbytes;
regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
NPCM_FIU_DRD_CFG_RDCMD, op->cmd.opcode); NPCM_FIU_DRD_CFG_RDCMD, op->cmd.opcode);
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/reset.h> #include <linux/reset.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -344,16 +342,9 @@ static int npcm_pspi_probe(struct platform_device *pdev) ...@@ -344,16 +342,9 @@ static int npcm_pspi_probe(struct platform_device *pdev)
struct npcm_pspi *priv; struct npcm_pspi *priv;
struct spi_master *master; struct spi_master *master;
unsigned long clk_hz; unsigned long clk_hz;
struct device_node *np = pdev->dev.of_node;
int num_cs, i;
int csgpio;
int irq; int irq;
int ret; int ret;
num_cs = of_gpio_named_count(np, "cs-gpios");
if (num_cs < 0)
return num_cs;
master = spi_alloc_master(&pdev->dev, sizeof(*priv)); master = spi_alloc_master(&pdev->dev, sizeof(*priv));
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
...@@ -418,24 +409,7 @@ static int npcm_pspi_probe(struct platform_device *pdev) ...@@ -418,24 +409,7 @@ static int npcm_pspi_probe(struct platform_device *pdev)
npcm_pspi_prepare_transfer_hardware; npcm_pspi_prepare_transfer_hardware;
master->unprepare_transfer_hardware = master->unprepare_transfer_hardware =
npcm_pspi_unprepare_transfer_hardware; npcm_pspi_unprepare_transfer_hardware;
master->num_chipselect = num_cs; master->use_gpio_descriptors = true;
for (i = 0; i < num_cs; i++) {
csgpio = of_get_named_gpio(np, "cs-gpios", i);
if (csgpio < 0) {
dev_err(&pdev->dev, "failed to get csgpio#%u\n", i);
goto out_disable_clk;
}
dev_dbg(&pdev->dev, "csgpio#%u = %d\n", i, csgpio);
ret = devm_gpio_request_one(&pdev->dev, csgpio,
GPIOF_OUT_INIT_HIGH, DRIVER_NAME);
if (ret < 0) {
dev_err(&pdev->dev,
"failed to configure csgpio#%u %d\n"
, i, csgpio);
goto out_disable_clk;
}
}
/* set to default clock rate */ /* set to default clock rate */
npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK); npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* /*
* OpenCores tiny SPI master driver * OpenCores tiny SPI master driver
* *
* http://opencores.org/project,tiny_spi * https://opencores.org/project,tiny_spi
* *
* Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw> * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw>
* *
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
......
...@@ -443,7 +443,7 @@ static void uwire_cleanup(struct spi_device *spi) ...@@ -443,7 +443,7 @@ static void uwire_cleanup(struct spi_device *spi)
static void uwire_off(struct uwire_spi *uwire) static void uwire_off(struct uwire_spi *uwire)
{ {
uwire_write_reg(UWIRE_SR3, 0); uwire_write_reg(UWIRE_SR3, 0);
clk_disable(uwire->ck); clk_disable_unprepare(uwire->ck);
spi_master_put(uwire->bitbang.master); spi_master_put(uwire->bitbang.master);
} }
...@@ -475,7 +475,7 @@ static int uwire_probe(struct platform_device *pdev) ...@@ -475,7 +475,7 @@ static int uwire_probe(struct platform_device *pdev)
spi_master_put(master); spi_master_put(master);
return status; return status;
} }
clk_enable(uwire->ck); clk_prepare_enable(uwire->ck);
if (cpu_is_omap7xx()) if (cpu_is_omap7xx())
uwire_idx_shift = 1; uwire_idx_shift = 1;
......
This diff is collapsed.
...@@ -708,7 +708,7 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -708,7 +708,7 @@ static int orion_spi_probe(struct platform_device *pdev)
/* /*
* Only map one page for direct access. This is enough for the * Only map one page for direct access. This is enough for the
* simple TX transfer which only writes to the first word. * simple TX transfer which only writes to the first word.
* This needs to get extended for the direct SPI-NOR / SPI-NAND * This needs to get extended for the direct SPI NOR / SPI NAND
* support, once this gets implemented. * support, once this gets implemented.
*/ */
dir_acc = &spi->child[cs].direct_access; dir_acc = &spi->child[cs].direct_access;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment