Commit 1325b655 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi updates from Mark Brown:
 "A quiet release, more bug fixes than anything else.  A few things do
  stand out though:

   - updates to several drivers to move towards the standard GPIO chip
     select handling in the core.
   - DMA support for the SH MSIOF driver.
   - support for Rockchip SPI controllers (their first mainline
     submission)"

* tag 'spi-v3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (64 commits)
  spi: davinci: use spi_device.cs_gpio to store gpio cs per spi device
  spi: davinci: add support to configure gpio cs through dt
  spi/pl022: Explicitly truncate large bitmask
  spi/atmel: Fix pointer to int conversion warnings on 64 bit builds
  spi: davinci: fix to support more than 2 chip selects
  spi: topcliff-pch: don't hardcode PCI slot to get DMA device
  spi: orion: fix incorrect handling of cell-index DT property
  spi: orion: Fix error return code in orion_spi_probe()
  spi/rockchip: fix error return code in rockchip_spi_probe()
  spi/rockchip: remove redundant dev_err call in rockchip_spi_probe()
  spi/rockchip: remove duplicated include from spi-rockchip.c
  ARM: dts: fix the chip select gpios definition in the SPI nodes
  spi: s3c64xx: Update binding documentation
  spi: s3c64xx: use the generic SPI "cs-gpios" property
  spi: s3c64xx: Revert "spi: s3c64xx: Added provision for dedicated cs pin"
  spi: atmel: Use dmaengine_prep_slave_sg() API
  spi: topcliff-pch: Update error messages for dmaengine_prep_slave_sg() API
  spi: sh-msiof: Use correct device for DMA mapping with IOMMU
  spi: sh-msiof: Handle dmaengine_prep_slave_single() failures gracefully
  spi: rspi: Handle dmaengine_prep_slave_sg() failures gracefully
  ...
