Commit dcc75dde authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi updates from Mark Brown:
 "A fairly quiet release for SPI, the biggest thing is the conversion to
  use GPIO descriptors which is now 90% done but still needs some
  stragglers converting.

  Summary:

   - Support for inter-word delays

   - Conversion of the core and most drivers to use GPIO descriptors for
     GPIO controlled chip selects

   - New drivers for NXP FlexSPI and QuadSPI, SiFive and Spreadtrum"

* tag 'spi-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (104 commits)
  spi: sh-msiof: Restrict bits per word to 8/16/24/32 on R-Car Gen2/3
  spi: sifive: Remove redundant dev_err call in sifive_spi_probe()
  spi: sifive: Remove spi_master_put in sifive_spi_remove()
  spi: spi-gpio: fix SPI_CS_HIGH capability
  spi: pxa2xx: Setup maximum supported DMA transfer length
  spi: sifive: Add driver for the SiFive SPI controller
  spi: sifive: Add DT documentation for SiFive SPI controller
  spi: sprd: Add a prefix for SPI DMA channel macros
  spi: sprd: spi: sprd: Add DMA mode support
  dt-bindings: spi: Add the DMA properties for the SPI dma mode
  spi: sprd: Add the SPI irq function for the SPI DMA mode
  dt-bindings: spi: imx: Add an entry for the i.MX8QM compatible
  spi: use gpio[d]_set_value_cansleep for setting chipselect GPIO
  spi: gpio: Advertise support for SPI_CS_HIGH
  spi: sh-msiof: Replace spi_master by spi_controller
  spi: sh-hspi: Replace spi_master by spi_controller
  spi: rspi: Replace spi_master by spi_controller
  spi: atmel-quadspi: add support for sam9x60 qspi controller
  dt-bindings: spi: atmel-quadspi: QuadSPI driver for Microchip SAM9X60
  spi: atmel-quadspi: add support for named peripheral clock
  ...