parents dc7aafba fab6a041
...@@ -10,11 +10,12 @@ Required properties: ...@@ -10,11 +10,12 @@ Required properties:
- cs-gpios: see spi-bus.txt - cs-gpios: see spi-bus.txt
Recommended properties : Recommended properties :
- efm32,location: Value to write to the ROUTE register's LOCATION bitfield to - energymicro,location: Value to write to the ROUTE register's LOCATION
configure the pinmux for the device, see datasheet for values. bitfield to configure the pinmux for the device, see
If "efm32,location" property is not provided, keeping what is datasheet for values.
already configured in the hardware, so its either the reset If this property is not provided, keeping what is
default 0 or whatever the bootloader did. already configured in the hardware, so its either the
reset default 0 or whatever the bootloader did.
Example: Example:
...@@ -26,7 +27,7 @@ spi1: spi@0x4000c400 { /* USART1 */ ...@@ -26,7 +27,7 @@ spi1: spi@0x4000c400 { /* USART1 */
interrupts = <15 16>; interrupts = <15 16>;
clocks = <&cmu 20>; clocks = <&cmu 20>;
cs-gpios = <&gpio 51 1>; // D3 cs-gpios = <&gpio 51 1>; // D3
efm32,location = <1>; energymicro,location = <1>;
status = "ok"; status = "ok";
ks8851@0 { ks8851@0 {
......
...@@ -7,7 +7,11 @@ SPI in master mode supports up to 50MHz, up to four chip selects, programmable ...@@ -7,7 +7,11 @@ SPI in master mode supports up to 50MHz, up to four chip selects, programmable
data path from 4 bits to 32 bits and numerous protocol variants. data path from 4 bits to 32 bits and numerous protocol variants.
Required properties: Required properties:
- compatible: Should contain "qcom,spi-qup-v2.1.1" or "qcom,spi-qup-v2.2.1" - compatible: Should contain:
"qcom,spi-qup-v1.1.1" for 8660, 8960 and 8064.
"qcom,spi-qup-v2.1.1" for 8974 and later
"qcom,spi-qup-v2.2.1" for 8974 v2 and later.
- reg: Should contain base register location and length - reg: Should contain base register location and length
- interrupts: Interrupt number used by this controller - interrupts: Interrupt number used by this controller
......
Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface.
Required properties:
- compatible : "snps,dw-apb-ssi"
- reg : The register base for the controller.
- interrupts : One interrupt, used by the controller.
- #address-cells : <1>, as required by generic SPI binding.
- #size-cells : <0>, also as required by generic SPI binding.
Optional properties:
- cs-gpios : Specifies the gpio pis to be used for chipselects.
- num-cs : The number of chipselects. If omitted, this will default to 4.
Child nodes as per the generic SPI binding.
Example:
spi@fff00000 {
compatible = "snps,dw-apb-ssi";
reg = <0xfff00000 0x1000>;
interrupts = <0 154 4>;
#address-cells = <1>;
#size-cells = <0>;
num-cs = <2>;
cs-gpios = <&gpio0 13 0>,
<&gpio0 14 0>;
};
...@@ -8,7 +8,8 @@ Required properties: ...@@ -8,7 +8,8 @@ Required properties:
- "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family - "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family
- "ti,da830-spi" for SPI used similar to that on DA8xx SoC family - "ti,da830-spi" for SPI used similar to that on DA8xx SoC family
- reg: Offset and length of SPI controller register space - reg: Offset and length of SPI controller register space
- num-cs: Number of chip selects - num-cs: Number of chip selects. This includes internal as well as
GPIO chip selects.
- ti,davinci-spi-intr-line: interrupt line used to connect the SPI - ti,davinci-spi-intr-line: interrupt line used to connect the SPI
IP to the interrupt controller within the SoC. Possible values IP to the interrupt controller within the SoC. Possible values
are 0 and 1. Manual says one of the two possible interrupt are 0 and 1. Manual says one of the two possible interrupt
...@@ -17,6 +18,12 @@ Required properties: ...@@ -17,6 +18,12 @@ Required properties:
- interrupts: interrupt number mapped to CPU. - interrupts: interrupt number mapped to CPU.
- clocks: spi clk phandle - clocks: spi clk phandle
Optional:
- cs-gpios: gpio chip selects
For example to have 3 internal CS and 2 GPIO CS, user could define
cs-gpios = <0>, <0>, <0>, <&gpio1 30 0>, <&gpio1 31 0>;
where first three are internal CS and last two are GPIO CS.
Example of a NOR flash slave device (n25q032) connected to DaVinci Example of a NOR flash slave device (n25q032) connected to DaVinci
SPI controller device over the SPI bus. SPI controller device over the SPI bus.
......
* Rockchip SPI Controller
The Rockchip SPI controller is used to interface with various devices such as flash
and display controllers using the SPI communication interface.
Required Properties:
- compatible: should be one of the following.
"rockchip,rk3066-spi" for rk3066.
"rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
"rockchip,rk3288-spi", "rockchip,rk3066-spi" for rk3288.
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: The interrupt number to the cpu. The interrupt specifier format
depends on the interrupt controller.
- clocks: Must contain an entry for each entry in clock-names.
- clock-names: Shall be "spiclk" for the transfer-clock, and "apb_pclk" for
the peripheral clock.
- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
Documentation/devicetree/bindings/dma/dma.txt
- dma-names: DMA request names should include "tx" and "rx" if present.
- #address-cells: should be 1.
- #size-cells: should be 0.
Example:
spi0: spi@ff110000 {
compatible = "rockchip,rk3066-spi";
reg = <0xff110000 0x1000>;
dmas = <&pdma1 11>, <&pdma1 12>;
dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
clock-names = "spiclk", "apb_pclk";
};
...@@ -18,14 +18,11 @@ Required SoC Specific Properties: ...@@ -18,14 +18,11 @@ Required SoC Specific Properties:
- interrupts: The interrupt number to the cpu. The interrupt specifier format - interrupts: The interrupt number to the cpu. The interrupt specifier format
depends on the interrupt controller. depends on the interrupt controller.
[PRELIMINARY: the dma channel allocation will change once there are - dmas : Two or more DMA channel specifiers following the convention outlined
official DMA bindings] in bindings/dma/dma.txt
- tx-dma-channel: The dma channel specifier for tx operations. The format of - dma-names: Names for the dma channels. There must be at least one channel
the dma specifier depends on the dma controller. named "tx" for transmit and named "rx" for receive.
- rx-dma-channel: The dma channel specifier for rx operations. The format of
the dma specifier depends on the dma controller.
Required Board Specific Properties: Required Board Specific Properties:
...@@ -42,15 +39,13 @@ Optional Board Specific Properties: ...@@ -42,15 +39,13 @@ Optional Board Specific Properties:
- num-cs: Specifies the number of chip select lines supported. If - num-cs: Specifies the number of chip select lines supported. If
not specified, the default number of chip select lines is set to 1. not specified, the default number of chip select lines is set to 1.
- cs-gpios: should specify GPIOs used for chipselects (see spi-bus.txt)
SPI Controller specific data in SPI slave nodes: SPI Controller specific data in SPI slave nodes:
- The spi slave nodes should provide the following information which is required - The spi slave nodes should provide the following information which is required
by the spi controller. by the spi controller.
- cs-gpio: A gpio specifier that specifies the gpio line used as
the slave select line by the spi controller. The format of the gpio
specifier depends on the gpio controller.
- samsung,spi-feedback-delay: The sampling phase shift to be applied on the - samsung,spi-feedback-delay: The sampling phase shift to be applied on the
miso line (to account for any lag in the miso line). The following are the miso line (to account for any lag in the miso line). The following are the
valid values. valid values.
...@@ -74,8 +69,11 @@ Example: ...@@ -74,8 +69,11 @@ Example:
compatible = "samsung,exynos4210-spi"; compatible = "samsung,exynos4210-spi";
reg = <0x12d20000 0x100>; reg = <0x12d20000 0x100>;
interrupts = <0 66 0>; interrupts = <0 66 0>;
tx-dma-channel = <&pdma0 5>; dmas = <&pdma0 5
rx-dma-channel = <&pdma0 4>; &pdma0 4>;
dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
}; };
- Board Specific Portion: - Board Specific Portion:
...@@ -85,6 +83,7 @@ Example: ...@@ -85,6 +83,7 @@ Example:
#size-cells = <0>; #size-cells = <0>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&spi0_bus>; pinctrl-0 = <&spi0_bus>;
cs-gpios = <&gpa2 5 0>;
w25q80bw@0 { w25q80bw@0 {
#address-cells = <1>; #address-cells = <1>;
...@@ -94,7 +93,6 @@ Example: ...@@ -94,7 +93,6 @@ Example:
spi-max-frequency = <10000>; spi-max-frequency = <10000>;
controller-data { controller-data {
cs-gpio = <&gpa2 5 1 0 3>;
samsung,spi-feedback-delay = <0>; samsung,spi-feedback-delay = <0>;
}; };
......
...@@ -168,6 +168,7 @@ eeprom@52 { ...@@ -168,6 +168,7 @@ eeprom@52 {
}; };
spi_2: spi@13940000 { spi_2: spi@13940000 {
cs-gpios = <&gpc1 2 0>;
status = "okay"; status = "okay";
w25x80@0 { w25x80@0 {
...@@ -178,7 +179,6 @@ w25x80@0 { ...@@ -178,7 +179,6 @@ w25x80@0 {
spi-max-frequency = <1000000>; spi-max-frequency = <1000000>;
controller-data { controller-data {
cs-gpio = <&gpc1 2 0>;
samsung,spi-feedback-delay = <0>; samsung,spi-feedback-delay = <0>;
}; };
......
...@@ -589,6 +589,7 @@ cm36651@18 { ...@@ -589,6 +589,7 @@ cm36651@18 {
spi_1: spi@13930000 { spi_1: spi@13930000 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&spi1_bus>; pinctrl-0 = <&spi1_bus>;
cs-gpios = <&gpb 5 0>;
status = "okay"; status = "okay";
s5c73m3_spi: s5c73m3 { s5c73m3_spi: s5c73m3 {
...@@ -596,7 +597,6 @@ s5c73m3_spi: s5c73m3 { ...@@ -596,7 +597,6 @@ s5c73m3_spi: s5c73m3 {
spi-max-frequency = <50000000>; spi-max-frequency = <50000000>;
reg = <0>; reg = <0>;
controller-data { controller-data {
cs-gpio = <&gpb 5 0>;
samsung,spi-feedback-delay = <2>; samsung,spi-feedback-delay = <2>;
}; };
}; };
......
...@@ -316,6 +316,7 @@ slot@0 { ...@@ -316,6 +316,7 @@ slot@0 {
}; };
spi_1: spi@12d30000 { spi_1: spi@12d30000 {
cs-gpios = <&gpa2 5 0>;
status = "okay"; status = "okay";
w25q80bw@0 { w25q80bw@0 {
...@@ -326,7 +327,6 @@ w25q80bw@0 { ...@@ -326,7 +327,6 @@ w25q80bw@0 {
spi-max-frequency = <1000000>; spi-max-frequency = <1000000>;
controller-data { controller-data {
cs-gpio = <&gpa2 5 0>;
samsung,spi-feedback-delay = <0>; samsung,spi-feedback-delay = <0>;
}; };
......
...@@ -382,9 +382,21 @@ config SPI_PXA2XX ...@@ -382,9 +382,21 @@ config SPI_PXA2XX
config SPI_PXA2XX_PCI config SPI_PXA2XX_PCI
def_tristate SPI_PXA2XX && PCI def_tristate SPI_PXA2XX && PCI
config SPI_ROCKCHIP
tristate "Rockchip SPI controller driver"
depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SUPERH
help
This selects a driver for Rockchip SPI controller.
If you say yes to this option, support will be included for
RK3066, RK3188 and RK3288 families of SPI controller.
Rockchip SPI controller support DMA transport and PIO mode.
The main usecase of this controller is to use spi flash as boot
device.
config SPI_RSPI config SPI_RSPI
tristate "Renesas RSPI/QSPI controller" tristate "Renesas RSPI/QSPI controller"
depends on (SUPERH && SH_DMAE_BASE) || ARCH_SHMOBILE depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
help help
SPI driver for Renesas RSPI and QSPI blocks. SPI driver for Renesas RSPI and QSPI blocks.
...@@ -434,7 +446,7 @@ config SPI_SC18IS602 ...@@ -434,7 +446,7 @@ config SPI_SC18IS602
config SPI_SH_MSIOF config SPI_SH_MSIOF
tristate "SuperH MSIOF SPI controller" tristate "SuperH MSIOF SPI controller"
depends on HAVE_CLK depends on HAVE_CLK && HAS_DMA
depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
help help
SPI driver for SuperH and SH Mobile MSIOF blocks. SPI driver for SuperH and SH Mobile MSIOF blocks.
......
...@@ -61,6 +61,7 @@ spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o ...@@ -61,6 +61,7 @@ spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_QUP) += spi-qup.o
obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
spi-s3c24xx-hw-y := spi-s3c24xx.o spi-s3c24xx-hw-y := spi-s3c24xx.o
......
...@@ -660,10 +660,9 @@ static int adi_spi_setup(struct spi_device *spi) ...@@ -660,10 +660,9 @@ static int adi_spi_setup(struct spi_device *spi)
struct adi_spi3_chip *chip_info = spi->controller_data; struct adi_spi3_chip *chip_info = spi->controller_data;
chip = kzalloc(sizeof(*chip), GFP_KERNEL); chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip) { if (!chip)
dev_err(&spi->dev, "can not allocate chip data\n");
return -ENOMEM; return -ENOMEM;
}
if (chip_info) { if (chip_info) {
if (chip_info->control & ~ctl_reg) { if (chip_info->control & ~ctl_reg) {
dev_err(&spi->dev, dev_err(&spi->dev,
......
...@@ -597,21 +597,15 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, ...@@ -597,21 +597,15 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
goto err_exit; goto err_exit;
/* Send both scatterlists */ /* Send both scatterlists */
rxdesc = rxchan->device->device_prep_slave_sg(rxchan, rxdesc = dmaengine_prep_slave_sg(rxchan, &as->dma.sgrx, 1,
&as->dma.sgrx, DMA_FROM_DEVICE,
1, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
DMA_FROM_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
NULL);
if (!rxdesc) if (!rxdesc)
goto err_dma; goto err_dma;
txdesc = txchan->device->device_prep_slave_sg(txchan, txdesc = dmaengine_prep_slave_sg(txchan, &as->dma.sgtx, 1,
&as->dma.sgtx, DMA_TO_DEVICE,
1, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
DMA_TO_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
NULL);
if (!txdesc) if (!txdesc)
goto err_dma; goto err_dma;
...@@ -1018,7 +1012,7 @@ static int atmel_spi_setup(struct spi_device *spi) ...@@ -1018,7 +1012,7 @@ static int atmel_spi_setup(struct spi_device *spi)
csr |= SPI_BF(DLYBCT, 0); csr |= SPI_BF(DLYBCT, 0);
/* chipselect must have been muxed as GPIO (e.g. in board setup) */ /* chipselect must have been muxed as GPIO (e.g. in board setup) */
npcs_pin = (unsigned int)spi->controller_data; npcs_pin = (unsigned long)spi->controller_data;
if (gpio_is_valid(spi->cs_gpio)) if (gpio_is_valid(spi->cs_gpio))
npcs_pin = spi->cs_gpio; npcs_pin = spi->cs_gpio;
...@@ -1253,7 +1247,7 @@ static int atmel_spi_transfer_one_message(struct spi_master *master, ...@@ -1253,7 +1247,7 @@ static int atmel_spi_transfer_one_message(struct spi_master *master,
static void atmel_spi_cleanup(struct spi_device *spi) static void atmel_spi_cleanup(struct spi_device *spi)
{ {
struct atmel_spi_device *asd = spi->controller_state; struct atmel_spi_device *asd = spi->controller_state;
unsigned gpio = (unsigned) spi->controller_data; unsigned gpio = (unsigned long) spi->controller_data;
if (!asd) if (!asd)
return; return;
......
...@@ -925,8 +925,7 @@ static int au1550_spi_probe(struct platform_device *pdev) ...@@ -925,8 +925,7 @@ static int au1550_spi_probe(struct platform_device *pdev)
iounmap((void __iomem *)hw->regs); iounmap((void __iomem *)hw->regs);
err_ioremap: err_ioremap:
release_resource(hw->ioarea); release_mem_region(r->start, sizeof(psc_spi_t));
kfree(hw->ioarea);
err_no_iores: err_no_iores:
err_no_pdata: err_no_pdata:
...@@ -946,8 +945,7 @@ static int au1550_spi_remove(struct platform_device *pdev) ...@@ -946,8 +945,7 @@ static int au1550_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&hw->bitbang); spi_bitbang_stop(&hw->bitbang);
free_irq(hw->irq, hw); free_irq(hw->irq, hw);
iounmap((void __iomem *)hw->regs); iounmap((void __iomem *)hw->regs);
release_resource(hw->ioarea); release_mem_region(r->start, sizeof(psc_spi_t));
kfree(hw->ioarea);
if (hw->usedma) { if (hw->usedma) {
au1550_spi_dma_rxtmp_free(hw); au1550_spi_dma_rxtmp_free(hw);
......
...@@ -205,18 +205,30 @@ static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) ...@@ -205,18 +205,30 @@ static void cdns_spi_chipselect(struct spi_device *spi, bool is_high)
static void cdns_spi_config_clock_mode(struct spi_device *spi) static void cdns_spi_config_clock_mode(struct spi_device *spi)
{ {
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, new_ctrl_reg;
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET);
/* Set the SPI clock phase and clock polarity */ /* Set the SPI clock phase and clock polarity */
ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK);
if (spi->mode & SPI_CPHA) if (spi->mode & SPI_CPHA)
ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; new_ctrl_reg |= CDNS_SPI_CR_CPHA_MASK;
if (spi->mode & SPI_CPOL) if (spi->mode & SPI_CPOL)
ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; new_ctrl_reg |= CDNS_SPI_CR_CPOL_MASK;
cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); if (new_ctrl_reg != ctrl_reg) {
/*
* Just writing the CR register does not seem to apply the clock
* setting changes. This is problematic when changing the clock
* polarity as it will cause the SPI slave to see spurious clock
* transitions. To workaround the issue toggle the ER register.
*/
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_DISABLE_MASK);
cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, new_ctrl_reg);
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_ENABLE_MASK);
}
} }
/** /**
...@@ -370,6 +382,12 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) ...@@ -370,6 +382,12 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
return status; return status;
} }
static int cdns_prepare_message(struct spi_master *master,
struct spi_message *msg)
{
cdns_spi_config_clock_mode(msg->spi);
return 0;
}
/** /**
* cdns_transfer_one - Initiates the SPI transfer * cdns_transfer_one - Initiates the SPI transfer
...@@ -416,8 +434,6 @@ static int cdns_prepare_transfer_hardware(struct spi_master *master) ...@@ -416,8 +434,6 @@ static int cdns_prepare_transfer_hardware(struct spi_master *master)
{ {
struct cdns_spi *xspi = spi_master_get_devdata(master); struct cdns_spi *xspi = spi_master_get_devdata(master);
cdns_spi_config_clock_mode(master->cur_msg->spi);
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_ENABLE_MASK); CDNS_SPI_ER_ENABLE_MASK);
...@@ -532,6 +548,7 @@ static int cdns_spi_probe(struct platform_device *pdev) ...@@ -532,6 +548,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
xspi->is_decoded_cs = 0; xspi->is_decoded_cs = 0;
master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
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;
...@@ -647,7 +664,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) ...@@ -647,7 +664,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend, static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend,
cdns_spi_resume); cdns_spi_resume);
static struct of_device_id cdns_spi_of_match[] = { static const struct of_device_id cdns_spi_of_match[] = {
{ .compatible = "xlnx,zynq-spi-r1p6" }, { .compatible = "xlnx,zynq-spi-r1p6" },
{ .compatible = "cdns,spi-r1p6" }, { .compatible = "cdns,spi-r1p6" },
{ /* end of table */ } { /* end of table */ }
......
...@@ -184,8 +184,6 @@ static int spi_clps711x_probe(struct platform_device *pdev) ...@@ -184,8 +184,6 @@ static int spi_clps711x_probe(struct platform_device *pdev)
} }
master->max_speed_hz = clk_get_rate(hw->spi_clk); master->max_speed_hz = clk_get_rate(hw->spi_clk);
platform_set_drvdata(pdev, master);
hw->syscon = syscon_regmap_lookup_by_pdevname("syscon.3"); hw->syscon = syscon_regmap_lookup_by_pdevname("syscon.3");
if (IS_ERR(hw->syscon)) { if (IS_ERR(hw->syscon)) {
ret = PTR_ERR(hw->syscon); ret = PTR_ERR(hw->syscon);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/edma.h> #include <linux/edma.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>
...@@ -38,8 +39,6 @@ ...@@ -38,8 +39,6 @@
#define SPI_NO_RESOURCE ((resource_size_t)-1) #define SPI_NO_RESOURCE ((resource_size_t)-1)
#define SPI_MAX_CHIPSELECT 2
#define CS_DEFAULT 0xFF #define CS_DEFAULT 0xFF
#define SPIFMT_PHASE_MASK BIT(16) #define SPIFMT_PHASE_MASK BIT(16)
...@@ -142,7 +141,7 @@ struct davinci_spi { ...@@ -142,7 +141,7 @@ struct davinci_spi {
void (*get_rx)(u32 rx_data, struct davinci_spi *); void (*get_rx)(u32 rx_data, struct davinci_spi *);
u32 (*get_tx)(struct davinci_spi *); u32 (*get_tx)(struct davinci_spi *);
u8 bytes_per_word[SPI_MAX_CHIPSELECT]; u8 *bytes_per_word;
}; };
static struct davinci_spi_config davinci_spi_default_cfg; static struct davinci_spi_config davinci_spi_default_cfg;
...@@ -213,13 +212,16 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -213,13 +212,16 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
u8 chip_sel = spi->chip_select; u8 chip_sel = spi->chip_select;
u16 spidat1 = CS_DEFAULT; u16 spidat1 = CS_DEFAULT;
bool gpio_chipsel = false; bool gpio_chipsel = false;
int gpio;
dspi = spi_master_get_devdata(spi->master); dspi = spi_master_get_devdata(spi->master);
pdata = &dspi->pdata; pdata = &dspi->pdata;
if (pdata->chip_sel && chip_sel < pdata->num_chipselect && if (spi->cs_gpio >= 0) {
pdata->chip_sel[chip_sel] != SPI_INTERN_CS) /* SPI core parse and update master->cs_gpio */
gpio_chipsel = true; gpio_chipsel = true;
gpio = spi->cs_gpio;
}
/* /*
* Board specific chip select logic decides the polarity and cs * Board specific chip select logic decides the polarity and cs
...@@ -227,9 +229,9 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -227,9 +229,9 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
*/ */
if (gpio_chipsel) { if (gpio_chipsel) {
if (value == BITBANG_CS_ACTIVE) if (value == BITBANG_CS_ACTIVE)
gpio_set_value(pdata->chip_sel[chip_sel], 0); gpio_set_value(gpio, spi->mode & SPI_CS_HIGH);
else else
gpio_set_value(pdata->chip_sel[chip_sel], 1); gpio_set_value(gpio, !(spi->mode & SPI_CS_HIGH));
} else { } else {
if (value == BITBANG_CS_ACTIVE) { if (value == BITBANG_CS_ACTIVE) {
spidat1 |= SPIDAT1_CSHOLD_MASK; spidat1 |= SPIDAT1_CSHOLD_MASK;
...@@ -392,17 +394,40 @@ static int davinci_spi_setup(struct spi_device *spi) ...@@ -392,17 +394,40 @@ static int davinci_spi_setup(struct spi_device *spi)
int retval = 0; int retval = 0;
struct davinci_spi *dspi; struct davinci_spi *dspi;
struct davinci_spi_platform_data *pdata; struct davinci_spi_platform_data *pdata;
struct spi_master *master = spi->master;
struct device_node *np = spi->dev.of_node;
bool internal_cs = true;
unsigned long flags = GPIOF_DIR_OUT;
dspi = spi_master_get_devdata(spi->master); dspi = spi_master_get_devdata(spi->master);
pdata = &dspi->pdata; pdata = &dspi->pdata;
flags |= (spi->mode & SPI_CS_HIGH) ? GPIOF_INIT_LOW : GPIOF_INIT_HIGH;
if (!(spi->mode & SPI_NO_CS)) { if (!(spi->mode & SPI_NO_CS)) {
if ((pdata->chip_sel == NULL) || if (np && (master->cs_gpios != NULL) && (spi->cs_gpio >= 0)) {
(pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS)) retval = gpio_request_one(spi->cs_gpio,
set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select); flags, dev_name(&spi->dev));
internal_cs = false;
} else if (pdata->chip_sel &&
spi->chip_select < pdata->num_chipselect &&
pdata->chip_sel[spi->chip_select] != SPI_INTERN_CS) {
spi->cs_gpio = pdata->chip_sel[spi->chip_select];
retval = gpio_request_one(spi->cs_gpio,
flags, dev_name(&spi->dev));
internal_cs = false;
}
}
if (retval) {
dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
spi->cs_gpio, retval);
return retval;
} }
if (internal_cs)
set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
if (spi->mode & SPI_READY) if (spi->mode & SPI_READY)
set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK); set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);
...@@ -414,6 +439,12 @@ static int davinci_spi_setup(struct spi_device *spi) ...@@ -414,6 +439,12 @@ static int davinci_spi_setup(struct spi_device *spi)
return retval; return retval;
} }
static void davinci_spi_cleanup(struct spi_device *spi)
{
if (spi->cs_gpio >= 0)
gpio_free(spi->cs_gpio);
}
static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status) static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
{ {
struct device *sdev = dspi->bitbang.master->dev.parent; struct device *sdev = dspi->bitbang.master->dev.parent;
...@@ -812,6 +843,8 @@ static int spi_davinci_get_pdata(struct platform_device *pdev, ...@@ -812,6 +843,8 @@ static int spi_davinci_get_pdata(struct platform_device *pdev,
/* /*
* default num_cs is 1 and all chipsel are internal to the chip * default num_cs is 1 and all chipsel are internal to the chip
* indicated by chip_sel being NULL or cs_gpios being NULL or
* set to -ENOENT. num-cs includes internal as well as gpios.
* indicated by chip_sel being NULL. GPIO based CS is not * indicated by chip_sel being NULL. GPIO based CS is not
* supported yet in DT bindings. * supported yet in DT bindings.
*/ */
...@@ -850,7 +883,7 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -850,7 +883,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
struct resource *r; struct resource *r;
resource_size_t dma_rx_chan = SPI_NO_RESOURCE; resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
resource_size_t dma_tx_chan = SPI_NO_RESOURCE; resource_size_t dma_tx_chan = SPI_NO_RESOURCE;
int i = 0, ret = 0; int ret = 0;
u32 spipc0; u32 spipc0;
master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi)); master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
...@@ -876,6 +909,14 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -876,6 +909,14 @@ static int davinci_spi_probe(struct platform_device *pdev)
/* pdata in dspi is now updated and point pdata to that */ /* pdata in dspi is now updated and point pdata to that */
pdata = &dspi->pdata; pdata = &dspi->pdata;
dspi->bytes_per_word = devm_kzalloc(&pdev->dev,
sizeof(*dspi->bytes_per_word) *
pdata->num_chipselect, GFP_KERNEL);
if (dspi->bytes_per_word == NULL) {
ret = -ENOMEM;
goto free_master;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) { if (r == NULL) {
ret = -ENOENT; ret = -ENOENT;
...@@ -915,6 +956,7 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -915,6 +956,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
master->num_chipselect = pdata->num_chipselect; master->num_chipselect = pdata->num_chipselect;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16);
master->setup = davinci_spi_setup; master->setup = davinci_spi_setup;
master->cleanup = davinci_spi_cleanup;
dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.chipselect = davinci_spi_chipselect;
dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
...@@ -962,14 +1004,6 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -962,14 +1004,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
spipc0 = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK; spipc0 = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK;
iowrite32(spipc0, dspi->base + SPIPC0); iowrite32(spipc0, dspi->base + SPIPC0);
/* initialize chip selects */
if (pdata->chip_sel) {
for (i = 0; i < pdata->num_chipselect; i++) {
if (pdata->chip_sel[i] != SPI_INTERN_CS)
gpio_direction_output(pdata->chip_sel[i], 1);
}
}
if (pdata->intr_line) if (pdata->intr_line)
iowrite32(SPI_INTLVL_1, dspi->base + SPILVL); iowrite32(SPI_INTLVL_1, dspi->base + SPILVL);
else else
......
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include "spi-dw.h" #include "spi-dw.h"
...@@ -33,6 +35,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) ...@@ -33,6 +35,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
struct dw_spi *dws; struct dw_spi *dws;
struct resource *mem; struct resource *mem;
int ret; int ret;
int num_cs;
dwsmmio = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_mmio), dwsmmio = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_mmio),
GFP_KERNEL); GFP_KERNEL);
...@@ -68,9 +71,16 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) ...@@ -68,9 +71,16 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
return ret; return ret;
dws->bus_num = pdev->id; dws->bus_num = pdev->id;
dws->num_cs = 4;
dws->max_freq = clk_get_rate(dwsmmio->clk); dws->max_freq = clk_get_rate(dwsmmio->clk);
num_cs = 4;
if (pdev->dev.of_node)
of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
dws->num_cs = num_cs;
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
int i; int i;
...@@ -114,12 +124,19 @@ static int dw_spi_mmio_remove(struct platform_device *pdev) ...@@ -114,12 +124,19 @@ static int dw_spi_mmio_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id dw_spi_mmio_of_match[] = {
{ .compatible = "snps,dw-apb-ssi", },
{ /* end of table */}
};
MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
static struct platform_driver dw_spi_mmio_driver = { static struct platform_driver dw_spi_mmio_driver = {
.probe = dw_spi_mmio_probe, .probe = dw_spi_mmio_probe,
.remove = dw_spi_mmio_remove, .remove = dw_spi_mmio_remove,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = dw_spi_mmio_of_match,
}, },
}; };
module_platform_driver(dw_spi_mmio_driver); module_platform_driver(dw_spi_mmio_driver);
......
...@@ -294,10 +294,16 @@ static void efm32_spi_probe_dt(struct platform_device *pdev, ...@@ -294,10 +294,16 @@ static void efm32_spi_probe_dt(struct platform_device *pdev,
u32 location; u32 location;
int ret; int ret;
ret = of_property_read_u32(np, "efm32,location", &location); ret = of_property_read_u32(np, "energymicro,location", &location);
if (ret)
/* fall back to wrongly namespaced property */
ret = of_property_read_u32(np, "efm32,location", &location);
if (ret) if (ret)
/* fall back to old and (wrongly) generic property "location" */ /* fall back to old and (wrongly) generic property "location" */
ret = of_property_read_u32(np, "location", &location); ret = of_property_read_u32(np, "location", &location);
if (!ret) { if (!ret) {
dev_dbg(&pdev->dev, "using location %u\n", location); dev_dbg(&pdev->dev, "using location %u\n", location);
} else { } else {
......
...@@ -425,8 +425,6 @@ static int falcon_sflash_probe(struct platform_device *pdev) ...@@ -425,8 +425,6 @@ static int falcon_sflash_probe(struct platform_device *pdev)
master->unprepare_transfer_hardware = falcon_sflash_unprepare_xfer; master->unprepare_transfer_hardware = falcon_sflash_unprepare_xfer;
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
platform_set_drvdata(pdev, priv);
ret = devm_spi_register_master(&pdev->dev, master); ret = devm_spi_register_master(&pdev->dev, master);
if (ret) if (ret)
spi_master_put(master); spi_master_put(master);
......
...@@ -196,7 +196,7 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev) ...@@ -196,7 +196,7 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
pinfo = devm_kzalloc(&ofdev->dev, sizeof(*pinfo), GFP_KERNEL); pinfo = devm_kzalloc(&ofdev->dev, sizeof(*pinfo), GFP_KERNEL);
if (!pinfo) if (!pinfo)
return -ENOMEM; return ret;
pdata = &pinfo->pdata; pdata = &pinfo->pdata;
dev->platform_data = pdata; dev->platform_data = pdata;
......
...@@ -58,7 +58,7 @@ static struct fsl_spi_match_data of_fsl_spi_grlib_config = { ...@@ -58,7 +58,7 @@ static struct fsl_spi_match_data of_fsl_spi_grlib_config = {
.type = TYPE_GRLIB, .type = TYPE_GRLIB,
}; };
static struct of_device_id of_fsl_spi_match[] = { static const struct of_device_id of_fsl_spi_match[] = {
{ {
.compatible = "fsl,spi", .compatible = "fsl,spi",
.data = &of_fsl_spi_fsl_config, .data = &of_fsl_spi_fsl_config,
......
...@@ -420,8 +420,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev) ...@@ -420,8 +420,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16); master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16);
master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ; master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ;
platform_set_drvdata(pdev, master);
spi100k = spi_master_get_devdata(master); spi100k = spi_master_get_devdata(master);
/* /*
......
...@@ -41,14 +41,15 @@ ...@@ -41,14 +41,15 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.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/module.h> #include <linux/module.h>
#include <linux/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/io.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <mach/mux.h> #include <mach/mux.h>
...@@ -447,7 +448,6 @@ static void uwire_off(struct uwire_spi *uwire) ...@@ -447,7 +448,6 @@ static void uwire_off(struct uwire_spi *uwire)
{ {
uwire_write_reg(UWIRE_SR3, 0); uwire_write_reg(UWIRE_SR3, 0);
clk_disable(uwire->ck); clk_disable(uwire->ck);
clk_put(uwire->ck);
spi_master_put(uwire->bitbang.master); spi_master_put(uwire->bitbang.master);
} }
...@@ -463,7 +463,7 @@ static int uwire_probe(struct platform_device *pdev) ...@@ -463,7 +463,7 @@ static int uwire_probe(struct platform_device *pdev)
uwire = spi_master_get_devdata(master); uwire = spi_master_get_devdata(master);
uwire_base = ioremap(UWIRE_BASE_PHYS, UWIRE_IO_SIZE); uwire_base = devm_ioremap(&pdev->dev, UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
if (!uwire_base) { if (!uwire_base) {
dev_dbg(&pdev->dev, "can't ioremap UWIRE\n"); dev_dbg(&pdev->dev, "can't ioremap UWIRE\n");
spi_master_put(master); spi_master_put(master);
...@@ -472,12 +472,11 @@ static int uwire_probe(struct platform_device *pdev) ...@@ -472,12 +472,11 @@ static int uwire_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, uwire); platform_set_drvdata(pdev, uwire);
uwire->ck = clk_get(&pdev->dev, "fck"); uwire->ck = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(uwire->ck)) { if (IS_ERR(uwire->ck)) {
status = PTR_ERR(uwire->ck); status = PTR_ERR(uwire->ck);
dev_dbg(&pdev->dev, "no functional clock?\n"); dev_dbg(&pdev->dev, "no functional clock?\n");
spi_master_put(master); spi_master_put(master);
iounmap(uwire_base);
return status; return status;
} }
clk_enable(uwire->ck); clk_enable(uwire->ck);
...@@ -507,7 +506,6 @@ static int uwire_probe(struct platform_device *pdev) ...@@ -507,7 +506,6 @@ static int uwire_probe(struct platform_device *pdev)
status = spi_bitbang_start(&uwire->bitbang); status = spi_bitbang_start(&uwire->bitbang);
if (status < 0) { if (status < 0) {
uwire_off(uwire); uwire_off(uwire);
iounmap(uwire_base);
} }
return status; return status;
} }
...@@ -520,7 +518,6 @@ static int uwire_remove(struct platform_device *pdev) ...@@ -520,7 +518,6 @@ static int uwire_remove(struct platform_device *pdev)
spi_bitbang_stop(&uwire->bitbang); spi_bitbang_stop(&uwire->bitbang);
uwire_off(uwire); uwire_off(uwire);
iounmap(uwire_base);
return 0; return 0;
} }
......
...@@ -149,6 +149,7 @@ struct omap2_mcspi_cs { ...@@ -149,6 +149,7 @@ struct omap2_mcspi_cs {
void __iomem *base; void __iomem *base;
unsigned long phys; unsigned long phys;
int word_len; int word_len;
u16 mode;
struct list_head node; struct list_head node;
/* Context save and restore shadow register */ /* Context save and restore shadow register */
u32 chconf0, chctrl0; u32 chconf0, chctrl0;
...@@ -926,6 +927,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, ...@@ -926,6 +927,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
mcspi_write_chconf0(spi, l); mcspi_write_chconf0(spi, l);
cs->mode = spi->mode;
dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
speed_hz, speed_hz,
(spi->mode & SPI_CPHA) ? "trailing" : "leading", (spi->mode & SPI_CPHA) ? "trailing" : "leading",
...@@ -998,6 +1001,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) ...@@ -998,6 +1001,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
return -ENOMEM; return -ENOMEM;
cs->base = mcspi->base + spi->chip_select * 0x14; cs->base = mcspi->base + spi->chip_select * 0x14;
cs->phys = mcspi->phys + spi->chip_select * 0x14; cs->phys = mcspi->phys + spi->chip_select * 0x14;
cs->mode = 0;
cs->chconf0 = 0; cs->chconf0 = 0;
cs->chctrl0 = 0; cs->chctrl0 = 0;
spi->controller_state = cs; spi->controller_state = cs;
...@@ -1079,6 +1083,16 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -1079,6 +1083,16 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
cs = spi->controller_state; cs = spi->controller_state;
cd = spi->controller_data; cd = spi->controller_data;
/*
* The slave driver could have changed spi->mode in which case
* it will be different from cs->mode (the current hardware setup).
* If so, set par_override (even though its not a parity issue) so
* omap2_mcspi_setup_transfer will be called to configure the hardware
* with the correct mode on the first iteration of the loop below.
*/
if (spi->mode != cs->mode)
par_override = 1;
omap2_mcspi_set_enable(spi, 0); omap2_mcspi_set_enable(spi, 0);
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/sizes.h> #include <linux/sizes.h>
...@@ -23,6 +24,9 @@ ...@@ -23,6 +24,9 @@
#define DRIVER_NAME "orion_spi" #define DRIVER_NAME "orion_spi"
/* Runtime PM autosuspend timeout: PM is fairly light on this driver */
#define SPI_AUTOSUSPEND_TIMEOUT 200
#define ORION_NUM_CHIPSELECTS 1 /* only one slave is supported*/ #define ORION_NUM_CHIPSELECTS 1 /* only one slave is supported*/
#define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */ #define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */
...@@ -277,7 +281,6 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -277,7 +281,6 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
return xfer->len - count; return xfer->len - count;
} }
static int orion_spi_transfer_one_message(struct spi_master *master, static int orion_spi_transfer_one_message(struct spi_master *master,
struct spi_message *m) struct spi_message *m)
{ {
...@@ -346,8 +349,6 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -346,8 +349,6 @@ static int orion_spi_probe(struct platform_device *pdev)
struct resource *r; struct resource *r;
unsigned long tclk_hz; unsigned long tclk_hz;
int status = 0; int status = 0;
const u32 *iprop;
int size;
master = spi_alloc_master(&pdev->dev, sizeof(*spi)); master = spi_alloc_master(&pdev->dev, sizeof(*spi));
if (master == NULL) { if (master == NULL) {
...@@ -358,10 +359,10 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -358,10 +359,10 @@ static int orion_spi_probe(struct platform_device *pdev)
if (pdev->id != -1) if (pdev->id != -1)
master->bus_num = pdev->id; master->bus_num = pdev->id;
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
iprop = of_get_property(pdev->dev.of_node, "cell-index", u32 cell_index;
&size); if (!of_property_read_u32(pdev->dev.of_node, "cell-index",
if (iprop && size == sizeof(*iprop)) &cell_index))
master->bus_num = *iprop; master->bus_num = cell_index;
} }
/* we support only mode 0, and no options */ /* we support only mode 0, and no options */
...@@ -370,6 +371,7 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -370,6 +371,7 @@ static int orion_spi_probe(struct platform_device *pdev)
master->transfer_one_message = orion_spi_transfer_one_message; master->transfer_one_message = orion_spi_transfer_one_message;
master->num_chipselect = ORION_NUM_CHIPSELECTS; master->num_chipselect = ORION_NUM_CHIPSELECTS;
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
master->auto_runtime_pm = true;
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
...@@ -382,8 +384,10 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -382,8 +384,10 @@ static int orion_spi_probe(struct platform_device *pdev)
goto out; goto out;
} }
clk_prepare(spi->clk); status = clk_prepare_enable(spi->clk);
clk_enable(spi->clk); if (status)
goto out;
tclk_hz = clk_get_rate(spi->clk); tclk_hz = clk_get_rate(spi->clk);
master->max_speed_hz = DIV_ROUND_UP(tclk_hz, 4); master->max_speed_hz = DIV_ROUND_UP(tclk_hz, 4);
master->min_speed_hz = DIV_ROUND_UP(tclk_hz, 30); master->min_speed_hz = DIV_ROUND_UP(tclk_hz, 30);
...@@ -395,16 +399,27 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -395,16 +399,27 @@ static int orion_spi_probe(struct platform_device *pdev)
goto out_rel_clk; goto out_rel_clk;
} }
if (orion_spi_reset(spi) < 0) pm_runtime_set_active(&pdev->dev);
goto out_rel_clk; pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
pm_runtime_enable(&pdev->dev);
status = orion_spi_reset(spi);
if (status < 0)
goto out_rel_pm;
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
status = devm_spi_register_master(&pdev->dev, master); status = spi_register_master(master);
if (status < 0) if (status < 0)
goto out_rel_clk; goto out_rel_pm;
return status; return status;
out_rel_pm:
pm_runtime_disable(&pdev->dev);
out_rel_clk: out_rel_clk:
clk_disable_unprepare(spi->clk); clk_disable_unprepare(spi->clk);
out: out:
...@@ -415,19 +430,45 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -415,19 +430,45 @@ static int orion_spi_probe(struct platform_device *pdev)
static int orion_spi_remove(struct platform_device *pdev) static int orion_spi_remove(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master = platform_get_drvdata(pdev);
struct orion_spi *spi; struct orion_spi *spi = spi_master_get_devdata(master);
master = platform_get_drvdata(pdev);
spi = spi_master_get_devdata(master);
pm_runtime_get_sync(&pdev->dev);
clk_disable_unprepare(spi->clk); clk_disable_unprepare(spi->clk);
spi_unregister_master(master);
pm_runtime_disable(&pdev->dev);
return 0; return 0;
} }
MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_ALIAS("platform:" DRIVER_NAME);
#ifdef CONFIG_PM_RUNTIME
static int orion_spi_runtime_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct orion_spi *spi = spi_master_get_devdata(master);
clk_disable_unprepare(spi->clk);
return 0;
}
static int orion_spi_runtime_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct orion_spi *spi = spi_master_get_devdata(master);
return clk_prepare_enable(spi->clk);
}
#endif
static const struct dev_pm_ops orion_spi_pm_ops = {
SET_RUNTIME_PM_OPS(orion_spi_runtime_suspend,
orion_spi_runtime_resume,
NULL)
};
static const struct of_device_id orion_spi_of_match_table[] = { static const struct of_device_id orion_spi_of_match_table[] = {
{ .compatible = "marvell,orion-spi", }, { .compatible = "marvell,orion-spi", },
{} {}
...@@ -438,6 +479,7 @@ static struct platform_driver orion_spi_driver = { ...@@ -438,6 +479,7 @@ static struct platform_driver orion_spi_driver = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &orion_spi_pm_ops,
.of_match_table = of_match_ptr(orion_spi_of_match_table), .of_match_table = of_match_ptr(orion_spi_of_match_table),
}, },
.probe = orion_spi_probe, .probe = orion_spi_probe,
......
...@@ -1417,7 +1417,7 @@ static void do_interrupt_dma_transfer(struct pl022 *pl022) ...@@ -1417,7 +1417,7 @@ static void do_interrupt_dma_transfer(struct pl022 *pl022)
* Default is to enable all interrupts except RX - * Default is to enable all interrupts except RX -
* this will be enabled once TX is complete * this will be enabled once TX is complete
*/ */
u32 irqflags = ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM; u32 irqflags = (u32)(ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM);
/* Enable target chip, if not already active */ /* Enable target chip, if not already active */
if (!pl022->next_msg_cs_active) if (!pl022->next_msg_cs_active)
......
...@@ -142,6 +142,7 @@ struct spi_qup { ...@@ -142,6 +142,7 @@ struct spi_qup {
int w_size; /* bytes per SPI word */ int w_size; /* bytes per SPI word */
int tx_bytes; int tx_bytes;
int rx_bytes; int rx_bytes;
int qup_v1;
}; };
...@@ -420,7 +421,9 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -420,7 +421,9 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
config |= QUP_CONFIG_SPI_MODE; config |= QUP_CONFIG_SPI_MODE;
writel_relaxed(config, controller->base + QUP_CONFIG); writel_relaxed(config, controller->base + QUP_CONFIG);
writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK); /* only write to OPERATIONAL_MASK when register is present */
if (!controller->qup_v1)
writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
return 0; return 0;
} }
...@@ -486,7 +489,7 @@ static int spi_qup_probe(struct platform_device *pdev) ...@@ -486,7 +489,7 @@ static int spi_qup_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
struct device *dev; struct device *dev;
void __iomem *base; void __iomem *base;
u32 data, max_freq, iomode; u32 max_freq, iomode;
int ret, irq, size; int ret, irq, size;
dev = &pdev->dev; dev = &pdev->dev;
...@@ -529,15 +532,6 @@ static int spi_qup_probe(struct platform_device *pdev) ...@@ -529,15 +532,6 @@ static int spi_qup_probe(struct platform_device *pdev)
return ret; return ret;
} }
data = readl_relaxed(base + QUP_HW_VERSION);
if (data < QUP_HW_VERSION_2_1_1) {
clk_disable_unprepare(cclk);
clk_disable_unprepare(iclk);
dev_err(dev, "v.%08x is not supported\n", data);
return -ENXIO;
}
master = spi_alloc_master(dev, sizeof(struct spi_qup)); master = spi_alloc_master(dev, sizeof(struct spi_qup));
if (!master) { if (!master) {
clk_disable_unprepare(cclk); clk_disable_unprepare(cclk);
...@@ -570,6 +564,10 @@ static int spi_qup_probe(struct platform_device *pdev) ...@@ -570,6 +564,10 @@ static int spi_qup_probe(struct platform_device *pdev)
controller->cclk = cclk; controller->cclk = cclk;
controller->irq = irq; controller->irq = irq;
/* set v1 flag if device is version 1 */
if (of_device_is_compatible(dev->of_node, "qcom,spi-qup-v1.1.1"))
controller->qup_v1 = 1;
spin_lock_init(&controller->lock); spin_lock_init(&controller->lock);
init_completion(&controller->done); init_completion(&controller->done);
...@@ -593,8 +591,8 @@ static int spi_qup_probe(struct platform_device *pdev) ...@@ -593,8 +591,8 @@ static int spi_qup_probe(struct platform_device *pdev)
size = QUP_IO_M_INPUT_FIFO_SIZE(iomode); size = QUP_IO_M_INPUT_FIFO_SIZE(iomode);
controller->in_fifo_sz = controller->in_blk_sz * (2 << size); controller->in_fifo_sz = controller->in_blk_sz * (2 << size);
dev_info(dev, "v.%08x IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", dev_info(dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
data, controller->in_blk_sz, controller->in_fifo_sz, controller->in_blk_sz, controller->in_fifo_sz,
controller->out_blk_sz, controller->out_fifo_sz); controller->out_blk_sz, controller->out_fifo_sz);
writel_relaxed(1, base + QUP_SW_RESET); writel_relaxed(1, base + QUP_SW_RESET);
...@@ -607,10 +605,19 @@ static int spi_qup_probe(struct platform_device *pdev) ...@@ -607,10 +605,19 @@ static int spi_qup_probe(struct platform_device *pdev)
writel_relaxed(0, base + QUP_OPERATIONAL); writel_relaxed(0, base + QUP_OPERATIONAL);
writel_relaxed(0, base + QUP_IO_M_MODES); writel_relaxed(0, base + QUP_IO_M_MODES);
writel_relaxed(0, base + QUP_OPERATIONAL_MASK);
if (!controller->qup_v1)
writel_relaxed(0, base + QUP_OPERATIONAL_MASK);
writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN, writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN,
base + SPI_ERROR_FLAGS_EN); base + SPI_ERROR_FLAGS_EN);
/* if earlier version of the QUP, disable INPUT_OVERRUN */
if (controller->qup_v1)
writel_relaxed(QUP_ERROR_OUTPUT_OVER_RUN |
QUP_ERROR_INPUT_UNDER_RUN | QUP_ERROR_OUTPUT_UNDER_RUN,
base + QUP_ERROR_FLAGS_EN);
writel_relaxed(0, base + SPI_CONFIG); writel_relaxed(0, base + SPI_CONFIG);
writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL); writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL);
...@@ -732,6 +739,7 @@ static int spi_qup_remove(struct platform_device *pdev) ...@@ -732,6 +739,7 @@ static int spi_qup_remove(struct platform_device *pdev)
} }
static const struct of_device_id spi_qup_dt_match[] = { static const struct of_device_id spi_qup_dt_match[] = {
{ .compatible = "qcom,spi-qup-v1.1.1", },
{ .compatible = "qcom,spi-qup-v2.1.1", }, { .compatible = "qcom,spi-qup-v2.1.1", },
{ .compatible = "qcom,spi-qup-v2.2.1", }, { .compatible = "qcom,spi-qup-v2.2.1", },
{ } { }
......
This diff is collapsed.
...@@ -477,7 +477,7 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, ...@@ -477,7 +477,7 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
tx->sgl, tx->nents, DMA_TO_DEVICE, tx->sgl, tx->nents, DMA_TO_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_tx) if (!desc_tx)
return -EIO; goto no_dma;
irq_mask |= SPCR_SPTIE; irq_mask |= SPCR_SPTIE;
} }
...@@ -486,7 +486,7 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, ...@@ -486,7 +486,7 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
rx->sgl, rx->nents, DMA_FROM_DEVICE, rx->sgl, rx->nents, DMA_FROM_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_rx) if (!desc_rx)
return -EIO; goto no_dma;
irq_mask |= SPCR_SPRIE; irq_mask |= SPCR_SPRIE;
} }
...@@ -540,6 +540,12 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, ...@@ -540,6 +540,12 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
enable_irq(rspi->rx_irq); enable_irq(rspi->rx_irq);
return ret; return ret;
no_dma:
pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
dev_driver_string(&rspi->master->dev),
dev_name(&rspi->master->dev));
return -EAGAIN;
} }
static void rspi_receive_init(const struct rspi_data *rspi) static void rspi_receive_init(const struct rspi_data *rspi)
...@@ -593,8 +599,10 @@ static int rspi_common_transfer(struct rspi_data *rspi, ...@@ -593,8 +599,10 @@ static int rspi_common_transfer(struct rspi_data *rspi,
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
/* rx_buf can be NULL on RSPI on SH in TX-only Mode */ /* rx_buf can be NULL on RSPI on SH in TX-only Mode */
return rspi_dma_transfer(rspi, &xfer->tx_sg, ret = rspi_dma_transfer(rspi, &xfer->tx_sg,
xfer->rx_buf ? &xfer->rx_sg : NULL); xfer->rx_buf ? &xfer->rx_sg : NULL);
if (ret != -EAGAIN)
return ret;
} }
ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
...@@ -630,7 +638,6 @@ static int rspi_rz_transfer_one(struct spi_master *master, ...@@ -630,7 +638,6 @@ static int rspi_rz_transfer_one(struct spi_master *master,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
struct rspi_data *rspi = spi_master_get_devdata(master); struct rspi_data *rspi = spi_master_get_devdata(master);
int ret;
rspi_rz_receive_init(rspi); rspi_rz_receive_init(rspi);
...@@ -649,8 +656,11 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) ...@@ -649,8 +656,11 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
{ {
int ret; int ret;
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
return rspi_dma_transfer(rspi, &xfer->tx_sg, NULL); ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
if (ret != -EAGAIN)
return ret;
}
ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len); ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len);
if (ret < 0) if (ret < 0)
...@@ -664,8 +674,11 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) ...@@ -664,8 +674,11 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
{ {
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
return rspi_dma_transfer(rspi, NULL, &xfer->rx_sg); int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
if (ret != -EAGAIN)
return ret;
}
return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len); return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len);
} }
...@@ -927,19 +940,19 @@ static int rspi_request_dma(struct device *dev, struct spi_master *master, ...@@ -927,19 +940,19 @@ static int rspi_request_dma(struct device *dev, struct spi_master *master,
return 0; return 0;
} }
static void rspi_release_dma(struct rspi_data *rspi) static void rspi_release_dma(struct spi_master *master)
{ {
if (rspi->master->dma_tx) if (master->dma_tx)
dma_release_channel(rspi->master->dma_tx); dma_release_channel(master->dma_tx);
if (rspi->master->dma_rx) if (master->dma_rx)
dma_release_channel(rspi->master->dma_rx); dma_release_channel(master->dma_rx);
} }
static int rspi_remove(struct platform_device *pdev) static int rspi_remove(struct platform_device *pdev)
{ {
struct rspi_data *rspi = platform_get_drvdata(pdev); struct rspi_data *rspi = platform_get_drvdata(pdev);
rspi_release_dma(rspi); rspi_release_dma(rspi->master);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return 0; return 0;
...@@ -1141,7 +1154,7 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1141,7 +1154,7 @@ static int rspi_probe(struct platform_device *pdev)
return 0; return 0;
error3: error3:
rspi_release_dma(rspi); rspi_release_dma(master);
error2: error2:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
error1: error1:
......
...@@ -197,7 +197,6 @@ struct s3c64xx_spi_driver_data { ...@@ -197,7 +197,6 @@ struct s3c64xx_spi_driver_data {
struct s3c64xx_spi_dma_data tx_dma; struct s3c64xx_spi_dma_data tx_dma;
struct s3c64xx_spi_port_config *port_conf; struct s3c64xx_spi_port_config *port_conf;
unsigned int port_id; unsigned int port_id;
bool cs_gpio;
}; };
static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
...@@ -754,10 +753,8 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( ...@@ -754,10 +753,8 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
{ {
struct s3c64xx_spi_csinfo *cs; struct s3c64xx_spi_csinfo *cs;
struct device_node *slave_np, *data_np = NULL; struct device_node *slave_np, *data_np = NULL;
struct s3c64xx_spi_driver_data *sdd;
u32 fb_delay = 0; u32 fb_delay = 0;
sdd = spi_master_get_devdata(spi->master);
slave_np = spi->dev.of_node; slave_np = spi->dev.of_node;
if (!slave_np) { if (!slave_np) {
dev_err(&spi->dev, "device node not found\n"); dev_err(&spi->dev, "device node not found\n");
...@@ -776,17 +773,6 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( ...@@ -776,17 +773,6 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
/* The CS line is asserted/deasserted by the gpio pin */
if (sdd->cs_gpio)
cs->line = of_get_named_gpio(data_np, "cs-gpio", 0);
if (!gpio_is_valid(cs->line)) {
dev_err(&spi->dev, "chip select gpio is not specified or invalid\n");
kfree(cs);
of_node_put(data_np);
return ERR_PTR(-EINVAL);
}
of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay); of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay);
cs->fb_delay = fb_delay; cs->fb_delay = fb_delay;
of_node_put(data_np); of_node_put(data_np);
...@@ -807,9 +793,16 @@ static int s3c64xx_spi_setup(struct spi_device *spi) ...@@ -807,9 +793,16 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
int err; int err;
sdd = spi_master_get_devdata(spi->master); sdd = spi_master_get_devdata(spi->master);
if (!cs && spi->dev.of_node) { if (spi->dev.of_node) {
cs = s3c64xx_get_slave_ctrldata(spi); cs = s3c64xx_get_slave_ctrldata(spi);
spi->controller_data = cs; spi->controller_data = cs;
} else if (cs) {
/* On non-DT platforms the SPI core will set spi->cs_gpio
* to -ENOENT. The GPIO pin used to drive the chip select
* is defined by using platform data so spi->cs_gpio value
* has to be override to have the proper GPIO pin number.
*/
spi->cs_gpio = cs->line;
} }
if (IS_ERR_OR_NULL(cs)) { if (IS_ERR_OR_NULL(cs)) {
...@@ -818,18 +811,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi) ...@@ -818,18 +811,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
} }
if (!spi_get_ctldata(spi)) { if (!spi_get_ctldata(spi)) {
/* Request gpio only if cs line is asserted by gpio pins */ if (gpio_is_valid(spi->cs_gpio)) {
if (sdd->cs_gpio) { err = gpio_request_one(spi->cs_gpio, GPIOF_OUT_INIT_HIGH,
err = gpio_request_one(cs->line, GPIOF_OUT_INIT_HIGH, dev_name(&spi->dev));
dev_name(&spi->dev));
if (err) { if (err) {
dev_err(&spi->dev, dev_err(&spi->dev,
"Failed to get /CS gpio [%d]: %d\n", "Failed to get /CS gpio [%d]: %d\n",
cs->line, err); spi->cs_gpio, err);
goto err_gpio_req; goto err_gpio_req;
} }
spi->cs_gpio = cs->line;
} }
spi_set_ctldata(spi, cs); spi_set_ctldata(spi, cs);
...@@ -884,7 +874,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi) ...@@ -884,7 +874,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
/* setup() returns with device de-selected */ /* setup() returns with device de-selected */
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
gpio_free(cs->line); if (gpio_is_valid(spi->cs_gpio))
gpio_free(spi->cs_gpio);
spi_set_ctldata(spi, NULL); spi_set_ctldata(spi, NULL);
err_gpio_req: err_gpio_req:
...@@ -897,14 +888,21 @@ static int s3c64xx_spi_setup(struct spi_device *spi) ...@@ -897,14 +888,21 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
static void s3c64xx_spi_cleanup(struct spi_device *spi) static void s3c64xx_spi_cleanup(struct spi_device *spi)
{ {
struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi); struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi);
struct s3c64xx_spi_driver_data *sdd;
sdd = spi_master_get_devdata(spi->master); if (gpio_is_valid(spi->cs_gpio)) {
if (spi->cs_gpio) {
gpio_free(spi->cs_gpio); gpio_free(spi->cs_gpio);
if (spi->dev.of_node) if (spi->dev.of_node)
kfree(cs); kfree(cs);
else {
/* On non-DT platforms, the SPI core sets
* spi->cs_gpio to -ENOENT and .setup()
* overrides it with the GPIO pin value
* passed using platform data.
*/
spi->cs_gpio = -ENOENT;
}
} }
spi_set_ctldata(spi, NULL); spi_set_ctldata(spi, NULL);
} }
...@@ -1075,11 +1073,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1075,11 +1073,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
sdd->cntrlr_info = sci; sdd->cntrlr_info = sci;
sdd->pdev = pdev; sdd->pdev = pdev;
sdd->sfr_start = mem_res->start; sdd->sfr_start = mem_res->start;
sdd->cs_gpio = true;
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
if (!of_find_property(pdev->dev.of_node, "cs-gpio", NULL))
sdd->cs_gpio = false;
ret = of_alias_get_id(pdev->dev.of_node, "spi"); ret = of_alias_get_id(pdev->dev.of_node, "spi");
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to get alias id, errno %d\n", dev_err(&pdev->dev, "failed to get alias id, errno %d\n",
......
...@@ -304,7 +304,7 @@ static int hspi_remove(struct platform_device *pdev) ...@@ -304,7 +304,7 @@ static int hspi_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct of_device_id hspi_of_match[] = { static const struct of_device_id hspi_of_match[] = {
{ .compatible = "renesas,hspi", }, { .compatible = "renesas,hspi", },
{ /* sentinel */ } { /* sentinel */ }
}; };
......
This diff is collapsed.
...@@ -432,7 +432,6 @@ static int spi_sh_remove(struct platform_device *pdev) ...@@ -432,7 +432,6 @@ static int spi_sh_remove(struct platform_device *pdev)
spi_unregister_master(ss->master); spi_unregister_master(ss->master);
destroy_workqueue(ss->workqueue); destroy_workqueue(ss->workqueue);
free_irq(ss->irq, ss); free_irq(ss->irq, ss);
iounmap(ss->addr);
return 0; return 0;
} }
...@@ -480,7 +479,7 @@ static int spi_sh_probe(struct platform_device *pdev) ...@@ -480,7 +479,7 @@ static int spi_sh_probe(struct platform_device *pdev)
} }
ss->irq = irq; ss->irq = irq;
ss->master = master; ss->master = master;
ss->addr = ioremap(res->start, resource_size(res)); ss->addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (ss->addr == NULL) { if (ss->addr == NULL) {
dev_err(&pdev->dev, "ioremap error.\n"); dev_err(&pdev->dev, "ioremap error.\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -495,13 +494,13 @@ static int spi_sh_probe(struct platform_device *pdev) ...@@ -495,13 +494,13 @@ static int spi_sh_probe(struct platform_device *pdev)
if (ss->workqueue == NULL) { if (ss->workqueue == NULL) {
dev_err(&pdev->dev, "create workqueue error\n"); dev_err(&pdev->dev, "create workqueue error\n");
ret = -EBUSY; ret = -EBUSY;
goto error2; goto error1;
} }
ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss); ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "request_irq error\n"); dev_err(&pdev->dev, "request_irq error\n");
goto error3; goto error2;
} }
master->num_chipselect = 2; master->num_chipselect = 2;
...@@ -513,17 +512,15 @@ static int spi_sh_probe(struct platform_device *pdev) ...@@ -513,17 +512,15 @@ static int spi_sh_probe(struct platform_device *pdev)
ret = spi_register_master(master); ret = spi_register_master(master);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "spi_register_master error.\n"); printk(KERN_ERR "spi_register_master error.\n");
goto error4; goto error3;
} }
return 0; return 0;
error4:
free_irq(irq, ss);
error3: error3:
destroy_workqueue(ss->workqueue); free_irq(irq, ss);
error2: error2:
iounmap(ss->addr); destroy_workqueue(ss->workqueue);
error1: error1:
spi_master_put(master); spi_master_put(master);
......
...@@ -874,8 +874,8 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw) ...@@ -874,8 +874,8 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
/* Get DMA's dev information */ /* Get DMA's dev information */
dma_dev = pci_get_bus_and_slot(data->board_dat->pdev->bus->number, dma_dev = pci_get_slot(data->board_dat->pdev->bus,
PCI_DEVFN(12, 0)); PCI_DEVFN(PCI_SLOT(data->board_dat->pdev->devfn), 0));
/* Set Tx DMA */ /* Set Tx DMA */
param = &dma->param_tx; param = &dma->param_tx;
...@@ -1047,8 +1047,8 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) ...@@ -1047,8 +1047,8 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
num, DMA_DEV_TO_MEM, num, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_rx) { if (!desc_rx) {
dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n", dev_err(&data->master->dev,
__func__); "%s:dmaengine_prep_slave_sg Failed\n", __func__);
return; return;
} }
dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_FROM_DEVICE); dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_FROM_DEVICE);
...@@ -1106,8 +1106,8 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) ...@@ -1106,8 +1106,8 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
sg, num, DMA_MEM_TO_DEV, sg, num, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_tx) { if (!desc_tx) {
dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n", dev_err(&data->master->dev,
__func__); "%s:dmaengine_prep_slave_sg Failed\n", __func__);
return; return;
} }
dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_TO_DEVICE); dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_TO_DEVICE);
......
...@@ -369,7 +369,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) ...@@ -369,7 +369,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
goto put_master; goto put_master;
} }
master->bus_num = pdev->dev.id; master->bus_num = pdev->id;
master->num_chipselect = num_cs; master->num_chipselect = num_cs;
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
......
...@@ -350,14 +350,12 @@ static DEFINE_MUTEX(board_lock); ...@@ -350,14 +350,12 @@ static DEFINE_MUTEX(board_lock);
struct spi_device *spi_alloc_device(struct spi_master *master) struct spi_device *spi_alloc_device(struct spi_master *master)
{ {
struct spi_device *spi; struct spi_device *spi;
struct device *dev = master->dev.parent;
if (!spi_master_get(master)) if (!spi_master_get(master))
return NULL; return NULL;
spi = kzalloc(sizeof(*spi), GFP_KERNEL); spi = kzalloc(sizeof(*spi), GFP_KERNEL);
if (!spi) { if (!spi) {
dev_err(dev, "cannot alloc spi_device\n");
spi_master_put(master); spi_master_put(master);
return NULL; return NULL;
} }
...@@ -624,6 +622,8 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, ...@@ -624,6 +622,8 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
} }
ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir); ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
if (!ret)
ret = -ENOMEM;
if (ret < 0) { if (ret < 0) {
sg_free_table(sgt); sg_free_table(sgt);
return ret; return ret;
...@@ -652,8 +652,8 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg) ...@@ -652,8 +652,8 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
if (!master->can_dma) if (!master->can_dma)
return 0; return 0;
tx_dev = &master->dma_tx->dev->device; tx_dev = master->dma_tx->device->dev;
rx_dev = &master->dma_rx->dev->device; rx_dev = master->dma_rx->device->dev;
list_for_each_entry(xfer, &msg->transfers, transfer_list) { list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer)) if (!master->can_dma(master, msg->spi, xfer))
...@@ -692,8 +692,8 @@ static int spi_unmap_msg(struct spi_master *master, struct spi_message *msg) ...@@ -692,8 +692,8 @@ static int spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
if (!master->cur_msg_mapped || !master->can_dma) if (!master->cur_msg_mapped || !master->can_dma)
return 0; return 0;
tx_dev = &master->dma_tx->dev->device; tx_dev = master->dma_tx->device->dev;
rx_dev = &master->dma_rx->dev->device; rx_dev = master->dma_rx->device->dev;
list_for_each_entry(xfer, &msg->transfers, transfer_list) { list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer)) if (!master->can_dma(master, msg->spi, xfer))
......
...@@ -5,6 +5,8 @@ struct sh_msiof_spi_info { ...@@ -5,6 +5,8 @@ struct sh_msiof_spi_info {
int tx_fifo_override; int tx_fifo_override;
int rx_fifo_override; int rx_fifo_override;
u16 num_chipselect; u16 num_chipselect;
unsigned int dma_tx_id;
unsigned int dma_rx_id;
}; };
#endif /* __SPI_SH_MSIOF_H__ */ #endif /* __SPI_SH_MSIOF_H__ */
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