parents 32c0ac3a 14dbfb41
* Atmel Quad Serial Peripheral Interface (QSPI) * Atmel Quad Serial Peripheral Interface (QSPI)
Required properties: Required properties:
- compatible: Should be "atmel,sama5d2-qspi". - compatible: Should be one of the following:
- "atmel,sama5d2-qspi"
- "microchip,sam9x60-qspi"
- reg: Should contain the locations and lengths of the base registers - reg: Should contain the locations and lengths of the base registers
and the mapped memory. and the mapped memory.
- reg-names: Should contain the resource reg names: - reg-names: Should contain the resource reg names:
- qspi_base: configuration register address space - qspi_base: configuration register address space
- qspi_mmap: memory mapped address space - qspi_mmap: memory mapped address space
- interrupts: Should contain the interrupt for the device. - interrupts: Should contain the interrupt for the device.
- clocks: The phandle of the clock needed by the QSPI controller. - clocks: Should reference the peripheral clock and the QSPI system
clock if available.
- clock-names: Should contain "pclk" for the peripheral clock and "qspick"
for the system clock when available.
- #address-cells: Should be <1>. - #address-cells: Should be <1>.
- #size-cells: Should be <0>. - #size-cells: Should be <0>.
...@@ -19,7 +24,8 @@ spi@f0020000 { ...@@ -19,7 +24,8 @@ spi@f0020000 {
reg = <0xf0020000 0x100>, <0xd0000000 0x8000000>; reg = <0xf0020000 0x100>, <0xd0000000 0x8000000>;
reg-names = "qspi_base", "qspi_mmap"; reg-names = "qspi_base", "qspi_mmap";
interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>; interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>;
clocks = <&spi0_clk>; clocks = <&pmc PMC_TYPE_PERIPHERAL 52>;
clock-names = "pclk";
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
pinctrl-names = "default"; pinctrl-names = "default";
......
...@@ -10,6 +10,7 @@ Required properties: ...@@ -10,6 +10,7 @@ Required properties:
- "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35 - "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,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,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.MX8M
- reg : Offset and length of the register set for the device - reg : Offset and length of the register set for the device
- interrupts : Should contain CSPI/eCSPI interrupt - interrupts : Should contain CSPI/eCSPI interrupt
- clocks : Clock specifiers for both ipg and per clocks. - clocks : Clock specifiers for both ipg and per clocks.
......
...@@ -14,15 +14,13 @@ Required properties: ...@@ -14,15 +14,13 @@ Required properties:
- clocks : The clocks needed by the QuadSPI controller - clocks : The clocks needed by the QuadSPI controller
- clock-names : Should contain the name of the clocks: "qspi_en" and "qspi". - clock-names : Should contain the name of the clocks: "qspi_en" and "qspi".
Optional properties: Required SPI slave node properties:
- fsl,qspi-has-second-chip: The controller has two buses, bus A and bus B. - reg: There are two buses (A and B) with two chip selects each.
Each bus can be connected with two NOR flashes. This encodes to which bus and CS the flash is connected:
Most of the time, each bus only has one NOR flash <0>: Bus A, CS 0
connected, this is the default case. <1>: Bus A, CS 1
But if there are two NOR flashes connected to the <2>: Bus B, CS 0
bus, you should enable this property. <3>: Bus B, CS 1
(Please check the board's schematic.)
- big-endian : That means the IP register is big endian
Example: Example:
...@@ -40,7 +38,7 @@ qspi0: quadspi@40044000 { ...@@ -40,7 +38,7 @@ qspi0: quadspi@40044000 {
}; };
}; };
Example showing the usage of two SPI NOR devices: Example showing the usage of two SPI NOR devices on bus A:
&qspi2 { &qspi2 {
pinctrl-names = "default"; pinctrl-names = "default";
......
* NXP Flex Serial Peripheral Interface (FSPI)
Required properties:
- compatible : Should be "nxp,lx2160a-fspi"
- reg : First contains the register location and length,
Second contains the memory mapping address and length
- reg-names : Should contain the resource reg names:
- fspi_base: configuration register address space
- fspi_mmap: memory mapped address space
- interrupts : Should contain the interrupt for the device
Required SPI slave node properties:
- reg : There are two buses (A and B) with two chip selects each.
This encodes to which bus and CS the flash is connected:
- <0>: Bus A, CS 0
- <1>: Bus A, CS 1
- <2>: Bus B, CS 0
- <3>: Bus B, CS 1
Example showing the usage of two SPI NOR slave devices on bus A:
fspi0: spi@20c0000 {
compatible = "nxp,lx2160a-fspi";
reg = <0x0 0x20c0000 0x0 0x10000>, <0x0 0x20000000 0x0 0x10000000>;
reg-names = "fspi_base", "fspi_mmap";
interrupts = <0 25 0x4>; /* Level high type */
clocks = <&clockgen 4 3>, <&clockgen 4 3>;
clock-names = "fspi_en", "fspi";
mt35xu512aba0: flash@0 {
reg = <0>;
....
};
mt35xu512aba1: flash@1 {
reg = <1>;
....
};
};
SiFive SPI controller Device Tree Bindings
------------------------------------------
Required properties:
- compatible : Should be "sifive,<chip>-spi" and "sifive,spi<version>".
Supported compatible strings are:
"sifive,fu540-c000-spi" for the SiFive SPI v0 as integrated
onto the SiFive FU540 chip, and "sifive,spi0" for the SiFive
SPI v0 IP block with no chip integration tweaks.
Please refer to sifive-blocks-ip-versioning.txt for details
- reg : Physical base address and size of SPI registers map
A second (optional) range can indicate memory mapped flash
- interrupts : Must contain one entry
- interrupt-parent : Must be core interrupt controller
- clocks : Must reference the frequency given to the controller
- #address-cells : Must be '1', indicating which CS to use
- #size-cells : Must be '0'
Optional properties:
- sifive,fifo-depth : Depth of hardware queues; defaults to 8
- sifive,max-bits-per-word : Maximum bits per word; defaults to 8
SPI RTL that corresponds to the IP block version numbers can be found here:
https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/spi
Example:
spi: spi@10040000 {
compatible = "sifive,fu540-c000-spi", "sifive,spi0";
reg = <0x0 0x10040000 0x0 0x1000 0x0 0x20000000 0x0 0x10000000>;
interrupt-parent = <&plic>;
interrupts = <51>;
clocks = <&tlclk>;
#address-cells = <1>;
#size-cells = <0>;
sifive,fifo-depth = <8>;
sifive,max-bits-per-word = <8>;
};
...@@ -14,6 +14,11 @@ Required properties: ...@@ -14,6 +14,11 @@ Required properties:
address on the SPI bus. Should be set to 1. address on the SPI bus. Should be set to 1.
- #size-cells: Should be set to 0. - #size-cells: Should be set to 0.
Optional properties:
dma-names: Should contain names of the SPI used DMA channel.
dmas: Should contain DMA channels and DMA slave ids which the SPI used
sorted in the same order as the dma-names property.
Example: Example:
spi0: spi@70a00000{ spi0: spi@70a00000{
compatible = "sprd,sc9860-spi"; compatible = "sprd,sc9860-spi";
...@@ -21,6 +26,8 @@ spi0: spi@70a00000{ ...@@ -21,6 +26,8 @@ spi0: spi@70a00000{
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "spi", "source","enable"; clock-names = "spi", "source","enable";
clocks = <&clk_spi0>, <&ext_26m>, <&clk_ap_apb_gates 5>; clocks = <&clk_spi0>, <&ext_26m>, <&clk_ap_apb_gates 5>;
dma-names = "rx_chn", "tx_chn";
dmas = <&apdma 11 11>, <&apdma 12 12>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
}; };
...@@ -7,7 +7,9 @@ from 4 to 32-bit data size. Although it can be configured as master or slave, ...@@ -7,7 +7,9 @@ from 4 to 32-bit data size. Although it can be configured as master or slave,
only master is supported by the driver. only master is supported by the driver.
Required properties: Required properties:
- compatible: Must be "st,stm32h7-spi". - compatible: Should be one of:
"st,stm32h7-spi"
"st,stm32f4-spi"
- reg: Offset and length of the device's register set. - reg: Offset and length of the device's register set.
- interrupts: Must contain the interrupt id. - interrupts: Must contain the interrupt id.
- clocks: Must contain an entry for spiclk (which feeds the internal clock - clocks: Must contain an entry for spiclk (which feeds the internal clock
...@@ -30,8 +32,9 @@ Child nodes represent devices on the SPI bus ...@@ -30,8 +32,9 @@ Child nodes represent devices on the SPI bus
See ../spi/spi-bus.txt See ../spi/spi-bus.txt
Optional properties: Optional properties:
- st,spi-midi-ns: (Master Inter-Data Idleness) minimum time delay in - st,spi-midi-ns: Only for STM32H7, (Master Inter-Data Idleness) minimum time
nanoseconds inserted between two consecutive data frames. delay in nanoseconds inserted between two consecutive data
frames.
Example: Example:
......
...@@ -21,15 +21,15 @@ Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a ...@@ -21,15 +21,15 @@ Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
"platform device". The master configuration is passed to the driver via a table "platform device". The master configuration is passed to the driver via a table
found in include/linux/spi/pxa2xx_spi.h: found in include/linux/spi/pxa2xx_spi.h:
struct pxa2xx_spi_master { struct pxa2xx_spi_controller {
u16 num_chipselect; u16 num_chipselect;
u8 enable_dma; u8 enable_dma;
}; };
The "pxa2xx_spi_master.num_chipselect" field is used to determine the number of The "pxa2xx_spi_controller.num_chipselect" field is used to determine the number of
slave device (chips) attached to this SPI master. slave device (chips) attached to this SPI master.
The "pxa2xx_spi_master.enable_dma" field informs the driver that SSP DMA should The "pxa2xx_spi_controller.enable_dma" field informs the driver that SSP DMA should
be used. This caused the driver to acquire two DMA channels: rx_channel and be used. This caused the driver to acquire two DMA channels: rx_channel and
tx_channel. The rx_channel has a higher DMA service priority the tx_channel. tx_channel. The rx_channel has a higher DMA service priority the tx_channel.
See the "PXA2xx Developer Manual" section "DMA Controller". See the "PXA2xx Developer Manual" section "DMA Controller".
...@@ -51,7 +51,7 @@ static struct resource pxa_spi_nssp_resources[] = { ...@@ -51,7 +51,7 @@ static struct resource pxa_spi_nssp_resources[] = {
}, },
}; };
static struct pxa2xx_spi_master pxa_nssp_master_info = { static struct pxa2xx_spi_controller pxa_nssp_master_info = {
.num_chipselect = 1, /* Matches the number of chips attached to NSSP */ .num_chipselect = 1, /* Matches the number of chips attached to NSSP */
.enable_dma = 1, /* Enables NSSP DMA */ .enable_dma = 1, /* Enables NSSP DMA */
}; };
...@@ -206,7 +206,7 @@ DMA and PIO I/O Support ...@@ -206,7 +206,7 @@ DMA and PIO I/O Support
----------------------- -----------------------
The pxa2xx_spi driver supports both DMA and interrupt driven PIO message The pxa2xx_spi driver supports both DMA and interrupt driven PIO message
transfers. The driver defaults to PIO mode and DMA transfers must be enabled transfers. The driver defaults to PIO mode and DMA transfers must be enabled
by setting the "enable_dma" flag in the "pxa2xx_spi_master" structure. The DMA by setting the "enable_dma" flag in the "pxa2xx_spi_controller" structure. The DMA
mode supports both coherent and stream based DMA mappings. mode supports both coherent and stream based DMA mappings.
The following logic is used to determine the type of I/O to be used on The following logic is used to determine the type of I/O to be used on
......
...@@ -6105,9 +6105,9 @@ F: Documentation/devicetree/bindings/ptp/ptp-qoriq.txt ...@@ -6105,9 +6105,9 @@ F: Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
FREESCALE QUAD SPI DRIVER FREESCALE QUAD SPI DRIVER
M: Han Xu <han.xu@nxp.com> M: Han Xu <han.xu@nxp.com>
L: linux-mtd@lists.infradead.org L: linux-spi@vger.kernel.org
S: Maintained S: Maintained
F: drivers/mtd/spi-nor/fsl-quadspi.c F: drivers/spi/spi-fsl-qspi.c
FREESCALE QUICC ENGINE LIBRARY FREESCALE QUICC ENGINE LIBRARY
M: Qiang Zhao <qiang.zhao@nxp.com> M: Qiang Zhao <qiang.zhao@nxp.com>
...@@ -10952,6 +10952,14 @@ F: lib/objagg.c ...@@ -10952,6 +10952,14 @@ F: lib/objagg.c
F: lib/test_objagg.c F: lib/test_objagg.c
F: include/linux/objagg.h F: include/linux/objagg.h
NXP FSPI DRIVER
R: Yogesh Gaur <yogeshgaur.83@gmail.com>
M: Ashish Kumar <ashish.kumar@nxp.com>
L: linux-spi@vger.kernel.org
S: Maintained
F: drivers/spi/spi-nxp-fspi.c
F: Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt
OBJTOOL OBJTOOL
M: Josh Poimboeuf <jpoimboe@redhat.com> M: Josh Poimboeuf <jpoimboe@redhat.com>
M: Peter Zijlstra <peterz@infradead.org> M: Peter Zijlstra <peterz@infradead.org>
......
...@@ -98,7 +98,7 @@ static unsigned long cmx255_pin_config[] = { ...@@ -98,7 +98,7 @@ static unsigned long cmx255_pin_config[] = {
}; };
#if defined(CONFIG_SPI_PXA2XX) #if defined(CONFIG_SPI_PXA2XX)
static struct pxa2xx_spi_master pxa_ssp_master_info = { static struct pxa2xx_spi_controller pxa_ssp_master_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
......
...@@ -313,7 +313,7 @@ static inline void cmx270_init_mmc(void) {} ...@@ -313,7 +313,7 @@ static inline void cmx270_init_mmc(void) {}
#endif #endif
#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE) #if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE)
static struct pxa2xx_spi_master cm_x270_spi_info = { static struct pxa2xx_spi_controller cm_x270_spi_info = {
.num_chipselect = 1, .num_chipselect = 1,
.enable_dma = 1, .enable_dma = 1,
}; };
......
...@@ -530,7 +530,7 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = { ...@@ -530,7 +530,7 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = {
}; };
#if IS_ENABLED(CONFIG_SPI_PXA2XX) #if IS_ENABLED(CONFIG_SPI_PXA2XX)
static struct pxa2xx_spi_master corgi_spi_info = { static struct pxa2xx_spi_controller corgi_spi_info = {
.num_chipselect = 3, .num_chipselect = 3,
}; };
......
...@@ -1065,7 +1065,7 @@ struct platform_device pxa93x_device_gpio = { ...@@ -1065,7 +1065,7 @@ struct platform_device pxa93x_device_gpio = {
/* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1. /* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1.
* See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */ * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */
void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info) void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_controller *info)
{ {
struct platform_device *pd; struct platform_device *pd;
......
...@@ -689,7 +689,7 @@ static inline void em_x270_init_lcd(void) {} ...@@ -689,7 +689,7 @@ static inline void em_x270_init_lcd(void) {}
#endif #endif
#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE) #if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE)
static struct pxa2xx_spi_master em_x270_spi_info = { static struct pxa2xx_spi_controller em_x270_spi_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
...@@ -703,7 +703,7 @@ static struct tdo24m_platform_data em_x270_tdo24m_pdata = { ...@@ -703,7 +703,7 @@ static struct tdo24m_platform_data em_x270_tdo24m_pdata = {
.model = TDO35S, .model = TDO35S,
}; };
static struct pxa2xx_spi_master em_x270_spi_2_info = { static struct pxa2xx_spi_controller em_x270_spi_2_info = {
.num_chipselect = 1, .num_chipselect = 1,
.enable_dma = 1, .enable_dma = 1,
}; };
......
...@@ -630,7 +630,7 @@ static struct spi_board_info tsc2046_board_info[] __initdata = { ...@@ -630,7 +630,7 @@ static struct spi_board_info tsc2046_board_info[] __initdata = {
}, },
}; };
static struct pxa2xx_spi_master pxa_ssp2_master_info = { static struct pxa2xx_spi_controller pxa_ssp2_master_info = {
.num_chipselect = 1, .num_chipselect = 1,
.enable_dma = 1, .enable_dma = 1,
}; };
......
...@@ -115,12 +115,12 @@ static struct spi_board_info mcp251x_board_info[] = { ...@@ -115,12 +115,12 @@ static struct spi_board_info mcp251x_board_info[] = {
} }
}; };
static struct pxa2xx_spi_master pxa_ssp3_spi_master_info = { static struct pxa2xx_spi_controller pxa_ssp3_spi_master_info = {
.num_chipselect = 2, .num_chipselect = 2,
.enable_dma = 1 .enable_dma = 1
}; };
static struct pxa2xx_spi_master pxa_ssp4_spi_master_info = { static struct pxa2xx_spi_controller pxa_ssp4_spi_master_info = {
.num_chipselect = 2, .num_chipselect = 2,
.enable_dma = 1 .enable_dma = 1
}; };
......
...@@ -191,7 +191,7 @@ static inline void littleton_init_lcd(void) {}; ...@@ -191,7 +191,7 @@ static inline void littleton_init_lcd(void) {};
#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */ #endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */
#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE) #if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE)
static struct pxa2xx_spi_master littleton_spi_info = { static struct pxa2xx_spi_controller littleton_spi_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
......
...@@ -197,7 +197,7 @@ static struct platform_device sa1111_device = { ...@@ -197,7 +197,7 @@ static struct platform_device sa1111_device = {
* (to J5) and poking board registers (as done below). Else it's only useful * (to J5) and poking board registers (as done below). Else it's only useful
* for the temperature sensors. * for the temperature sensors.
*/ */
static struct pxa2xx_spi_master pxa_ssp_master_info = { static struct pxa2xx_spi_controller pxa_ssp_master_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
......
...@@ -940,7 +940,7 @@ struct pxa2xx_spi_chip tsc2046_chip_info = { ...@@ -940,7 +940,7 @@ struct pxa2xx_spi_chip tsc2046_chip_info = {
.gpio_cs = GPIO14_MAGICIAN_TSC2046_CS, .gpio_cs = GPIO14_MAGICIAN_TSC2046_CS,
}; };
static struct pxa2xx_spi_master magician_spi_info = { static struct pxa2xx_spi_controller magician_spi_info = {
.num_chipselect = 1, .num_chipselect = 1,
.enable_dma = 1, .enable_dma = 1,
}; };
......
...@@ -132,7 +132,7 @@ static struct platform_device smc91x_device = { ...@@ -132,7 +132,7 @@ static struct platform_device smc91x_device = {
/* /*
* SPI host and devices * SPI host and devices
*/ */
static struct pxa2xx_spi_master pxa_ssp_master_info = { static struct pxa2xx_spi_controller pxa_ssp_master_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
......
...@@ -196,7 +196,7 @@ struct platform_device poodle_locomo_device = { ...@@ -196,7 +196,7 @@ struct platform_device poodle_locomo_device = {
EXPORT_SYMBOL(poodle_locomo_device); EXPORT_SYMBOL(poodle_locomo_device);
#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE) #if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE)
static struct pxa2xx_spi_master poodle_spi_info = { static struct pxa2xx_spi_controller poodle_spi_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
......
...@@ -572,7 +572,7 @@ static struct spi_board_info spitz_spi_devices[] = { ...@@ -572,7 +572,7 @@ static struct spi_board_info spitz_spi_devices[] = {
}, },
}; };
static struct pxa2xx_spi_master spitz_spi_info = { static struct pxa2xx_spi_controller spitz_spi_info = {
.num_chipselect = 3, .num_chipselect = 3,
}; };
......
...@@ -337,15 +337,15 @@ static struct platform_device stargate2_flash_device = { ...@@ -337,15 +337,15 @@ static struct platform_device stargate2_flash_device = {
.num_resources = 1, .num_resources = 1,
}; };
static struct pxa2xx_spi_master pxa_ssp_master_0_info = { static struct pxa2xx_spi_controller pxa_ssp_master_0_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
static struct pxa2xx_spi_master pxa_ssp_master_1_info = { static struct pxa2xx_spi_controller pxa_ssp_master_1_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
static struct pxa2xx_spi_master pxa_ssp_master_2_info = { static struct pxa2xx_spi_controller pxa_ssp_master_2_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
......
...@@ -813,7 +813,7 @@ static struct platform_device tosa_bt_device = { ...@@ -813,7 +813,7 @@ static struct platform_device tosa_bt_device = {
.dev.platform_data = &tosa_bt_data, .dev.platform_data = &tosa_bt_data,
}; };
static struct pxa2xx_spi_master pxa_ssp_master_info = { static struct pxa2xx_spi_controller pxa_ssp_master_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
......
...@@ -607,12 +607,12 @@ static struct spi_board_info spi_board_info[] __initdata = { ...@@ -607,12 +607,12 @@ static struct spi_board_info spi_board_info[] __initdata = {
}, },
}; };
static struct pxa2xx_spi_master pxa_ssp1_master_info = { static struct pxa2xx_spi_controller pxa_ssp1_master_info = {
.num_chipselect = 1, .num_chipselect = 1,
.enable_dma = 1, .enable_dma = 1,
}; };
static struct pxa2xx_spi_master pxa_ssp2_master_info = { static struct pxa2xx_spi_controller pxa_ssp2_master_info = {
.num_chipselect = 1, .num_chipselect = 1,
}; };
......
...@@ -391,7 +391,7 @@ static struct platform_device zeus_sram_device = { ...@@ -391,7 +391,7 @@ static struct platform_device zeus_sram_device = {
}; };
/* SPI interface on SSP3 */ /* SPI interface on SSP3 */
static struct pxa2xx_spi_master pxa2xx_spi_ssp3_master_info = { static struct pxa2xx_spi_controller pxa2xx_spi_ssp3_master_info = {
.num_chipselect = 1, .num_chipselect = 1,
.enable_dma = 1, .enable_dma = 1,
}; };
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#define _ATH79_DEV_SPI_H #define _ATH79_DEV_SPI_H
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <asm/mach-ath79/ath79_spi_platform.h> #include <linux/platform_data/spi-ath79.h>
void ath79_register_spi(struct ath79_spi_platform_data *pdata, void ath79_register_spi(struct ath79_spi_platform_data *pdata,
struct spi_board_info const *info, struct spi_board_info const *info,
......
...@@ -125,7 +125,7 @@ static void of_gpio_flags_quirks(struct device_node *np, ...@@ -125,7 +125,7 @@ static void of_gpio_flags_quirks(struct device_node *np,
for_each_child_of_node(np, child) { for_each_child_of_node(np, child) {
ret = of_property_read_u32(child, "reg", &cs); ret = of_property_read_u32(child, "reg", &cs);
if (!ret) if (ret)
continue; continue;
if (cs == index) { if (cs == index) {
/* /*
......
...@@ -42,15 +42,6 @@ config SPI_CADENCE_QUADSPI ...@@ -42,15 +42,6 @@ config SPI_CADENCE_QUADSPI
device with a Cadence QSPI controller and want to access the device with a Cadence QSPI controller and want to access the
Flash as an MTD device. Flash as an MTD device.
config SPI_FSL_QUADSPI
tristate "Freescale Quad SPI controller"
depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
depends on HAS_IOMEM
help
This enables support for the Quad SPI controller in master mode.
This controller does not support generic SPI. It only supports
SPI NOR.
config SPI_HISI_SFC config SPI_HISI_SFC
tristate "Hisilicon SPI-NOR Flash Controller(SFC)" tristate "Hisilicon SPI-NOR Flash Controller(SFC)"
depends on ARCH_HISI || COMPILE_TEST depends on ARCH_HISI || COMPILE_TEST
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
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_CADENCE_QUADSPI) += cadence-quadspi.o
obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_SPI_MTK_QUADSPI) += mtk-quadspi.o obj-$(CONFIG_SPI_MTK_QUADSPI) += mtk-quadspi.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
......
This diff is collapsed.
...@@ -63,7 +63,7 @@ config SPI_ALTERA ...@@ -63,7 +63,7 @@ config SPI_ALTERA
config SPI_ATH79 config SPI_ATH79
tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver" tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
depends on ATH79 && GPIOLIB depends on ATH79 || COMPILE_TEST
select SPI_BITBANG select SPI_BITBANG
help help
This enables support for the SPI controller present on the This enables support for the SPI controller present on the
...@@ -268,6 +268,27 @@ config SPI_FSL_LPSPI ...@@ -268,6 +268,27 @@ config SPI_FSL_LPSPI
help help
This enables Freescale i.MX LPSPI controllers in master mode. This enables Freescale i.MX LPSPI controllers in master mode.
config SPI_FSL_QUADSPI
tristate "Freescale QSPI controller"
depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
depends on HAS_IOMEM
help
This enables support for the Quad SPI controller in master mode.
Up to four flash chips can be connected on two buses with two
chipselects each.
This controller does not support generic SPI messages. It only
supports the high-level SPI memory interface.
config SPI_NXP_FLEXSPI
tristate "NXP Flex SPI controller"
depends on ARCH_LAYERSCAPE || HAS_IOMEM
help
This enables support for the Flex SPI controller in master mode.
Up to four slave devices can be connected on two buses with two
chipselects each.
This controller does not support generic SPI messages and only
supports the high-level SPI memory interface.
config SPI_GPIO config SPI_GPIO
tristate "GPIO-based bitbanging SPI Master" tristate "GPIO-based bitbanging SPI Master"
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
...@@ -296,8 +317,7 @@ config SPI_IMX ...@@ -296,8 +317,7 @@ config SPI_IMX
depends on ARCH_MXC || COMPILE_TEST depends on ARCH_MXC || COMPILE_TEST
select SPI_BITBANG select SPI_BITBANG
help help
This enables using the Freescale i.MX SPI controllers in master This enables support for the Freescale i.MX SPI controllers.
mode.
config SPI_JCORE config SPI_JCORE
tristate "J-Core SPI Master" tristate "J-Core SPI Master"
...@@ -372,7 +392,7 @@ config SPI_FSL_DSPI ...@@ -372,7 +392,7 @@ config SPI_FSL_DSPI
depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || M5441x || COMPILE_TEST depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || M5441x || COMPILE_TEST
help help
This enables support for the Freescale DSPI controller in master This enables support for the Freescale DSPI controller in master
mode. VF610 platform uses the controller. mode. VF610, LS1021A and ColdFire platforms uses the controller.
config SPI_FSL_ESPI config SPI_FSL_ESPI
tristate "Freescale eSPI controller" tristate "Freescale eSPI controller"
...@@ -631,6 +651,12 @@ config SPI_SH_HSPI ...@@ -631,6 +651,12 @@ config SPI_SH_HSPI
help help
SPI driver for SuperH HSPI blocks. SPI driver for SuperH HSPI blocks.
config SPI_SIFIVE
tristate "SiFive SPI controller"
depends on HAS_IOMEM
help
This exposes the SPI controller IP from SiFive.
config SPI_SIRF config SPI_SIRF
tristate "CSR SiRFprimaII SPI controller" tristate "CSR SiRFprimaII SPI controller"
depends on SIRF_DMA depends on SIRF_DMA
...@@ -665,7 +691,7 @@ config SPI_STM32 ...@@ -665,7 +691,7 @@ config SPI_STM32
tristate "STMicroelectronics STM32 SPI controller" tristate "STMicroelectronics STM32 SPI controller"
depends on ARCH_STM32 || COMPILE_TEST depends on ARCH_STM32 || COMPILE_TEST
help help
SPI driver for STMicroelectonics STM32 SoCs. SPI driver for STMicroelectronics STM32 SoCs.
STM32 SPI controller supports DMA and PIO modes. When DMA STM32 SPI controller supports DMA and PIO modes. When DMA
is not available, the driver automatically falls back to is not available, the driver automatically falls back to
......
...@@ -45,6 +45,7 @@ obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o ...@@ -45,6 +45,7 @@ obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o
obj-$(CONFIG_SPI_FSL_QUADSPI) += spi-fsl-qspi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o
obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o
...@@ -63,6 +64,7 @@ obj-$(CONFIG_SPI_MXIC) += spi-mxic.o ...@@ -63,6 +64,7 @@ obj-$(CONFIG_SPI_MXIC) += spi-mxic.o
obj-$(CONFIG_SPI_MXS) += spi-mxs.o obj-$(CONFIG_SPI_MXS) += spi-mxs.o
obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o
obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o
obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
spi-octeon-objs := spi-cavium.o spi-cavium-octeon.o spi-octeon-objs := spi-cavium.o spi-cavium-octeon.o
obj-$(CONFIG_SPI_OCTEON) += spi-octeon.o obj-$(CONFIG_SPI_OCTEON) += spi-octeon.o
...@@ -93,6 +95,7 @@ obj-$(CONFIG_SPI_SH) += spi-sh.o ...@@ -93,6 +95,7 @@ obj-$(CONFIG_SPI_SH) += spi-sh.o
obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o
obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o
obj-$(CONFIG_SPI_SIRF) += spi-sirf.o obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
obj-$(CONFIG_SPI_SLAVE_MT27XX) += spi-slave-mt27xx.o obj-$(CONFIG_SPI_SLAVE_MT27XX) += spi-slave-mt27xx.o
obj-$(CONFIG_SPI_SPRD) += spi-sprd.o obj-$(CONFIG_SPI_SPRD) += spi-sprd.o
......
This diff is collapsed.
...@@ -21,18 +21,26 @@ ...@@ -21,18 +21,26 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h> #include <linux/spi/spi_bitbang.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gpio.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_data/spi-ath79.h>
#include <asm/mach-ath79/ar71xx_regs.h>
#include <asm/mach-ath79/ath79_spi_platform.h>
#define DRV_NAME "ath79-spi" #define DRV_NAME "ath79-spi"
#define ATH79_SPI_RRW_DELAY_FACTOR 12000 #define ATH79_SPI_RRW_DELAY_FACTOR 12000
#define MHZ (1000 * 1000) #define MHZ (1000 * 1000)
#define AR71XX_SPI_REG_FS 0x00 /* Function Select */
#define AR71XX_SPI_REG_CTRL 0x04 /* SPI Control */
#define AR71XX_SPI_REG_IOC 0x08 /* SPI I/O Control */
#define AR71XX_SPI_REG_RDS 0x0c /* Read Data Shift */
#define AR71XX_SPI_FS_GPIO BIT(0) /* Enable GPIO mode */
#define AR71XX_SPI_IOC_DO BIT(0) /* Data Out pin */
#define AR71XX_SPI_IOC_CLK BIT(8) /* CLK pin */
#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n))
struct ath79_spi { struct ath79_spi {
struct spi_bitbang bitbang; struct spi_bitbang bitbang;
u32 ioc_base; u32 ioc_base;
...@@ -67,31 +75,14 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active) ...@@ -67,31 +75,14 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
{ {
struct ath79_spi *sp = ath79_spidev_to_sp(spi); struct ath79_spi *sp = ath79_spidev_to_sp(spi);
int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active; int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
if (is_active) { if (cs_high)
/* set initial clock polarity */ sp->ioc_base |= cs_bit;
if (spi->mode & SPI_CPOL) else
sp->ioc_base |= AR71XX_SPI_IOC_CLK; sp->ioc_base &= ~cs_bit;
else
sp->ioc_base &= ~AR71XX_SPI_IOC_CLK;
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
}
if (gpio_is_valid(spi->cs_gpio)) {
/* SPI is normally active-low */
gpio_set_value_cansleep(spi->cs_gpio, cs_high);
} else {
u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
if (cs_high)
sp->ioc_base |= cs_bit;
else
sp->ioc_base &= ~cs_bit;
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
}
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
} }
static void ath79_spi_enable(struct ath79_spi *sp) static void ath79_spi_enable(struct ath79_spi *sp)
...@@ -103,6 +94,9 @@ static void ath79_spi_enable(struct ath79_spi *sp) ...@@ -103,6 +94,9 @@ static void ath79_spi_enable(struct ath79_spi *sp)
sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL); sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC); sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
/* clear clk and mosi in the base state */
sp->ioc_base &= ~(AR71XX_SPI_IOC_DO | AR71XX_SPI_IOC_CLK);
/* TODO: setup speed? */ /* TODO: setup speed? */
ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
} }
...@@ -115,66 +109,6 @@ static void ath79_spi_disable(struct ath79_spi *sp) ...@@ -115,66 +109,6 @@ static void ath79_spi_disable(struct ath79_spi *sp)
ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
} }
static int ath79_spi_setup_cs(struct spi_device *spi)
{
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
int status;
status = 0;
if (gpio_is_valid(spi->cs_gpio)) {
unsigned long flags;
flags = GPIOF_DIR_OUT;
if (spi->mode & SPI_CS_HIGH)
flags |= GPIOF_INIT_LOW;
else
flags |= GPIOF_INIT_HIGH;
status = gpio_request_one(spi->cs_gpio, flags,
dev_name(&spi->dev));
} else {
u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
if (spi->mode & SPI_CS_HIGH)
sp->ioc_base &= ~cs_bit;
else
sp->ioc_base |= cs_bit;
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
}
return status;
}
static void ath79_spi_cleanup_cs(struct spi_device *spi)
{
if (gpio_is_valid(spi->cs_gpio))
gpio_free(spi->cs_gpio);
}
static int ath79_spi_setup(struct spi_device *spi)
{
int status = 0;
if (!spi->controller_state) {
status = ath79_spi_setup_cs(spi);
if (status)
return status;
}
status = spi_bitbang_setup(spi);
if (status && !spi->controller_state)
ath79_spi_cleanup_cs(spi);
return status;
}
static void ath79_spi_cleanup(struct spi_device *spi)
{
ath79_spi_cleanup_cs(spi);
spi_bitbang_cleanup(spi);
}
static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs, static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,
u32 word, u8 bits, unsigned flags) u32 word, u8 bits, unsigned flags)
{ {
...@@ -225,9 +159,10 @@ static int ath79_spi_probe(struct platform_device *pdev) ...@@ -225,9 +159,10 @@ static int ath79_spi_probe(struct platform_device *pdev)
pdata = dev_get_platdata(&pdev->dev); pdata = dev_get_platdata(&pdev->dev);
master->use_gpio_descriptors = true;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
master->setup = ath79_spi_setup; master->setup = spi_bitbang_setup;
master->cleanup = ath79_spi_cleanup; master->cleanup = spi_bitbang_cleanup;
if (pdata) { if (pdata) {
master->bus_num = pdata->bus_num; master->bus_num = pdata->bus_num;
master->num_chipselect = pdata->num_chipselect; master->num_chipselect = pdata->num_chipselect;
...@@ -236,7 +171,6 @@ static int ath79_spi_probe(struct platform_device *pdev) ...@@ -236,7 +171,6 @@ static int ath79_spi_probe(struct platform_device *pdev)
sp->bitbang.master = master; sp->bitbang.master = master;
sp->bitbang.chipselect = ath79_spi_chipselect; sp->bitbang.chipselect = ath79_spi_chipselect;
sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
sp->bitbang.flags = SPI_CS_HIGH; sp->bitbang.flags = SPI_CS_HIGH;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
...@@ -23,8 +23,7 @@ ...@@ -23,8 +23,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
...@@ -312,7 +311,7 @@ struct atmel_spi { ...@@ -312,7 +311,7 @@ struct atmel_spi {
/* Controller-specific per-slave state */ /* Controller-specific per-slave state */
struct atmel_spi_device { struct atmel_spi_device {
unsigned int npcs_pin; struct gpio_desc *npcs_pin;
u32 csr; u32 csr;
}; };
...@@ -355,7 +354,6 @@ static bool atmel_spi_is_v2(struct atmel_spi *as) ...@@ -355,7 +354,6 @@ static bool atmel_spi_is_v2(struct atmel_spi *as)
static void cs_activate(struct atmel_spi *as, struct spi_device *spi) static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
{ {
struct atmel_spi_device *asd = spi->controller_state; struct atmel_spi_device *asd = spi->controller_state;
unsigned active = spi->mode & SPI_CS_HIGH;
u32 mr; u32 mr;
if (atmel_spi_is_v2(as)) { if (atmel_spi_is_v2(as)) {
...@@ -379,7 +377,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) ...@@ -379,7 +377,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
mr = spi_readl(as, MR); mr = spi_readl(as, MR);
if (as->use_cs_gpios) if (as->use_cs_gpios)
gpio_set_value(asd->npcs_pin, active); gpiod_set_value(asd->npcs_pin, 1);
} else { } else {
u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
int i; int i;
...@@ -396,19 +394,16 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) ...@@ -396,19 +394,16 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
mr = spi_readl(as, MR); mr = spi_readl(as, MR);
mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr); mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
if (as->use_cs_gpios && spi->chip_select != 0) if (as->use_cs_gpios && spi->chip_select != 0)
gpio_set_value(asd->npcs_pin, active); gpiod_set_value(asd->npcs_pin, 1);
spi_writel(as, MR, mr); spi_writel(as, MR, mr);
} }
dev_dbg(&spi->dev, "activate %u%s, mr %08x\n", dev_dbg(&spi->dev, "activate NPCS, mr %08x\n", mr);
asd->npcs_pin, active ? " (high)" : "",
mr);
} }
static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
{ {
struct atmel_spi_device *asd = spi->controller_state; struct atmel_spi_device *asd = spi->controller_state;
unsigned active = spi->mode & SPI_CS_HIGH;
u32 mr; u32 mr;
/* only deactivate *this* device; sometimes transfers to /* only deactivate *this* device; sometimes transfers to
...@@ -420,14 +415,12 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) ...@@ -420,14 +415,12 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
spi_writel(as, MR, mr); spi_writel(as, MR, mr);
} }
dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n", dev_dbg(&spi->dev, "DEactivate NPCS, mr %08x\n", mr);
asd->npcs_pin, active ? " (low)" : "",
mr);
if (!as->use_cs_gpios) if (!as->use_cs_gpios)
spi_writel(as, CR, SPI_BIT(LASTXFER)); spi_writel(as, CR, SPI_BIT(LASTXFER));
else if (atmel_spi_is_v2(as) || spi->chip_select != 0) else if (atmel_spi_is_v2(as) || spi->chip_select != 0)
gpio_set_value(asd->npcs_pin, !active); gpiod_set_value(asd->npcs_pin, 0);
} }
static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock) static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock)
...@@ -1188,7 +1181,6 @@ static int atmel_spi_setup(struct spi_device *spi) ...@@ -1188,7 +1181,6 @@ static int atmel_spi_setup(struct spi_device *spi)
struct atmel_spi_device *asd; struct atmel_spi_device *asd;
u32 csr; u32 csr;
unsigned int bits = spi->bits_per_word; unsigned int bits = spi->bits_per_word;
unsigned int npcs_pin;
as = spi_master_get_devdata(spi->master); as = spi_master_get_devdata(spi->master);
...@@ -1209,21 +1201,14 @@ static int atmel_spi_setup(struct spi_device *spi) ...@@ -1209,21 +1201,14 @@ static int atmel_spi_setup(struct spi_device *spi)
csr |= SPI_BIT(CSAAT); csr |= SPI_BIT(CSAAT);
/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs. /* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
*
* DLYBCT would add delays between words, slowing down transfers.
* It could potentially be useful to cope with DMA bottlenecks, but
* in those cases it's probably best to just use a lower bitrate.
*/ */
csr |= SPI_BF(DLYBS, 0); csr |= SPI_BF(DLYBS, 0);
csr |= SPI_BF(DLYBCT, 0);
/* chipselect must have been muxed as GPIO (e.g. in board setup) */
npcs_pin = (unsigned long)spi->controller_data;
if (!as->use_cs_gpios) /* DLYBCT adds delays between words. This is useful for slow devices
npcs_pin = spi->chip_select; * that need a bit of time to setup the next transfer.
else if (gpio_is_valid(spi->cs_gpio)) */
npcs_pin = spi->cs_gpio; csr |= SPI_BF(DLYBCT,
(as->spi_clk / 1000000 * spi->word_delay_usecs) >> 5);
asd = spi->controller_state; asd = spi->controller_state;
if (!asd) { if (!asd) {
...@@ -1231,11 +1216,21 @@ static int atmel_spi_setup(struct spi_device *spi) ...@@ -1231,11 +1216,21 @@ static int atmel_spi_setup(struct spi_device *spi)
if (!asd) if (!asd)
return -ENOMEM; return -ENOMEM;
if (as->use_cs_gpios) /*
gpio_direction_output(npcs_pin, * If use_cs_gpios is true this means that we have "cs-gpios"
!(spi->mode & SPI_CS_HIGH)); * defined in the device tree node so we should have
* gotten the GPIO lines from the device tree inside the
* SPI core. Warn if this is not the case but continue since
* CS GPIOs are after all optional.
*/
if (as->use_cs_gpios) {
if (!spi->cs_gpiod) {
dev_err(&spi->dev,
"host claims to use CS GPIOs but no CS found in DT by the SPI core\n");
}
asd->npcs_pin = spi->cs_gpiod;
}
asd->npcs_pin = npcs_pin;
spi->controller_state = asd; spi->controller_state = asd;
} }
...@@ -1473,41 +1468,6 @@ static void atmel_get_caps(struct atmel_spi *as) ...@@ -1473,41 +1468,6 @@ static void atmel_get_caps(struct atmel_spi *as)
as->caps.has_pdc_support = version < 0x212; as->caps.has_pdc_support = version < 0x212;
} }
/*-------------------------------------------------------------------------*/
static int atmel_spi_gpio_cs(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct atmel_spi *as = spi_master_get_devdata(master);
struct device_node *np = master->dev.of_node;
int i;
int ret = 0;
int nb = 0;
if (!as->use_cs_gpios)
return 0;
if (!np)
return 0;
nb = of_gpio_named_count(np, "cs-gpios");
for (i = 0; i < nb; i++) {
int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
"cs-gpios", i);
if (cs_gpio == -EPROBE_DEFER)
return cs_gpio;
if (gpio_is_valid(cs_gpio)) {
ret = devm_gpio_request(&pdev->dev, cs_gpio,
dev_name(&pdev->dev));
if (ret)
return ret;
}
}
return 0;
}
static void atmel_spi_init(struct atmel_spi *as) static void atmel_spi_init(struct atmel_spi *as)
{ {
spi_writel(as, CR, SPI_BIT(SWRST)); spi_writel(as, CR, SPI_BIT(SWRST));
...@@ -1560,6 +1520,7 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1560,6 +1520,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
goto out_free; goto out_free;
/* the spi->mode bits understood by this driver: */ /* the spi->mode bits understood by this driver: */
master->use_gpio_descriptors = true;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
...@@ -1592,6 +1553,11 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1592,6 +1553,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
atmel_get_caps(as); atmel_get_caps(as);
/*
* If there are chip selects in the device tree, those will be
* discovered by the SPI core when registering the SPI master
* and assigned to each SPI device.
*/
as->use_cs_gpios = true; as->use_cs_gpios = true;
if (atmel_spi_is_v2(as) && if (atmel_spi_is_v2(as) &&
pdev->dev.of_node && pdev->dev.of_node &&
...@@ -1600,10 +1566,6 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1600,10 +1566,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
master->num_chipselect = 4; master->num_chipselect = 4;
} }
ret = atmel_spi_gpio_cs(pdev);
if (ret)
goto out_unmap_regs;
as->use_dma = false; as->use_dma = false;
as->use_pdc = false; as->use_pdc = false;
if (as->caps.has_dma_support) { if (as->caps.has_dma_support) {
......
...@@ -456,7 +456,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) ...@@ -456,7 +456,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
} }
bs->clk = devm_clk_get(&pdev->dev, NULL); bs->clk = devm_clk_get(&pdev->dev, NULL);
if ((!bs->clk) || (IS_ERR(bs->clk))) { if (IS_ERR(bs->clk)) {
err = PTR_ERR(bs->clk); err = PTR_ERR(bs->clk);
dev_err(&pdev->dev, "could not get clk: %d\n", err); dev_err(&pdev->dev, "could not get clk: %d\n", err);
goto out_master_put; goto out_master_put;
......
...@@ -213,19 +213,6 @@ int spi_bitbang_setup(struct spi_device *spi) ...@@ -213,19 +213,6 @@ int spi_bitbang_setup(struct spi_device *spi)
dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs); dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
/* NOTE we _need_ to call chipselect() early, ideally with adapter
* setup, unless the hardware defaults cooperate to avoid confusion
* between normal (active low) and inverted chipselects.
*/
/* deselect chip (low or high) */
mutex_lock(&bitbang->lock);
if (!bitbang->busy) {
bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
ndelay(cs->nsecs);
}
mutex_unlock(&bitbang->lock);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(spi_bitbang_setup); EXPORT_SYMBOL_GPL(spi_bitbang_setup);
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -128,10 +128,6 @@ struct cdns_spi { ...@@ -128,10 +128,6 @@ struct cdns_spi {
u32 is_decoded_cs; u32 is_decoded_cs;
}; };
struct cdns_spi_device_data {
bool gpio_requested;
};
/* Macros for the SPI controller read/write */ /* Macros for the SPI controller read/write */
static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset) static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset)
{ {
...@@ -176,16 +172,16 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi) ...@@ -176,16 +172,16 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi)
/** /**
* cdns_spi_chipselect - Select or deselect the chip select line * cdns_spi_chipselect - Select or deselect the chip select line
* @spi: Pointer to the spi_device structure * @spi: Pointer to the spi_device structure
* @is_high: Select(0) or deselect (1) the chip select line * @enable: Select (1) or deselect (0) the chip select line
*/ */
static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) static void cdns_spi_chipselect(struct spi_device *spi, bool enable)
{ {
struct cdns_spi *xspi = spi_master_get_devdata(spi->master); struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
u32 ctrl_reg; u32 ctrl_reg;
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
if (is_high) { if (!enable) {
/* Deselect the slave */ /* Deselect the slave */
ctrl_reg |= CDNS_SPI_CR_SSCTRL; ctrl_reg |= CDNS_SPI_CR_SSCTRL;
} else { } else {
...@@ -469,64 +465,6 @@ static int cdns_unprepare_transfer_hardware(struct spi_master *master) ...@@ -469,64 +465,6 @@ static int cdns_unprepare_transfer_hardware(struct spi_master *master)
return 0; return 0;
} }
static int cdns_spi_setup(struct spi_device *spi)
{
int ret = -EINVAL;
struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi);
/* this is a pin managed by the controller, leave it alone */
if (spi->cs_gpio == -ENOENT)
return 0;
/* this seems to be the first time we're here */
if (!cdns_spi_data) {
cdns_spi_data = kzalloc(sizeof(*cdns_spi_data), GFP_KERNEL);
if (!cdns_spi_data)
return -ENOMEM;
cdns_spi_data->gpio_requested = false;
spi_set_ctldata(spi, cdns_spi_data);
}
/* if we haven't done so, grab the gpio */
if (!cdns_spi_data->gpio_requested && gpio_is_valid(spi->cs_gpio)) {
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
cdns_spi_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 cdns_spi_cleanup(struct spi_device *spi)
{
struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi);
if (cdns_spi_data) {
if (cdns_spi_data->gpio_requested)
gpio_free(spi->cs_gpio);
kfree(cdns_spi_data);
spi_set_ctldata(spi, NULL);
}
}
/** /**
* cdns_spi_probe - Probe method for the SPI driver * cdns_spi_probe - Probe method for the SPI driver
* @pdev: Pointer to the platform_device structure * @pdev: Pointer to the platform_device structure
...@@ -584,11 +522,6 @@ static int cdns_spi_probe(struct platform_device *pdev) ...@@ -584,11 +522,6 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto clk_dis_apb; goto clk_dis_apb;
} }
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs); ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
if (ret < 0) if (ret < 0)
master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS; master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS;
...@@ -603,8 +536,10 @@ static int cdns_spi_probe(struct platform_device *pdev) ...@@ -603,8 +536,10 @@ static int cdns_spi_probe(struct platform_device *pdev)
/* SPI controller initializations */ /* SPI controller initializations */
cdns_spi_init_hw(xspi); cdns_spi_init_hw(xspi);
pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_set_active(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq <= 0) { if (irq <= 0) {
...@@ -621,13 +556,12 @@ static int cdns_spi_probe(struct platform_device *pdev) ...@@ -621,13 +556,12 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto clk_dis_all; goto clk_dis_all;
} }
master->use_gpio_descriptors = true;
master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
master->prepare_message = cdns_prepare_message; master->prepare_message = cdns_prepare_message;
master->transfer_one = cdns_transfer_one; master->transfer_one = cdns_transfer_one;
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->setup = cdns_spi_setup;
master->cleanup = cdns_spi_cleanup;
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
master->mode_bits = SPI_CPOL | SPI_CPHA; master->mode_bits = SPI_CPOL | SPI_CPHA;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -36,25 +36,6 @@ struct spi_clps711x_data { ...@@ -36,25 +36,6 @@ struct spi_clps711x_data {
int len; int len;
}; };
static int spi_clps711x_setup(struct spi_device *spi)
{
if (!spi->controller_state) {
int ret;
ret = devm_gpio_request(&spi->master->dev, spi->cs_gpio,
dev_name(&spi->master->dev));
if (ret)
return ret;
spi->controller_state = spi;
}
/* We are expect that SPI-device is not selected */
gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
return 0;
}
static int spi_clps711x_prepare_message(struct spi_master *master, static int spi_clps711x_prepare_message(struct spi_master *master,
struct spi_message *msg) struct spi_message *msg)
{ {
...@@ -125,11 +106,11 @@ static int spi_clps711x_probe(struct platform_device *pdev) ...@@ -125,11 +106,11 @@ static int spi_clps711x_probe(struct platform_device *pdev)
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
master->use_gpio_descriptors = true;
master->bus_num = -1; master->bus_num = -1;
master->mode_bits = SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8);
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
master->setup = spi_clps711x_setup;
master->prepare_message = spi_clps711x_prepare_message; master->prepare_message = spi_clps711x_prepare_message;
master->transfer_one = spi_clps711x_transfer_one; master->transfer_one = spi_clps711x_transfer_one;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.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/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h> #include <linux/spi/spi_bitbang.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -222,12 +221,17 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -222,12 +221,17 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
* Board specific chip select logic decides the polarity and cs * Board specific chip select logic decides the polarity and cs
* line for the controller * line for the controller
*/ */
if (spi->cs_gpio >= 0) { if (spi->cs_gpiod) {
/*
* FIXME: is this code ever executed? This host does not
* set SPI_MASTER_GPIO_SS so this chipselect callback should
* not get called from the SPI core when we are using
* GPIOs for chip select.
*/
if (value == BITBANG_CS_ACTIVE) if (value == BITBANG_CS_ACTIVE)
gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH); gpiod_set_value(spi->cs_gpiod, 1);
else else
gpio_set_value(spi->cs_gpio, gpiod_set_value(spi->cs_gpiod, 0);
!(spi->mode & SPI_CS_HIGH));
} else { } else {
if (value == BITBANG_CS_ACTIVE) { if (value == BITBANG_CS_ACTIVE) {
if (!(spi->mode & SPI_CS_WORD)) if (!(spi->mode & SPI_CS_WORD))
...@@ -418,30 +422,18 @@ static int davinci_spi_of_setup(struct spi_device *spi) ...@@ -418,30 +422,18 @@ static int davinci_spi_of_setup(struct spi_device *spi)
*/ */
static int davinci_spi_setup(struct spi_device *spi) static int davinci_spi_setup(struct spi_device *spi)
{ {
int retval = 0;
struct davinci_spi *dspi; struct davinci_spi *dspi;
struct spi_master *master = spi->master;
struct device_node *np = spi->dev.of_node; struct device_node *np = spi->dev.of_node;
bool internal_cs = true; bool internal_cs = true;
dspi = spi_master_get_devdata(spi->master); dspi = spi_master_get_devdata(spi->master);
if (!(spi->mode & SPI_NO_CS)) { if (!(spi->mode & SPI_NO_CS)) {
if (np && (master->cs_gpios != NULL) && (spi->cs_gpio >= 0)) { if (np && spi->cs_gpiod)
retval = gpio_direction_output(
spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
internal_cs = false; internal_cs = false;
}
if (retval) {
dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
spi->cs_gpio, retval);
return retval;
}
if (internal_cs) { if (internal_cs)
set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select); set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
}
} }
if (spi->mode & SPI_READY) if (spi->mode & SPI_READY)
...@@ -962,6 +954,7 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -962,6 +954,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
if (ret) if (ret)
goto free_master; goto free_master;
master->use_gpio_descriptors = true;
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->num_chipselect = pdata->num_chipselect; master->num_chipselect = pdata->num_chipselect;
...@@ -980,27 +973,6 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -980,27 +973,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
if (dspi->version == SPI_VERSION_2) if (dspi->version == SPI_VERSION_2)
dspi->bitbang.flags |= SPI_READY; dspi->bitbang.flags |= SPI_READY;
if (pdev->dev.of_node) {
int i;
for (i = 0; i < pdata->num_chipselect; i++) {
int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
"cs-gpios", i);
if (cs_gpio == -EPROBE_DEFER) {
ret = cs_gpio;
goto free_clk;
}
if (gpio_is_valid(cs_gpio)) {
ret = devm_gpio_request(&pdev->dev, cs_gpio,
dev_name(&pdev->dev));
if (ret)
goto free_clk;
}
}
}
dspi->bitbang.txrx_bufs = davinci_spi_bufs; dspi->bitbang.txrx_bufs = davinci_spi_bufs;
ret = davinci_spi_request_dma(dspi); ret = davinci_spi_request_dma(dspi);
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/property.h> #include <linux/property.h>
...@@ -185,27 +184,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) ...@@ -185,27 +184,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
dws->num_cs = num_cs; dws->num_cs = num_cs;
if (pdev->dev.of_node) {
int i;
for (i = 0; i < dws->num_cs; i++) {
int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
"cs-gpios", i);
if (cs_gpio == -EPROBE_DEFER) {
ret = cs_gpio;
goto out;
}
if (gpio_is_valid(cs_gpio)) {
ret = devm_gpio_request(&pdev->dev, cs_gpio,
dev_name(&pdev->dev));
if (ret)
goto out;
}
}
}
init_func = device_get_match_data(&pdev->dev); init_func = device_get_match_data(&pdev->dev);
if (init_func) { if (init_func) {
ret = init_func(pdev, dwsmmio); ret = init_func(pdev, dwsmmio);
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/gpio.h>
#include "spi-dw.h" #include "spi-dw.h"
...@@ -54,41 +53,41 @@ static ssize_t dw_spi_show_regs(struct file *file, char __user *user_buf, ...@@ -54,41 +53,41 @@ static ssize_t dw_spi_show_regs(struct file *file, char __user *user_buf,
if (!buf) if (!buf)
return 0; return 0;
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"%s registers:\n", dev_name(&dws->master->dev)); "%s registers:\n", dev_name(&dws->master->dev));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"=================================\n"); "=================================\n");
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0)); "CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1)); "CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR)); "SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER)); "SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR)); "BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR)); "TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR)); "RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR)); "TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR)); "RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR)); "SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR)); "IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR)); "ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR)); "DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR)); "DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR)); "DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += scnprintf(buf + len, SPI_REGS_BUFSIZE - len,
"=================================\n"); "=================================\n");
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
...@@ -138,11 +137,10 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable) ...@@ -138,11 +137,10 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable)
struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
struct chip_data *chip = spi_get_ctldata(spi); struct chip_data *chip = spi_get_ctldata(spi);
/* Chip select logic is inverted from spi_set_cs() */
if (chip && chip->cs_control) if (chip && chip->cs_control)
chip->cs_control(!enable); chip->cs_control(enable);
if (!enable) if (enable)
dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select)); dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select));
else if (dws->cs_override) else if (dws->cs_override)
dw_writel(dws, DW_SPI_SER, 0); dw_writel(dws, DW_SPI_SER, 0);
...@@ -317,7 +315,8 @@ static int dw_spi_transfer_one(struct spi_controller *master, ...@@ -317,7 +315,8 @@ static int dw_spi_transfer_one(struct spi_controller *master,
/* Default SPI mode is SCPOL = 0, SCPH = 0 */ /* Default SPI mode is SCPOL = 0, SCPH = 0 */
cr0 = (transfer->bits_per_word - 1) cr0 = (transfer->bits_per_word - 1)
| (chip->type << SPI_FRF_OFFSET) | (chip->type << SPI_FRF_OFFSET)
| (spi->mode << SPI_MODE_OFFSET) | ((((spi->mode & SPI_CPOL) ? 1 : 0) << SPI_SCOL_OFFSET) |
(((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET))
| (chip->tmode << SPI_TMOD_OFFSET); | (chip->tmode << SPI_TMOD_OFFSET);
/* /*
...@@ -397,7 +396,6 @@ static int dw_spi_setup(struct spi_device *spi) ...@@ -397,7 +396,6 @@ static int dw_spi_setup(struct spi_device *spi)
{ {
struct dw_spi_chip *chip_info = NULL; struct dw_spi_chip *chip_info = NULL;
struct chip_data *chip; struct chip_data *chip;
int ret;
/* Only alloc on first setup */ /* Only alloc on first setup */
chip = spi_get_ctldata(spi); chip = spi_get_ctldata(spi);
...@@ -425,13 +423,6 @@ static int dw_spi_setup(struct spi_device *spi) ...@@ -425,13 +423,6 @@ static int dw_spi_setup(struct spi_device *spi)
chip->tmode = SPI_TMOD_TR; chip->tmode = SPI_TMOD_TR;
if (gpio_is_valid(spi->cs_gpio)) {
ret = gpio_direction_output(spi->cs_gpio,
!(spi->mode & SPI_CS_HIGH));
if (ret)
return ret;
}
return 0; return 0;
} }
...@@ -496,6 +487,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -496,6 +487,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
goto err_free_master; goto err_free_master;
} }
master->use_gpio_descriptors = true;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
master->bus_num = dws->bus_num; master->bus_num = dws->bus_num;
......
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
#define SPI_SR 0x2c #define SPI_SR 0x2c
#define SPI_SR_EOQF 0x10000000 #define SPI_SR_EOQF 0x10000000
#define SPI_SR_TCFQF 0x80000000 #define SPI_SR_TCFQF 0x80000000
#define SPI_SR_CLEAR 0xdaad0000 #define SPI_SR_CLEAR 0x9aaf0000
#define SPI_RSER_TFFFE BIT(25) #define SPI_RSER_TFFFE BIT(25)
#define SPI_RSER_TFFFD BIT(24) #define SPI_RSER_TFFFD BIT(24)
...@@ -233,6 +233,9 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi) ...@@ -233,6 +233,9 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi)
{ {
u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi); u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi);
if (spi_controller_is_slave(dspi->master))
return data;
if (dspi->len > 0) if (dspi->len > 0)
cmd |= SPI_PUSHR_CMD_CONT; cmd |= SPI_PUSHR_CMD_CONT;
return cmd << 16 | data; return cmd << 16 | data;
...@@ -329,6 +332,11 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) ...@@ -329,6 +332,11 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
dma_async_issue_pending(dma->chan_rx); dma_async_issue_pending(dma->chan_rx);
dma_async_issue_pending(dma->chan_tx); dma_async_issue_pending(dma->chan_tx);
if (spi_controller_is_slave(dspi->master)) {
wait_for_completion_interruptible(&dspi->dma->cmd_rx_complete);
return 0;
}
time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete, time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete,
DMA_COMPLETION_TIMEOUT); DMA_COMPLETION_TIMEOUT);
if (time_left == 0) { if (time_left == 0) {
...@@ -798,14 +806,18 @@ static int dspi_setup(struct spi_device *spi) ...@@ -798,14 +806,18 @@ static int dspi_setup(struct spi_device *spi)
ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate); ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
chip->ctar_val = SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0) chip->ctar_val = SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0) | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0);
| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
| SPI_CTAR_PCSSCK(pcssck) if (!spi_controller_is_slave(dspi->master)) {
| SPI_CTAR_CSSCK(cssck) chip->ctar_val |= SPI_CTAR_LSBFE(spi->mode &
| SPI_CTAR_PASC(pasc) SPI_LSB_FIRST ? 1 : 0)
| SPI_CTAR_ASC(asc) | SPI_CTAR_PCSSCK(pcssck)
| SPI_CTAR_PBR(pbr) | SPI_CTAR_CSSCK(cssck)
| SPI_CTAR_BR(br); | SPI_CTAR_PASC(pasc)
| SPI_CTAR_ASC(asc)
| SPI_CTAR_PBR(pbr)
| SPI_CTAR_BR(br);
}
spi_set_ctldata(spi, chip); spi_set_ctldata(spi, chip);
...@@ -970,8 +982,13 @@ static const struct regmap_config dspi_xspi_regmap_config[] = { ...@@ -970,8 +982,13 @@ static const struct regmap_config dspi_xspi_regmap_config[] = {
static void dspi_init(struct fsl_dspi *dspi) static void dspi_init(struct fsl_dspi *dspi)
{ {
regmap_write(dspi->regmap, SPI_MCR, SPI_MCR_MASTER | SPI_MCR_PCSIS | unsigned int mcr = SPI_MCR_PCSIS |
(dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0)); (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0);
if (!spi_controller_is_slave(dspi->master))
mcr |= SPI_MCR_MASTER;
regmap_write(dspi->regmap, SPI_MCR, mcr);
regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR); regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);
if (dspi->devtype_data->xspi_mode) if (dspi->devtype_data->xspi_mode)
regmap_write(dspi->regmap, SPI_CTARE(0), regmap_write(dspi->regmap, SPI_CTARE(0),
...@@ -1027,6 +1044,9 @@ static int dspi_probe(struct platform_device *pdev) ...@@ -1027,6 +1044,9 @@ static int dspi_probe(struct platform_device *pdev)
} }
master->bus_num = bus_num; master->bus_num = bus_num;
if (of_property_read_bool(np, "spi-slave"))
master->slave = true;
dspi->devtype_data = of_device_get_match_data(&pdev->dev); dspi->devtype_data = of_device_get_match_data(&pdev->dev);
if (!dspi->devtype_data) { if (!dspi->devtype_data) {
dev_err(&pdev->dev, "can't get devtype_data\n"); dev_err(&pdev->dev, "can't get devtype_data\n");
......
...@@ -48,10 +48,13 @@ ...@@ -48,10 +48,13 @@
#define CR_RTF BIT(8) #define CR_RTF BIT(8)
#define CR_RST BIT(1) #define CR_RST BIT(1)
#define CR_MEN BIT(0) #define CR_MEN BIT(0)
#define SR_MBF BIT(24)
#define SR_TCF BIT(10) #define SR_TCF BIT(10)
#define SR_FCF BIT(9)
#define SR_RDF BIT(1) #define SR_RDF BIT(1)
#define SR_TDF BIT(0) #define SR_TDF BIT(0)
#define IER_TCIE BIT(10) #define IER_TCIE BIT(10)
#define IER_FCIE BIT(9)
#define IER_RDIE BIT(1) #define IER_RDIE BIT(1)
#define IER_TDIE BIT(0) #define IER_TDIE BIT(0)
#define CFGR1_PCSCFG BIT(27) #define CFGR1_PCSCFG BIT(27)
...@@ -59,6 +62,7 @@ ...@@ -59,6 +62,7 @@
#define CFGR1_PCSPOL BIT(8) #define CFGR1_PCSPOL BIT(8)
#define CFGR1_NOSTALL BIT(3) #define CFGR1_NOSTALL BIT(3)
#define CFGR1_MASTER BIT(0) #define CFGR1_MASTER BIT(0)
#define FSR_RXCOUNT (BIT(16)|BIT(17)|BIT(18))
#define RSR_RXEMPTY BIT(1) #define RSR_RXEMPTY BIT(1)
#define TCR_CPOL BIT(31) #define TCR_CPOL BIT(31)
#define TCR_CPHA BIT(30) #define TCR_CPHA BIT(30)
...@@ -161,28 +165,10 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller) ...@@ -161,28 +165,10 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller)
return 0; return 0;
} }
static int fsl_lpspi_txfifo_empty(struct fsl_lpspi_data *fsl_lpspi)
{
u32 txcnt;
unsigned long orig_jiffies = jiffies;
do {
txcnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff;
if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
dev_dbg(fsl_lpspi->dev, "txfifo empty timeout\n");
return -ETIMEDOUT;
}
cond_resched();
} while (txcnt);
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;
u32 temp;
txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff;
...@@ -193,9 +179,15 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) ...@@ -193,9 +179,15 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
txfifo_cnt++; txfifo_cnt++;
} }
if (!fsl_lpspi->remain && (txfifo_cnt < fsl_lpspi->txfifosize)) if (txfifo_cnt < fsl_lpspi->txfifosize) {
writel(0, fsl_lpspi->base + IMX7ULP_TDR); if (!fsl_lpspi->is_slave) {
else temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
temp &= ~TCR_CONTC;
writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
}
fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE);
} else
fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE); fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE);
} }
...@@ -276,10 +268,6 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi) ...@@ -276,10 +268,6 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi)
u32 temp; u32 temp;
int ret; int ret;
temp = CR_RST;
writel(temp, fsl_lpspi->base + IMX7ULP_CR);
writel(0, fsl_lpspi->base + IMX7ULP_CR);
if (!fsl_lpspi->is_slave) { if (!fsl_lpspi->is_slave) {
ret = fsl_lpspi_set_bitrate(fsl_lpspi); ret = fsl_lpspi_set_bitrate(fsl_lpspi);
if (ret) if (ret)
...@@ -370,6 +358,24 @@ static int fsl_lpspi_wait_for_completion(struct spi_controller *controller) ...@@ -370,6 +358,24 @@ static int fsl_lpspi_wait_for_completion(struct spi_controller *controller)
return 0; return 0;
} }
static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi)
{
u32 temp;
/* Disable all interrupt */
fsl_lpspi_intctrl(fsl_lpspi, 0);
/* W1C for all flags in SR */
temp = 0x3F << 8;
writel(temp, fsl_lpspi->base + IMX7ULP_SR);
/* Clear FIFO and disable module */
temp = CR_RRF | CR_RTF;
writel(temp, fsl_lpspi->base + IMX7ULP_CR);
return 0;
}
static int fsl_lpspi_transfer_one(struct spi_controller *controller, static int fsl_lpspi_transfer_one(struct spi_controller *controller,
struct spi_device *spi, struct spi_device *spi,
struct spi_transfer *t) struct spi_transfer *t)
...@@ -391,11 +397,7 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller, ...@@ -391,11 +397,7 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller,
if (ret) if (ret)
return ret; return ret;
ret = fsl_lpspi_txfifo_empty(fsl_lpspi); fsl_lpspi_reset(fsl_lpspi);
if (ret)
return ret;
fsl_lpspi_read_rx_fifo(fsl_lpspi);
return 0; return 0;
} }
...@@ -408,7 +410,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller, ...@@ -408,7 +410,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
struct spi_device *spi = msg->spi; struct spi_device *spi = msg->spi;
struct spi_transfer *xfer; struct spi_transfer *xfer;
bool is_first_xfer = true; bool is_first_xfer = true;
u32 temp;
int ret = 0; int ret = 0;
msg->status = 0; msg->status = 0;
...@@ -428,13 +429,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller, ...@@ -428,13 +429,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
} }
complete: complete:
if (!fsl_lpspi->is_slave) {
/* de-assert SS, then finalize current message */
temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
temp &= ~TCR_CONTC;
writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
}
msg->status = ret; msg->status = ret;
spi_finalize_current_message(controller); spi_finalize_current_message(controller);
...@@ -443,20 +437,30 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller, ...@@ -443,20 +437,30 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id)
{ {
u32 temp_SR, temp_IER;
struct fsl_lpspi_data *fsl_lpspi = dev_id; struct fsl_lpspi_data *fsl_lpspi = dev_id;
u32 temp;
temp_IER = readl(fsl_lpspi->base + IMX7ULP_IER);
fsl_lpspi_intctrl(fsl_lpspi, 0); fsl_lpspi_intctrl(fsl_lpspi, 0);
temp = readl(fsl_lpspi->base + IMX7ULP_SR); temp_SR = readl(fsl_lpspi->base + IMX7ULP_SR);
fsl_lpspi_read_rx_fifo(fsl_lpspi); fsl_lpspi_read_rx_fifo(fsl_lpspi);
if (temp & SR_TDF) { if ((temp_SR & SR_TDF) && (temp_IER & IER_TDIE)) {
fsl_lpspi_write_tx_fifo(fsl_lpspi); fsl_lpspi_write_tx_fifo(fsl_lpspi);
return IRQ_HANDLED;
}
if (!fsl_lpspi->remain) if (temp_SR & SR_MBF ||
complete(&fsl_lpspi->xfer_done); readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_RXCOUNT) {
writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE);
return IRQ_HANDLED;
}
if (temp_SR & SR_FCF && (temp_IER & IER_FCIE)) {
writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
complete(&fsl_lpspi->xfer_done);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
This diff is collapsed.
...@@ -89,9 +89,6 @@ struct spi_geni_master { ...@@ -89,9 +89,6 @@ struct spi_geni_master {
int irq; int irq;
}; };
static void handle_fifo_timeout(struct spi_master *spi,
struct spi_message *msg);
static int get_spi_clk_cfg(unsigned int speed_hz, static int get_spi_clk_cfg(unsigned int speed_hz,
struct spi_geni_master *mas, struct spi_geni_master *mas,
unsigned int *clk_idx, unsigned int *clk_idx,
...@@ -122,6 +119,32 @@ static int get_spi_clk_cfg(unsigned int speed_hz, ...@@ -122,6 +119,32 @@ static int get_spi_clk_cfg(unsigned int speed_hz,
return ret; return ret;
} }
static void handle_fifo_timeout(struct spi_master *spi,
struct spi_message *msg)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
unsigned long time_left, flags;
struct geni_se *se = &mas->se;
spin_lock_irqsave(&mas->lock, flags);
reinit_completion(&mas->xfer_done);
mas->cur_mcmd = CMD_CANCEL;
geni_se_cancel_m_cmd(se);
writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
spin_unlock_irqrestore(&mas->lock, flags);
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
if (time_left)
return;
spin_lock_irqsave(&mas->lock, flags);
reinit_completion(&mas->xfer_done);
geni_se_abort_m_cmd(se);
spin_unlock_irqrestore(&mas->lock, flags);
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
if (!time_left)
dev_err(mas->dev, "Failed to cancel/abort m_cmd\n");
}
static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
{ {
struct spi_geni_master *mas = spi_master_get_devdata(slv->master); struct spi_geni_master *mas = spi_master_get_devdata(slv->master);
...@@ -233,7 +256,6 @@ static int spi_geni_prepare_message(struct spi_master *spi, ...@@ -233,7 +256,6 @@ static int spi_geni_prepare_message(struct spi_master *spi,
struct geni_se *se = &mas->se; struct geni_se *se = &mas->se;
geni_se_select_mode(se, GENI_SE_FIFO); geni_se_select_mode(se, GENI_SE_FIFO);
reinit_completion(&mas->xfer_done);
ret = setup_fifo_params(spi_msg->spi, spi); ret = setup_fifo_params(spi_msg->spi, spi);
if (ret) if (ret)
dev_err(mas->dev, "Couldn't select mode %d\n", ret); dev_err(mas->dev, "Couldn't select mode %d\n", ret);
...@@ -357,32 +379,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, ...@@ -357,32 +379,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG); writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG);
} }
static void handle_fifo_timeout(struct spi_master *spi,
struct spi_message *msg)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
unsigned long time_left, flags;
struct geni_se *se = &mas->se;
spin_lock_irqsave(&mas->lock, flags);
reinit_completion(&mas->xfer_done);
mas->cur_mcmd = CMD_CANCEL;
geni_se_cancel_m_cmd(se);
writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
spin_unlock_irqrestore(&mas->lock, flags);
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
if (time_left)
return;
spin_lock_irqsave(&mas->lock, flags);
reinit_completion(&mas->xfer_done);
geni_se_abort_m_cmd(se);
spin_unlock_irqrestore(&mas->lock, flags);
time_left = wait_for_completion_timeout(&mas->xfer_done, HZ);
if (!time_left)
dev_err(mas->dev, "Failed to cancel/abort m_cmd\n");
}
static int spi_geni_transfer_one(struct spi_master *spi, static int spi_geni_transfer_one(struct spi_master *spi,
struct spi_device *slv, struct spi_device *slv,
struct spi_transfer *xfer) struct spi_transfer *xfer)
......
...@@ -428,7 +428,8 @@ static int spi_gpio_probe(struct platform_device *pdev) ...@@ -428,7 +428,8 @@ static int spi_gpio_probe(struct platform_device *pdev)
return status; return status;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL; master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL |
SPI_CS_HIGH;
master->flags = master_flags; master->flags = master_flags;
master->bus_num = pdev->id; master->bus_num = pdev->id;
/* The master needs to think there is a chipselect even if not connected */ /* The master needs to think there is a chipselect even if not connected */
...@@ -455,7 +456,6 @@ static int spi_gpio_probe(struct platform_device *pdev) ...@@ -455,7 +456,6 @@ static int spi_gpio_probe(struct platform_device *pdev)
spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3; spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
} }
spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
spi_gpio->bitbang.flags = SPI_CS_HIGH;
status = spi_bitbang_start(&spi_gpio->bitbang); status = spi_bitbang_start(&spi_gpio->bitbang);
if (status) if (status)
......
...@@ -537,7 +537,6 @@ EXPORT_SYMBOL_GPL(spi_mem_dirmap_create); ...@@ -537,7 +537,6 @@ EXPORT_SYMBOL_GPL(spi_mem_dirmap_create);
/** /**
* spi_mem_dirmap_destroy() - Destroy a direct mapping descriptor * spi_mem_dirmap_destroy() - Destroy a direct mapping descriptor
* @desc: the direct mapping descriptor to destroy * @desc: the direct mapping descriptor to destroy
* @info: direct mapping information
* *
* This function destroys a direct mapping descriptor previously created by * This function destroys a direct mapping descriptor previously created by
* spi_mem_dirmap_create(). * spi_mem_dirmap_create().
...@@ -548,9 +547,80 @@ void spi_mem_dirmap_destroy(struct spi_mem_dirmap_desc *desc) ...@@ -548,9 +547,80 @@ void spi_mem_dirmap_destroy(struct spi_mem_dirmap_desc *desc)
if (!desc->nodirmap && ctlr->mem_ops && ctlr->mem_ops->dirmap_destroy) if (!desc->nodirmap && ctlr->mem_ops && ctlr->mem_ops->dirmap_destroy)
ctlr->mem_ops->dirmap_destroy(desc); ctlr->mem_ops->dirmap_destroy(desc);
kfree(desc);
} }
EXPORT_SYMBOL_GPL(spi_mem_dirmap_destroy); EXPORT_SYMBOL_GPL(spi_mem_dirmap_destroy);
static void devm_spi_mem_dirmap_release(struct device *dev, void *res)
{
struct spi_mem_dirmap_desc *desc = *(struct spi_mem_dirmap_desc **)res;
spi_mem_dirmap_destroy(desc);
}
/**
* devm_spi_mem_dirmap_create() - Create a direct mapping descriptor and attach
* it to a device
* @dev: device the dirmap desc will be attached to
* @mem: SPI mem device this direct mapping should be created for
* @info: direct mapping information
*
* devm_ variant of the spi_mem_dirmap_create() function. See
* spi_mem_dirmap_create() for more details.
*
* Return: a valid pointer in case of success, and ERR_PTR() otherwise.
*/
struct spi_mem_dirmap_desc *
devm_spi_mem_dirmap_create(struct device *dev, struct spi_mem *mem,
const struct spi_mem_dirmap_info *info)
{
struct spi_mem_dirmap_desc **ptr, *desc;
ptr = devres_alloc(devm_spi_mem_dirmap_release, sizeof(*ptr),
GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
desc = spi_mem_dirmap_create(mem, info);
if (IS_ERR(desc)) {
devres_free(ptr);
} else {
*ptr = desc;
devres_add(dev, ptr);
}
return desc;
}
EXPORT_SYMBOL_GPL(devm_spi_mem_dirmap_create);
static int devm_spi_mem_dirmap_match(struct device *dev, void *res, void *data)
{
struct spi_mem_dirmap_desc **ptr = res;
if (WARN_ON(!ptr || !*ptr))
return 0;
return *ptr == data;
}
/**
* devm_spi_mem_dirmap_destroy() - Destroy a direct mapping descriptor attached
* to a device
* @dev: device the dirmap desc is attached to
* @desc: the direct mapping descriptor to destroy
*
* devm_ variant of the spi_mem_dirmap_destroy() function. See
* spi_mem_dirmap_destroy() for more details.
*/
void devm_spi_mem_dirmap_destroy(struct device *dev,
struct spi_mem_dirmap_desc *desc)
{
devres_release(dev, devm_spi_mem_dirmap_release,
devm_spi_mem_dirmap_match, desc);
}
EXPORT_SYMBOL_GPL(devm_spi_mem_dirmap_destroy);
/** /**
* spi_mem_dirmap_dirmap_read() - Read data through a direct mapping * spi_mem_dirmap_dirmap_read() - Read data through a direct mapping
* @desc: direct mapping descriptor * @desc: direct mapping descriptor
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/stmp_device.h> #include <linux/stmp_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/mxs-spi.h> #include <linux/spi/mxs-spi.h>
#include <trace/events/spi.h>
#define DRIVER_NAME "mxs-spi" #define DRIVER_NAME "mxs-spi"
...@@ -374,6 +375,8 @@ static int mxs_spi_transfer_one(struct spi_master *master, ...@@ -374,6 +375,8 @@ static int mxs_spi_transfer_one(struct spi_master *master,
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
trace_spi_transfer_start(m, t);
status = mxs_spi_setup_transfer(m->spi, t); status = mxs_spi_setup_transfer(m->spi, t);
if (status) if (status)
break; break;
...@@ -419,6 +422,8 @@ static int mxs_spi_transfer_one(struct spi_master *master, ...@@ -419,6 +422,8 @@ static int mxs_spi_transfer_one(struct spi_master *master,
flag); flag);
} }
trace_spi_transfer_stop(m, t);
if (status) { if (status) {
stmp_reset_block(ssp->base); stmp_reset_block(ssp->base);
break; break;
......
...@@ -465,7 +465,8 @@ static int npcm_pspi_probe(struct platform_device *pdev) ...@@ -465,7 +465,8 @@ static int npcm_pspi_probe(struct platform_device *pdev)
static int npcm_pspi_remove(struct platform_device *pdev) static int npcm_pspi_remove(struct platform_device *pdev)
{ {
struct npcm_pspi *priv = platform_get_drvdata(pdev); struct spi_master *master = platform_get_drvdata(pdev);
struct npcm_pspi *priv = spi_master_get_devdata(master);
npcm_pspi_reset_hw(priv); npcm_pspi_reset_hw(priv);
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
......
This diff is collapsed.
...@@ -623,8 +623,8 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -623,8 +623,8 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0;
cfg.src_addr_width = width; cfg.src_addr_width = width;
cfg.dst_addr_width = width; cfg.dst_addr_width = width;
cfg.src_maxburst = es; cfg.src_maxburst = 1;
cfg.dst_maxburst = es; cfg.dst_maxburst = 1;
rx = xfer->rx_buf; rx = xfer->rx_buf;
tx = xfer->tx_buf; tx = xfer->tx_buf;
......
...@@ -253,6 +253,7 @@ ...@@ -253,6 +253,7 @@
#define STATE_RUNNING ((void *) 1) #define STATE_RUNNING ((void *) 1)
#define STATE_DONE ((void *) 2) #define STATE_DONE ((void *) 2)
#define STATE_ERROR ((void *) -1) #define STATE_ERROR ((void *) -1)
#define STATE_TIMEOUT ((void *) -2)
/* /*
* SSP State - Whether Enabled or Disabled * SSP State - Whether Enabled or Disabled
...@@ -1484,6 +1485,30 @@ static void do_interrupt_dma_transfer(struct pl022 *pl022) ...@@ -1484,6 +1485,30 @@ static void do_interrupt_dma_transfer(struct pl022 *pl022)
writew(irqflags, SSP_IMSC(pl022->virtbase)); writew(irqflags, SSP_IMSC(pl022->virtbase));
} }
static void print_current_status(struct pl022 *pl022)
{
u32 read_cr0;
u16 read_cr1, read_dmacr, read_sr;
if (pl022->vendor->extended_cr)
read_cr0 = readl(SSP_CR0(pl022->virtbase));
else
read_cr0 = readw(SSP_CR0(pl022->virtbase));
read_cr1 = readw(SSP_CR1(pl022->virtbase));
read_dmacr = readw(SSP_DMACR(pl022->virtbase));
read_sr = readw(SSP_SR(pl022->virtbase));
dev_warn(&pl022->adev->dev, "spi-pl022 CR0: %x\n", read_cr0);
dev_warn(&pl022->adev->dev, "spi-pl022 CR1: %x\n", read_cr1);
dev_warn(&pl022->adev->dev, "spi-pl022 DMACR: %x\n", read_dmacr);
dev_warn(&pl022->adev->dev, "spi-pl022 SR: %x\n", read_sr);
dev_warn(&pl022->adev->dev,
"spi-pl022 exp_fifo_level/fifodepth: %u/%d\n",
pl022->exp_fifo_level,
pl022->vendor->fifodepth);
}
static void do_polling_transfer(struct pl022 *pl022) static void do_polling_transfer(struct pl022 *pl022)
{ {
struct spi_message *message = NULL; struct spi_message *message = NULL;
...@@ -1535,7 +1560,8 @@ static void do_polling_transfer(struct pl022 *pl022) ...@@ -1535,7 +1560,8 @@ static void do_polling_transfer(struct pl022 *pl022)
if (time_after(time, timeout)) { if (time_after(time, timeout)) {
dev_warn(&pl022->adev->dev, dev_warn(&pl022->adev->dev,
"%s: timeout!\n", __func__); "%s: timeout!\n", __func__);
message->state = STATE_ERROR; message->state = STATE_TIMEOUT;
print_current_status(pl022);
goto out; goto out;
} }
cpu_relax(); cpu_relax();
...@@ -1553,6 +1579,8 @@ static void do_polling_transfer(struct pl022 *pl022) ...@@ -1553,6 +1579,8 @@ static void do_polling_transfer(struct pl022 *pl022)
/* Handle end of message */ /* Handle end of message */
if (message->state == STATE_DONE) if (message->state == STATE_DONE)
message->status = 0; message->status = 0;
else if (message->state == STATE_TIMEOUT)
message->status = -EAGAIN;
else else
message->status = -EIO; message->status = -EIO;
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
bool error) bool error)
{ {
struct spi_message *msg = drv_data->master->cur_msg; struct spi_message *msg = drv_data->controller->cur_msg;
/* /*
* It is possible that one CPU is handling ROR interrupt and other * It is possible that one CPU is handling ROR interrupt and other
...@@ -59,7 +59,7 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, ...@@ -59,7 +59,7 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
msg->status = -EIO; msg->status = -EIO;
} }
spi_finalize_current_transfer(drv_data->master); spi_finalize_current_transfer(drv_data->controller);
} }
} }
...@@ -74,7 +74,7 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, ...@@ -74,7 +74,7 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
struct chip_data *chip = struct chip_data *chip =
spi_get_ctldata(drv_data->master->cur_msg->spi); spi_get_ctldata(drv_data->controller->cur_msg->spi);
enum dma_slave_buswidth width; enum dma_slave_buswidth width;
struct dma_slave_config cfg; struct dma_slave_config cfg;
struct dma_chan *chan; struct dma_chan *chan;
...@@ -102,14 +102,14 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data, ...@@ -102,14 +102,14 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
cfg.dst_maxburst = chip->dma_burst_size; cfg.dst_maxburst = chip->dma_burst_size;
sgt = &xfer->tx_sg; sgt = &xfer->tx_sg;
chan = drv_data->master->dma_tx; chan = drv_data->controller->dma_tx;
} else { } else {
cfg.src_addr = drv_data->ssdr_physical; cfg.src_addr = drv_data->ssdr_physical;
cfg.src_addr_width = width; cfg.src_addr_width = width;
cfg.src_maxburst = chip->dma_burst_size; cfg.src_maxburst = chip->dma_burst_size;
sgt = &xfer->rx_sg; sgt = &xfer->rx_sg;
chan = drv_data->master->dma_rx; chan = drv_data->controller->dma_rx;
} }
ret = dmaengine_slave_config(chan, &cfg); ret = dmaengine_slave_config(chan, &cfg);
...@@ -130,8 +130,8 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data) ...@@ -130,8 +130,8 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
if (status & SSSR_ROR) { if (status & SSSR_ROR) {
dev_err(&drv_data->pdev->dev, "FIFO overrun\n"); dev_err(&drv_data->pdev->dev, "FIFO overrun\n");
dmaengine_terminate_async(drv_data->master->dma_rx); dmaengine_terminate_async(drv_data->controller->dma_rx);
dmaengine_terminate_async(drv_data->master->dma_tx); dmaengine_terminate_async(drv_data->controller->dma_tx);
pxa2xx_spi_dma_transfer_complete(drv_data, true); pxa2xx_spi_dma_transfer_complete(drv_data, true);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -171,15 +171,15 @@ int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, ...@@ -171,15 +171,15 @@ int pxa2xx_spi_dma_prepare(struct driver_data *drv_data,
return 0; return 0;
err_rx: err_rx:
dmaengine_terminate_async(drv_data->master->dma_tx); dmaengine_terminate_async(drv_data->controller->dma_tx);
err_tx: err_tx:
return err; return err;
} }
void pxa2xx_spi_dma_start(struct driver_data *drv_data) void pxa2xx_spi_dma_start(struct driver_data *drv_data)
{ {
dma_async_issue_pending(drv_data->master->dma_rx); dma_async_issue_pending(drv_data->controller->dma_rx);
dma_async_issue_pending(drv_data->master->dma_tx); dma_async_issue_pending(drv_data->controller->dma_tx);
atomic_set(&drv_data->dma_running, 1); atomic_set(&drv_data->dma_running, 1);
} }
...@@ -187,30 +187,30 @@ void pxa2xx_spi_dma_start(struct driver_data *drv_data) ...@@ -187,30 +187,30 @@ void pxa2xx_spi_dma_start(struct driver_data *drv_data)
void pxa2xx_spi_dma_stop(struct driver_data *drv_data) void pxa2xx_spi_dma_stop(struct driver_data *drv_data)
{ {
atomic_set(&drv_data->dma_running, 0); atomic_set(&drv_data->dma_running, 0);
dmaengine_terminate_sync(drv_data->master->dma_rx); dmaengine_terminate_sync(drv_data->controller->dma_rx);
dmaengine_terminate_sync(drv_data->master->dma_tx); dmaengine_terminate_sync(drv_data->controller->dma_tx);
} }
int pxa2xx_spi_dma_setup(struct driver_data *drv_data) int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
{ {
struct pxa2xx_spi_master *pdata = drv_data->master_info; struct pxa2xx_spi_controller *pdata = drv_data->controller_info;
struct device *dev = &drv_data->pdev->dev; struct device *dev = &drv_data->pdev->dev;
struct spi_controller *master = drv_data->master; struct spi_controller *controller = drv_data->controller;
dma_cap_mask_t mask; dma_cap_mask_t mask;
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
master->dma_tx = dma_request_slave_channel_compat(mask, controller->dma_tx = dma_request_slave_channel_compat(mask,
pdata->dma_filter, pdata->tx_param, dev, "tx"); pdata->dma_filter, pdata->tx_param, dev, "tx");
if (!master->dma_tx) if (!controller->dma_tx)
return -ENODEV; return -ENODEV;
master->dma_rx = dma_request_slave_channel_compat(mask, controller->dma_rx = dma_request_slave_channel_compat(mask,
pdata->dma_filter, pdata->rx_param, dev, "rx"); pdata->dma_filter, pdata->rx_param, dev, "rx");
if (!master->dma_rx) { if (!controller->dma_rx) {
dma_release_channel(master->dma_tx); dma_release_channel(controller->dma_tx);
master->dma_tx = NULL; controller->dma_tx = NULL;
return -ENODEV; return -ENODEV;
} }
...@@ -219,17 +219,17 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data) ...@@ -219,17 +219,17 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
void pxa2xx_spi_dma_release(struct driver_data *drv_data) void pxa2xx_spi_dma_release(struct driver_data *drv_data)
{ {
struct spi_controller *master = drv_data->master; struct spi_controller *controller = drv_data->controller;
if (master->dma_rx) { if (controller->dma_rx) {
dmaengine_terminate_sync(master->dma_rx); dmaengine_terminate_sync(controller->dma_rx);
dma_release_channel(master->dma_rx); dma_release_channel(controller->dma_rx);
master->dma_rx = NULL; controller->dma_rx = NULL;
} }
if (master->dma_tx) { if (controller->dma_tx) {
dmaengine_terminate_sync(master->dma_tx); dmaengine_terminate_sync(controller->dma_tx);
dma_release_channel(master->dma_tx); dma_release_channel(controller->dma_tx);
master->dma_tx = NULL; controller->dma_tx = NULL;
} }
} }
......
...@@ -197,7 +197,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ...@@ -197,7 +197,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
struct platform_device_info pi; struct platform_device_info pi;
int ret; int ret;
struct platform_device *pdev; struct platform_device *pdev;
struct pxa2xx_spi_master spi_pdata; struct pxa2xx_spi_controller spi_pdata;
struct ssp_device *ssp; struct ssp_device *ssp;
struct pxa_spi_info *c; struct pxa_spi_info *c;
char buf[40]; char buf[40];
...@@ -265,7 +265,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ...@@ -265,7 +265,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
static void pxa2xx_spi_pci_remove(struct pci_dev *dev) static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
{ {
struct platform_device *pdev = pci_get_drvdata(dev); struct platform_device *pdev = pci_get_drvdata(dev);
struct pxa2xx_spi_master *spi_pdata; struct pxa2xx_spi_controller *spi_pdata;
spi_pdata = dev_get_platdata(&pdev->dev); spi_pdata = dev_get_platdata(&pdev->dev);
......
This diff is collapsed.
...@@ -31,10 +31,10 @@ struct driver_data { ...@@ -31,10 +31,10 @@ struct driver_data {
/* SPI framework hookup */ /* SPI framework hookup */
enum pxa_ssp_type ssp_type; enum pxa_ssp_type ssp_type;
struct spi_controller *master; struct spi_controller *controller;
/* PXA hookup */ /* PXA hookup */
struct pxa2xx_spi_master *master_info; struct pxa2xx_spi_controller *controller_info;
/* SSP register addresses */ /* SSP register addresses */
void __iomem *ioaddr; void __iomem *ioaddr;
......
This diff is collapsed.
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
struct hspi_priv { struct hspi_priv {
void __iomem *addr; void __iomem *addr;
struct spi_master *master; struct spi_controller *ctlr;
struct device *dev; struct device *dev;
struct clk *clk; struct clk *clk;
}; };
...@@ -140,10 +140,10 @@ static void hspi_hw_setup(struct hspi_priv *hspi, ...@@ -140,10 +140,10 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
hspi_write(hspi, SPSCR, 0x21); /* master mode / CS control */ hspi_write(hspi, SPSCR, 0x21); /* master mode / CS control */
} }
static int hspi_transfer_one_message(struct spi_master *master, static int hspi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *msg) struct spi_message *msg)
{ {
struct hspi_priv *hspi = spi_master_get_devdata(master); struct hspi_priv *hspi = spi_controller_get_devdata(ctlr);
struct spi_transfer *t; struct spi_transfer *t;
u32 tx; u32 tx;
u32 rx; u32 rx;
...@@ -205,7 +205,7 @@ static int hspi_transfer_one_message(struct spi_master *master, ...@@ -205,7 +205,7 @@ static int hspi_transfer_one_message(struct spi_master *master,
ndelay(nsecs); ndelay(nsecs);
hspi_hw_cs_disable(hspi); hspi_hw_cs_disable(hspi);
} }
spi_finalize_current_message(master); spi_finalize_current_message(ctlr);
return ret; return ret;
} }
...@@ -213,7 +213,7 @@ static int hspi_transfer_one_message(struct spi_master *master, ...@@ -213,7 +213,7 @@ static int hspi_transfer_one_message(struct spi_master *master,
static int hspi_probe(struct platform_device *pdev) static int hspi_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
struct spi_master *master; struct spi_controller *ctlr;
struct hspi_priv *hspi; struct hspi_priv *hspi;
struct clk *clk; struct clk *clk;
int ret; int ret;
...@@ -225,11 +225,9 @@ static int hspi_probe(struct platform_device *pdev) ...@@ -225,11 +225,9 @@ static int hspi_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
master = spi_alloc_master(&pdev->dev, sizeof(*hspi)); ctlr = spi_alloc_master(&pdev->dev, sizeof(*hspi));
if (!master) { if (!ctlr)
dev_err(&pdev->dev, "spi_alloc_master error.\n");
return -ENOMEM; return -ENOMEM;
}
clk = clk_get(&pdev->dev, NULL); clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
...@@ -238,33 +236,32 @@ static int hspi_probe(struct platform_device *pdev) ...@@ -238,33 +236,32 @@ static int hspi_probe(struct platform_device *pdev)
goto error0; goto error0;
} }
hspi = spi_master_get_devdata(master); hspi = spi_controller_get_devdata(ctlr);
platform_set_drvdata(pdev, hspi); platform_set_drvdata(pdev, hspi);
/* init hspi */ /* init hspi */
hspi->master = master; hspi->ctlr = ctlr;
hspi->dev = &pdev->dev; hspi->dev = &pdev->dev;
hspi->clk = clk; hspi->clk = clk;
hspi->addr = devm_ioremap(hspi->dev, hspi->addr = devm_ioremap(hspi->dev,
res->start, resource_size(res)); res->start, resource_size(res));
if (!hspi->addr) { if (!hspi->addr) {
dev_err(&pdev->dev, "ioremap error.\n");
ret = -ENOMEM; ret = -ENOMEM;
goto error1; goto error1;
} }
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
master->bus_num = pdev->id; ctlr->bus_num = pdev->id;
master->mode_bits = SPI_CPOL | SPI_CPHA; ctlr->mode_bits = SPI_CPOL | SPI_CPHA;
master->dev.of_node = pdev->dev.of_node; ctlr->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true; ctlr->auto_runtime_pm = true;
master->transfer_one_message = hspi_transfer_one_message; ctlr->transfer_one_message = hspi_transfer_one_message;
master->bits_per_word_mask = SPI_BPW_MASK(8); ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
ret = devm_spi_register_master(&pdev->dev, master); ret = devm_spi_register_controller(&pdev->dev, ctlr);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "spi_register_master error.\n"); dev_err(&pdev->dev, "devm_spi_register_controller error.\n");
goto error2; goto error2;
} }
...@@ -275,7 +272,7 @@ static int hspi_probe(struct platform_device *pdev) ...@@ -275,7 +272,7 @@ static int hspi_probe(struct platform_device *pdev)
error1: error1:
clk_put(clk); clk_put(clk);
error0: error0:
spi_master_put(master); spi_controller_put(ctlr);
return ret; return ret;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -490,8 +490,8 @@ static void ti_qspi_enable_memory_map(struct spi_device *spi) ...@@ -490,8 +490,8 @@ static void ti_qspi_enable_memory_map(struct spi_device *spi)
ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG); ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG);
if (qspi->ctrl_base) { if (qspi->ctrl_base) {
regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg, regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
MEM_CS_EN(spi->chip_select), MEM_CS_MASK,
MEM_CS_MASK); MEM_CS_EN(spi->chip_select));
} }
qspi->mmap_enabled = true; qspi->mmap_enabled = true;
} }
...@@ -503,7 +503,7 @@ static void ti_qspi_disable_memory_map(struct spi_device *spi) ...@@ -503,7 +503,7 @@ static void ti_qspi_disable_memory_map(struct spi_device *spi)
ti_qspi_write(qspi, 0, QSPI_SPI_SWITCH_REG); ti_qspi_write(qspi, 0, QSPI_SPI_SWITCH_REG);
if (qspi->ctrl_base) if (qspi->ctrl_base)
regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg, regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
0, MEM_CS_MASK); MEM_CS_MASK, 0);
qspi->mmap_enabled = false; qspi->mmap_enabled = false;
} }
......
...@@ -1008,6 +1008,9 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) ...@@ -1008,6 +1008,9 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
/* RX */ /* RX */
dma->sg_rx_p = kcalloc(num, sizeof(*dma->sg_rx_p), GFP_ATOMIC); dma->sg_rx_p = kcalloc(num, sizeof(*dma->sg_rx_p), GFP_ATOMIC);
if (!dma->sg_rx_p)
return;
sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */ sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */
/* offset, length setting */ /* offset, length setting */
sg = dma->sg_rx_p; sg = dma->sg_rx_p;
...@@ -1068,6 +1071,9 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) ...@@ -1068,6 +1071,9 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
} }
dma->sg_tx_p = kcalloc(num, sizeof(*dma->sg_tx_p), GFP_ATOMIC); dma->sg_tx_p = kcalloc(num, sizeof(*dma->sg_tx_p), GFP_ATOMIC);
if (!dma->sg_tx_p)
return;
sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */ sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */
/* offset, length setting */ /* offset, length setting */
sg = dma->sg_tx_p; sg = dma->sg_tx_p;
......
This diff is collapsed.
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
struct dma_chan; struct dma_chan;
/* device.platform_data for SSP controller devices */ /* device.platform_data for SSP controller devices */
struct pxa2xx_spi_master { struct pxa2xx_spi_controller {
u16 num_chipselect; u16 num_chipselect;
u8 enable_dma; u8 enable_dma;
bool is_slave; bool is_slave;
...@@ -54,7 +54,7 @@ struct pxa2xx_spi_chip { ...@@ -54,7 +54,7 @@ struct pxa2xx_spi_chip {
#include <linux/clk.h> #include <linux/clk.h>
extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info); extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_controller *info);
#endif #endif
#endif #endif
...@@ -330,6 +330,11 @@ ssize_t spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc, ...@@ -330,6 +330,11 @@ ssize_t spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
u64 offs, size_t len, void *buf); u64 offs, size_t len, void *buf);
ssize_t spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc, ssize_t spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
u64 offs, size_t len, const void *buf); u64 offs, size_t len, const void *buf);
struct spi_mem_dirmap_desc *
devm_spi_mem_dirmap_create(struct device *dev, struct spi_mem *mem,
const struct spi_mem_dirmap_info *info);
void devm_spi_mem_dirmap_destroy(struct device *dev,
struct spi_mem_dirmap_desc *desc);
int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv, int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv,
struct module *owner); struct module *owner);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/gpio/consumer.h>
struct dma_chan; struct dma_chan;
struct property_entry; struct property_entry;
...@@ -116,8 +117,13 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, ...@@ -116,8 +117,13 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
* @modalias: Name of the driver to use with this device, or an alias * @modalias: Name of the driver to use with this device, or an alias
* for that name. This appears in the sysfs "modalias" attribute * for that name. This appears in the sysfs "modalias" attribute
* for driver coldplugging, and in uevents used for hotplugging * for driver coldplugging, and in uevents used for hotplugging
* @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when * @cs_gpio: LEGACY: gpio number of the chipselect line (optional, -ENOENT when
* not using a GPIO line) use cs_gpiod in new drivers by opting in on
* the spi_master.
* @cs_gpiod: gpio descriptor of the chipselect line (optional, NULL when
* not using a GPIO line) * not using a GPIO line)
* @word_delay_usecs: microsecond delay to be inserted between consecutive
* words of a transfer
* *
* @statistics: statistics for the spi_device * @statistics: statistics for the spi_device
* *
...@@ -163,7 +169,9 @@ struct spi_device { ...@@ -163,7 +169,9 @@ struct spi_device {
void *controller_data; void *controller_data;
char modalias[SPI_NAME_SIZE]; char modalias[SPI_NAME_SIZE];
const char *driver_override; const char *driver_override;
int cs_gpio; /* chip select gpio */ int cs_gpio; /* LEGACY: chip select gpio */
struct gpio_desc *cs_gpiod; /* chip select gpio desc */
uint8_t word_delay_usecs; /* inter-word delay */
/* the statistics */ /* the statistics */
struct spi_statistics statistics; struct spi_statistics statistics;
...@@ -376,9 +384,17 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) ...@@ -376,9 +384,17 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* controller has native support for memory like operations. * controller has native support for memory like operations.
* @unprepare_message: undo any work done by prepare_message(). * @unprepare_message: undo any work done by prepare_message().
* @slave_abort: abort the ongoing transfer request on an SPI slave controller * @slave_abort: abort the ongoing transfer request on an SPI slave controller
* @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * @cs_gpios: LEGACY: array of GPIO descs to use as chip select lines; one per
* number. Any individual value may be -ENOENT for CS lines that * CS number. Any individual value may be -ENOENT for CS lines that
* are not GPIOs (driven by the SPI controller itself). Use the cs_gpiods
* in new drivers.
* @cs_gpiods: Array of GPIO descs to use as chip select lines; one per CS
* number. Any individual value may be NULL for CS lines that
* are not GPIOs (driven by the SPI controller itself). * are not GPIOs (driven by the SPI controller itself).
* @use_gpio_descriptors: Turns on the code in the SPI core to parse and grab
* GPIO descriptors rather than using global GPIO numbers grabbed by the
* driver. This will fill in @cs_gpiods and @cs_gpios should not be used,
* and SPI devices will have the cs_gpiod assigned rather than cs_gpio.
* @statistics: statistics for the spi_controller * @statistics: statistics for the spi_controller
* @dma_tx: DMA transmit channel * @dma_tx: DMA transmit channel
* @dma_rx: DMA receive channel * @dma_rx: DMA receive channel
...@@ -557,6 +573,8 @@ struct spi_controller { ...@@ -557,6 +573,8 @@ struct spi_controller {
/* gpio chip select */ /* gpio chip select */
int *cs_gpios; int *cs_gpios;
struct gpio_desc **cs_gpiods;
bool use_gpio_descriptors;
/* statistics */ /* statistics */
struct spi_statistics statistics; struct spi_statistics statistics;
...@@ -706,6 +724,8 @@ extern void spi_res_release(struct spi_controller *ctlr, ...@@ -706,6 +724,8 @@ extern void spi_res_release(struct spi_controller *ctlr,
* @delay_usecs: microseconds to delay after this transfer before * @delay_usecs: microseconds to delay after this transfer before
* (optionally) changing the chipselect status, then starting * (optionally) changing the chipselect status, then starting
* the next transfer or completing this @spi_message. * the next transfer or completing this @spi_message.
* @word_delay_usecs: microseconds to inter word delay after each word size
* (set by bits_per_word) transmission.
* @word_delay: clock cycles to inter word delay after each word size * @word_delay: clock cycles to inter word delay after each word size
* (set by bits_per_word) transmission. * (set by bits_per_word) transmission.
* @transfer_list: transfers are sequenced through @spi_message.transfers * @transfer_list: transfers are sequenced through @spi_message.transfers
...@@ -788,6 +808,7 @@ struct spi_transfer { ...@@ -788,6 +808,7 @@ struct spi_transfer {
#define SPI_NBITS_DUAL 0x02 /* 2bits transfer */ #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
#define SPI_NBITS_QUAD 0x04 /* 4bits transfer */ #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */
u8 bits_per_word; u8 bits_per_word;
u8 word_delay_usecs;
u16 delay_usecs; u16 delay_usecs;
u32 speed_hz; u32 speed_hz;
u16 word_delay; u16 word_delay;
......
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