Commit 61f3d0a9 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi updates from Mark Brown:
 "A fairly quiet release for SPI, mainly driver work.  A few highlights:

   - Supports bits per word compatibility checking in the core.
   - Allow use of the IP used in Freescale SPI controllers outside
     Freescale SoCs.
   - DMA support for the Atmel SPI driver.
   - New drivers for the BCM2835 and Tegra114"

* tag 'spi-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (68 commits)
  spi-topcliff-pch: fix to use list_for_each_entry_safe() when delete list items
  spi-topcliff-pch: missing platform_driver_unregister() on error in pch_spi_init()
  ARM: dts: add pinctrl property for spi node for atmel SoC
  ARM: dts: add spi nodes for the atmel boards
  ARM: dts: add spi nodes for atmel SoC
  ARM: at91: add clocks for spi dt entries
  spi/spi-atmel: add dmaengine support
  spi/spi-atmel: add flag to controller data for lock operations
  spi/spi-atmel: add physical base address
  spi/sirf: fix MODULE_DEVICE_TABLE
  MAINTAINERS: Add git repository and update my address
  spi/s3c64xx: Check for errors in dmaengine prepare_transfer()
  spi/s3c64xx: Fix non-dmaengine usage
  spi: omap2-mcspi: fix error return code in omap2_mcspi_probe()
  spi/s3c64xx: let device core setup the default pin configuration
  MAINTAINERS: Update Grant's email address and maintainership
  spi: omap2-mcspi: Fix transfers if DMADEVICES is not set
  spi: s3c64xx: move to generic dmaengine API
  spi-gpio: init CS before spi_bitbang_setup()
  spi: spi-mpc512x-psc: let transmiter/receiver enabled when in xfer loop
  ...
parents 8ded8d4e cd8d984f
Broadcom BCM2835 SPI0 controller
The BCM2835 contains two forms of SPI master controller, one known simply as
SPI0, and the other known as the "Universal SPI Master"; part of the
auxilliary block. This binding applies to the SPI0 controller.
Required properties:
- compatible: Should be "brcm,bcm2835-spi".
- reg: Should contain register location and length.
- interrupts: Should contain interrupt.
- clocks: The clock feeding the SPI controller.
Example:
spi@20204000 {
compatible = "brcm,bcm2835-spi";
reg = <0x7e204000 0x1000>;
interrupts = <2 22>;
clocks = <&clk_spi>;
#address-cells = <1>;
#size-cells = <0>;
};
......@@ -4,7 +4,7 @@ Required properties:
- cell-index : QE SPI subblock index.
0: QE subblock SPI1
1: QE subblock SPI2
- compatible : should be "fsl,spi".
- compatible : should be "fsl,spi" or "aeroflexgaisler,spictrl".
- mode : the SPI operation mode, it can be "cpu" or "cpu-qe".
- reg : Offset and length of the register set for the device
- interrupts : <a b> where a is the interrupt number and b is a
......@@ -14,6 +14,7 @@ Required properties:
controller you have.
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.
- clock-frequency : input clock frequency to non FSL_SOC cores
Optional properties:
- gpios : specifies the gpio pins to be used for chipselects.
......
NVIDIA Tegra114 SPI controller.
Required properties:
- compatible : should be "nvidia,tegra114-spi".
- reg: Should contain SPI registers location and length.
- interrupts: Should contain SPI interrupts.
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
request selector for this SPI controller.
- This is also require clock named "spi" as per binding document
Documentation/devicetree/bindings/clock/clock-bindings.txt
Recommended properties:
- spi-max-frequency: Definition as per
Documentation/devicetree/bindings/spi/spi-bus.txt
Example:
spi@7000d600 {
compatible = "nvidia,tegra114-spi";
reg = <0x7000d600 0x200>;
interrupts = <0 82 0x04>;
nvidia,dma-request-selector = <&apbdma 16>;
spi-max-frequency = <25000000>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
......@@ -31,9 +31,6 @@ Required Board Specific Properties:
- #address-cells: should be 1.
- #size-cells: should be 0.
- gpios: The gpio specifier for clock, mosi and miso interface lines (in the
order specified). The format of the gpio specifier depends on the gpio
controller.
Optional Board Specific Properties:
......@@ -86,9 +83,8 @@ Example:
spi_0: spi@12d20000 {
#address-cells = <1>;
#size-cells = <0>;
gpios = <&gpa2 4 2 3 0>,
<&gpa2 6 2 3 0>,
<&gpa2 7 2 3 0>;
pinctrl-names = "default";
pinctrl-0 = <&spi0_bus>;
w25q80bw@0 {
#address-cells = <1>;
......
......@@ -5,6 +5,7 @@ using them to avoid name-space collisions.
ad Avionic Design GmbH
adi Analog Devices, Inc.
aeroflexgaisler Aeroflex Gaisler AB
ak Asahi Kasei Corp.
amcc Applied Micro Circuits Corporation (APM, formally AMCC)
apm Applied Micro Circuits Corporation (APM)
......
......@@ -3515,7 +3515,7 @@ F: drivers/isdn/gigaset/
F: include/uapi/linux/gigaset_dev.h
GPIO SUBSYSTEM
M: Grant Likely <grant.likely@secretlab.ca>
M: Grant Likely <grant.likely@linaro.org>
M: Linus Walleij <linus.walleij@linaro.org>
S: Maintained
T: git git://git.secretlab.ca/git/linux-2.6.git
......@@ -4348,7 +4348,7 @@ F: drivers/irqchip/
IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
M: Grant Likely <grant.likely@secretlab.ca>
M: Grant Likely <grant.likely@linaro.org>
T: git git://git.secretlab.ca/git/linux-2.6.git irqdomain/next
S: Maintained
F: Documentation/IRQ-domain.txt
......@@ -4835,11 +4835,8 @@ F: arch/powerpc/platforms/40x/
F: arch/powerpc/platforms/44x/
LINUX FOR POWERPC EMBEDDED XILINX VIRTEX
M: Grant Likely <grant.likely@secretlab.ca>
W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex
L: linuxppc-dev@lists.ozlabs.org
T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
S: Unmaintained
F: arch/powerpc/*/*virtex*
F: arch/powerpc/*/*/*virtex*
......@@ -5857,7 +5854,7 @@ F: Documentation/i2c/busses/i2c-ocores
F: drivers/i2c/busses/i2c-ocores.c
OPEN FIRMWARE AND FLATTENED DEVICE TREE
M: Grant Likely <grant.likely@secretlab.ca>
M: Grant Likely <grant.likely@linaro.org>
M: Rob Herring <rob.herring@calxeda.com>
L: devicetree-discuss@lists.ozlabs.org (moderated for non-subscribers)
W: http://fdt.secretlab.ca
......@@ -7481,11 +7478,11 @@ S: Maintained
F: drivers/clk/spear/
SPI SUBSYSTEM
M: Grant Likely <grant.likely@secretlab.ca>
M: Mark Brown <broonie@kernel.org>
M: Grant Likely <grant.likely@linaro.org>
L: spi-devel-general@lists.sourceforge.net
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
Q: http://patchwork.kernel.org/project/spi-devel-general/list/
T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
F: Documentation/spi/
F: drivers/spi/
......@@ -8996,9 +8993,7 @@ S: Maintained
F: drivers/net/ethernet/xilinx/xilinx_axienet*
XILINX SYSTEMACE DRIVER
M: Grant Likely <grant.likely@secretlab.ca>
W: http://www.secretlab.ca/
S: Maintained
S: Unmaintained
F: drivers/block/xsysace.c
XILINX UARTLITE SERIAL DRIVER
......
......@@ -322,6 +322,24 @@ pinctrl_ssc0_rx: ssc0_rx-0 {
};
};
spi0 {
pinctrl_spi0: spi0-0 {
atmel,pins =
<0 0 0x1 0x0 /* PA0 periph A SPI0_MISO pin */
0 1 0x1 0x0 /* PA1 periph A SPI0_MOSI pin */
0 2 0x1 0x0>; /* PA2 periph A SPI0_SPCK pin */
};
};
spi1 {
pinctrl_spi1: spi1-0 {
atmel,pins =
<1 0 0x1 0x0 /* PB0 periph A SPI1_MISO pin */
1 1 0x1 0x0 /* PB1 periph A SPI1_MOSI pin */
1 2 0x1 0x0>; /* PB2 periph A SPI1_SPCK pin */
};
};
pioA: gpio@fffff400 {
compatible = "atmel,at91rm9200-gpio";
reg = <0xfffff400 0x200>;
......@@ -471,6 +489,28 @@ ssc0: ssc@fffbc000 {
status = "disabled";
};
spi0: spi@fffc8000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xfffc8000 0x200>;
interrupts = <12 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
status = "disabled";
};
spi1: spi@fffcc000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xfffcc000 0x200>;
interrupts = <13 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi1>;
status = "disabled";
};
adc0: adc@fffe0000 {
compatible = "atmel,at91sam9260-adc";
reg = <0xfffe0000 0x100>;
......
......@@ -303,6 +303,24 @@ pinctrl_ssc1_rx: ssc1_rx-0 {
};
};
spi0 {
pinctrl_spi0: spi0-0 {
atmel,pins =
<0 0 0x2 0x0 /* PA0 periph B SPI0_MISO pin */
0 1 0x2 0x0 /* PA1 periph B SPI0_MOSI pin */
0 2 0x2 0x0>; /* PA2 periph B SPI0_SPCK pin */
};
};
spi1 {
pinctrl_spi1: spi1-0 {
atmel,pins =
<1 12 0x1 0x0 /* PB12 periph A SPI1_MISO pin */
1 13 0x1 0x0 /* PB13 periph A SPI1_MOSI pin */
1 14 0x1 0x0>; /* PB14 periph A SPI1_SPCK pin */
};
};
pioA: gpio@fffff200 {
compatible = "atmel,at91rm9200-gpio";
reg = <0xfffff200 0x200>;
......@@ -462,6 +480,28 @@ watchdog@fffffd40 {
reg = <0xfffffd40 0x10>;
status = "disabled";
};
spi0: spi@fffa4000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xfffa4000 0x200>;
interrupts = <14 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
status = "disabled";
};
spi1: spi@fffa8000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xfffa8000 0x200>;
interrupts = <15 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi1>;
status = "disabled";
};
};
nand0: nand@40000000 {
......
......@@ -79,6 +79,16 @@ pinctrl_board_mmc0: mmc0-board {
};
};
};
spi0: spi@fffa4000 {
status = "okay";
cs-gpios = <&pioA 5 0>, <0>, <0>, <0>;
mtd_dataflash@0 {
compatible = "atmel,at45", "atmel,dataflash";
spi-max-frequency = <50000000>;
reg = <0>;
};
};
};
nand0: nand@40000000 {
......
......@@ -96,6 +96,16 @@ ssc0: ssc@fffbc000 {
status = "okay";
pinctrl-0 = <&pinctrl_ssc0_tx>;
};
spi0: spi@fffc8000 {
status = "okay";
cs-gpios = <0>, <&pioC 11 0>, <0>, <0>;
mtd_dataflash@0 {
compatible = "atmel,at45", "atmel,dataflash";
spi-max-frequency = <50000000>;
reg = <1>;
};
};
};
nand0: nand@40000000 {
......
......@@ -322,6 +322,24 @@ pinctrl_ssc1_rx: ssc1_rx-0 {
};
};
spi0 {
pinctrl_spi0: spi0-0 {
atmel,pins =
<1 0 0x1 0x0 /* PB0 periph A SPI0_MISO pin */
1 1 0x1 0x0 /* PB1 periph A SPI0_MOSI pin */
1 2 0x1 0x0>; /* PB2 periph A SPI0_SPCK pin */
};
};
spi1 {
pinctrl_spi1: spi1-0 {
atmel,pins =
<1 14 0x1 0x0 /* PB14 periph A SPI1_MISO pin */
1 15 0x1 0x0 /* PB15 periph A SPI1_MOSI pin */
1 16 0x1 0x0>; /* PB16 periph A SPI1_SPCK pin */
};
};
pioA: gpio@fffff200 {
compatible = "atmel,at91rm9200-gpio";
reg = <0xfffff200 0x200>;
......@@ -531,6 +549,28 @@ watchdog@fffffd40 {
reg = <0xfffffd40 0x10>;
status = "disabled";
};
spi0: spi@fffa4000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xfffa4000 0x200>;
interrupts = <14 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
status = "disabled";
};
spi1: spi@fffa8000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xfffa8000 0x200>;
interrupts = <15 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi1>;
status = "disabled";
};
};
nand0: nand@40000000 {
......
......@@ -102,6 +102,16 @@ pinctrl_board_mmc1: mmc1-board {
};
};
};
spi0: spi@fffa4000{
status = "okay";
cs-gpios = <&pioB 3 0>, <0>, <0>, <0>;
mtd_dataflash@0 {
compatible = "atmel,at45", "atmel,dataflash";
spi-max-frequency = <13000000>;
reg = <0>;
};
};
};
nand0: nand@40000000 {
......
......@@ -261,6 +261,24 @@ pinctrl_ssc0_rx: ssc0_rx-0 {
};
};
spi0 {
pinctrl_spi0: spi0-0 {
atmel,pins =
<0 11 0x1 0x0 /* PA11 periph A SPI0_MISO pin */
0 12 0x1 0x0 /* PA12 periph A SPI0_MOSI pin */
0 13 0x1 0x0>; /* PA13 periph A SPI0_SPCK pin */
};
};
spi1 {
pinctrl_spi1: spi1-0 {
atmel,pins =
<0 21 0x2 0x0 /* PA21 periph B SPI1_MISO pin */
0 22 0x2 0x0 /* PA22 periph B SPI1_MOSI pin */
0 23 0x2 0x0>; /* PA23 periph B SPI1_SPCK pin */
};
};
pioA: gpio@fffff400 {
compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
reg = <0xfffff400 0x200>;
......@@ -373,6 +391,28 @@ i2c1: i2c@f8014000 {
#size-cells = <0>;
status = "disabled";
};
spi0: spi@f0000000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xf0000000 0x100>;
interrupts = <13 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
status = "disabled";
};
spi1: spi@f0004000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xf0004000 0x100>;
interrupts = <14 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi1>;
status = "disabled";
};
};
nand0: nand@40000000 {
......
......@@ -67,6 +67,16 @@ pinctrl_board_mmc0: mmc0-board {
};
};
};
spi0: spi@f0000000 {
status = "okay";
cs-gpios = <&pioA 14 0>, <0>, <0>, <0>;
m25p80@0 {
compatible = "atmel,at25df321a";
spi-max-frequency = <50000000>;
reg = <0>;
};
};
};
nand0: nand@40000000 {
......
......@@ -343,6 +343,24 @@ pinctrl_ssc0_rx: ssc0_rx-0 {
};
};
spi0 {
pinctrl_spi0: spi0-0 {
atmel,pins =
<0 11 0x1 0x0 /* PA11 periph A SPI0_MISO pin */
0 12 0x1 0x0 /* PA12 periph A SPI0_MOSI pin */
0 13 0x1 0x0>; /* PA13 periph A SPI0_SPCK pin */
};
};
spi1 {
pinctrl_spi1: spi1-0 {
atmel,pins =
<0 21 0x2 0x0 /* PA21 periph B SPI1_MISO pin */
0 22 0x2 0x0 /* PA22 periph B SPI1_MOSI pin */
0 23 0x2 0x0>; /* PA23 periph B SPI1_SPCK pin */
};
};
pioA: gpio@fffff400 {
compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
reg = <0xfffff400 0x200>;
......@@ -529,6 +547,28 @@ trigger@3 {
trigger-value = <0x6>;
};
};
spi0: spi@f0000000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xf0000000 0x100>;
interrupts = <13 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
status = "disabled";
};
spi1: spi@f0004000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "atmel,at91rm9200-spi";
reg = <0xf0004000 0x100>;
interrupts = <14 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi1>;
status = "disabled";
};
};
nand0: nand@40000000 {
......
......@@ -84,6 +84,16 @@ pinctrl_board_mmc1: mmc1-board {
};
};
};
spi0: spi@f0000000 {
status = "okay";
cs-gpios = <&pioA 14 0>, <0>, <0>, <0>;
m25p80@0 {
compatible = "atmel,at25df321a";
spi-max-frequency = <50000000>;
reg = <0>;
};
};
};
usb0: ohci@00600000 {
......
......@@ -232,6 +232,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk),
CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk),
CLKDEV_CON_DEV_ID("mci_clk", "fffa8000.mmc", &mmc_clk),
CLKDEV_CON_DEV_ID("spi_clk", "fffc8000.spi", &spi0_clk),
CLKDEV_CON_DEV_ID("spi_clk", "fffcc000.spi", &spi1_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
......
......@@ -262,6 +262,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("mci_clk", "fffd0000.mmc", &mmc1_clk),
CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
......
......@@ -172,6 +172,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
CLKDEV_CON_DEV_ID("spi_clk", "f0000000.spi", &spi0_clk),
CLKDEV_CON_DEV_ID("spi_clk", "f0004000.spi", &spi1_clk),
CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
......
......@@ -237,6 +237,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
CLKDEV_CON_DEV_ID("spi_clk", "f0000000.spi", &spi0_clk),
CLKDEV_CON_DEV_ID("spi_clk", "f0004000.spi", &spi1_clk),
CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
......
......@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*/
#include <linux/amba/pl330.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
......@@ -1552,6 +1553,9 @@ void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
pd.num_cs = num_cs;
pd.src_clk_nr = src_clk_nr;
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
#ifdef CONFIG_PL330_DMA
pd.filter = pl330_filter;
#endif
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi0);
}
......@@ -1590,6 +1594,9 @@ void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
pd.num_cs = num_cs;
pd.src_clk_nr = src_clk_nr;
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
#ifdef CONFIG_PL330_DMA
pd.filter = pl330_filter;
#endif
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
}
......@@ -1628,6 +1635,9 @@ void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
pd.num_cs = num_cs;
pd.src_clk_nr = src_clk_nr;
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
#ifdef CONFIG_PL330_DMA
pd.filter = pl330_filter;
#endif
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
}
......
......@@ -85,20 +85,9 @@ static struct platform_device bcm63xx_spi_device = {
int __init bcm63xx_spi_register(void)
{
struct clk *periph_clk;
if (BCMCPU_IS_6328() || BCMCPU_IS_6345())
return -ENODEV;
periph_clk = clk_get(NULL, "periph");
if (IS_ERR(periph_clk)) {
pr_err("unable to get periph clock\n");
return -ENODEV;
}
/* Set bus frequency */
spi_pdata.speed_hz = clk_get_rate(periph_clk);
spi_resources[0].start = bcm63xx_regset_address(RSET_SPI);
spi_resources[0].end = spi_resources[0].start;
spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
......
......@@ -13,7 +13,6 @@ struct bcm63xx_spi_pdata {
unsigned int msg_ctl_width;
int bus_num;
int num_chipselect;
u32 speed_hz;
};
enum bcm63xx_regs_spi {
......
......@@ -75,6 +75,17 @@ config SPI_ATMEL
This selects a driver for the Atmel SPI Controller, present on
many AT32 (AVR32) and AT91 (ARM) chips.
config SPI_BCM2835
tristate "BCM2835 SPI controller"
depends on ARCH_BCM2835
help
This selects a driver for the Broadcom BCM2835 SPI master.
The BCM2835 contains two types of SPI master controller; the
"universal SPI master", and the regular SPI controller. This driver
is for the regular SPI controller. Slave mode operation is not also
not supported.
config SPI_BFIN5XX
tristate "SPI controller driver for ADI Blackfin5xx"
depends on BLACKFIN
......@@ -218,17 +229,24 @@ config SPI_MPC512x_PSC
Controller in SPI master mode.
config SPI_FSL_LIB
tristate
depends on OF
config SPI_FSL_CPM
tristate
depends on FSL_SOC
config SPI_FSL_SPI
bool "Freescale SPI controller"
depends on FSL_SOC
bool "Freescale SPI controller and Aeroflex Gaisler GRLIB SPI controller"
depends on OF
select SPI_FSL_LIB
select SPI_FSL_CPM if FSL_SOC
help
This enables using the Freescale SPI controllers in master mode.
MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
This also enables using the Aeroflex Gaisler GRLIB SPI controller in
master mode.
config SPI_FSL_ESPI
bool "Freescale eSPI controller"
......@@ -398,6 +416,14 @@ config SPI_MXS
help
SPI driver for Freescale MXS devices.
config SPI_TEGRA114
tristate "NVIDIA Tegra114 SPI Controller"
depends on ARCH_TEGRA && TEGRA20_APB_DMA
help
SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller
is different than the older SoCs SPI controller and also register interface
get changed with this controller.
config SPI_TEGRA20_SFLASH
tristate "Nvidia Tegra20 Serial flash Controller"
depends on ARCH_TEGRA
......
......@@ -14,6 +14,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera.o
obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
......@@ -28,6 +29,7 @@ obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
obj-$(CONFIG_SPI_FALCON) += spi-falcon.o
obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
......@@ -63,6 +65,7 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o
obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o
obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o
obj-$(CONFIG_SPI_TEGRA20_SLINK) += spi-tegra20-slink.o
obj-$(CONFIG_SPI_TI_SSP) += spi-ti-ssp.o
......
This diff is collapsed.
This diff is collapsed.
......@@ -46,7 +46,6 @@ struct bcm63xx_spi {
int irq;
/* Platform data */
u32 speed_hz;
unsigned fifo_size;
unsigned int msg_type_shift;
unsigned int msg_ctl_width;
......@@ -93,40 +92,16 @@ static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
{ 391000, SPI_CLK_0_391MHZ }
};
static int bcm63xx_spi_check_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
u8 bits_per_word;
bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
if (bits_per_word != 8) {
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
__func__, bits_per_word);
return -EINVAL;
}
if (spi->chip_select > spi->master->num_chipselect) {
dev_err(&spi->dev, "%s, unsupported slave %d\n",
__func__, spi->chip_select);
return -EINVAL;
}
return 0;
}
static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
u32 hz;
u8 clk_cfg, reg;
int i;
hz = (t) ? t->speed_hz : spi->max_speed_hz;
/* Find the closest clock configuration */
for (i = 0; i < SPI_CLK_MASK; i++) {
if (hz >= bcm63xx_spi_freq_table[i][0]) {
if (t->speed_hz >= bcm63xx_spi_freq_table[i][0]) {
clk_cfg = bcm63xx_spi_freq_table[i][1];
break;
}
......@@ -143,7 +118,7 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
clk_cfg, hz);
clk_cfg, t->speed_hz);
}
/* the spi->mode bits understood by this driver: */
......@@ -151,22 +126,12 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
static int bcm63xx_spi_setup(struct spi_device *spi)
{
struct bcm63xx_spi *bs;
bs = spi_master_get_devdata(spi->master);
if (!spi->bits_per_word)
spi->bits_per_word = 8;
if (spi->mode & ~MODEBITS) {
dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
__func__, spi->mode & ~MODEBITS);
if (spi->bits_per_word != 8) {
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
__func__, spi->bits_per_word);
return -EINVAL;
}
dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
__func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
return 0;
}
......@@ -312,9 +277,12 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master,
* full-duplex transfers.
*/
list_for_each_entry(t, &m->transfers, transfer_list) {
status = bcm63xx_spi_check_transfer(spi, t);
if (status < 0)
if (t->bits_per_word != 8) {
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
__func__, t->bits_per_word);
status = -EINVAL;
goto exit;
}
if (!first)
first = t;
......@@ -443,18 +411,9 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
bs->pdev = pdev;
if (!devm_request_mem_region(&pdev->dev, r->start,
resource_size(r), PFX)) {
dev_err(dev, "iomem request failed\n");
ret = -ENXIO;
goto out_err;
}
bs->regs = devm_ioremap_nocache(&pdev->dev, r->start,
resource_size(r));
if (!bs->regs) {
dev_err(dev, "unable to ioremap regs\n");
ret = -ENOMEM;
bs->regs = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(bs->regs)) {
ret = PTR_ERR(bs->regs);
goto out_err;
}
......@@ -476,7 +435,6 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
master->transfer_one_message = bcm63xx_spi_transfer_one;
master->mode_bits = MODEBITS;
bs->speed_hz = pdata->speed_hz;
bs->msg_type_shift = pdata->msg_type_shift;
bs->msg_ctl_width = pdata->msg_ctl_width;
bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
......@@ -493,7 +451,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
}
/* Initialize hardware */
clk_enable(bs->clk);
clk_prepare_enable(bs->clk);
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
/* register and we are done */
......@@ -509,7 +467,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
return 0;
out_clk_disable:
clk_disable(clk);
clk_disable_unprepare(clk);
out_err:
platform_set_drvdata(pdev, NULL);
spi_master_put(master);
......@@ -530,7 +488,7 @@ static int bcm63xx_spi_remove(struct platform_device *pdev)
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
/* HW shutdown */
clk_disable(bs->clk);
clk_disable_unprepare(bs->clk);
clk_put(bs->clk);
platform_set_drvdata(pdev, 0);
......@@ -549,7 +507,7 @@ static int bcm63xx_spi_suspend(struct device *dev)
spi_master_suspend(master);
clk_disable(bs->clk);
clk_disable_unprepare(bs->clk);
return 0;
}
......@@ -560,7 +518,7 @@ static int bcm63xx_spi_resume(struct device *dev)
platform_get_drvdata(to_platform_device(dev));
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
clk_enable(bs->clk);
clk_prepare_enable(bs->clk);
spi_master_resume(master);
......
/*
* Freescale SPI controller driver cpm functions.
*
* Maintainer: Kumar Gala
*
* Copyright (C) 2006 Polycom, Inc.
* Copyright 2010 Freescale Semiconductor, Inc.
*
* CPM SPI and QE buffer descriptors mode support:
* Copyright (c) 2009 MontaVista Software, Inc.
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
#include <linux/dma-mapping.h>
#include <asm/cpm.h>
#include <asm/qe.h>
#include "spi-fsl-lib.h"
#include "spi-fsl-cpm.h"
#include "spi-fsl-spi.h"
/* CPM1 and CPM2 are mutually exclusive. */
#ifdef CONFIG_CPM1
#include <asm/cpm1.h>
#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
#else
#include <asm/cpm2.h>
#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
#endif
#define SPIE_TXB 0x00000200 /* Last char is written to tx fifo */
#define SPIE_RXB 0x00000100 /* Last char is written to rx buf */
/* SPCOM register values */
#define SPCOM_STR (1 << 23) /* Start transmit */
#define SPI_PRAM_SIZE 0x100
#define SPI_MRBLR ((unsigned int)PAGE_SIZE)
static void *fsl_dummy_rx;
static DEFINE_MUTEX(fsl_dummy_rx_lock);
static int fsl_dummy_rx_refcnt;
void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi)
{
if (mspi->flags & SPI_QE) {
qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
QE_CR_PROTOCOL_UNSPECIFIED, 0);
} else {
cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
if (mspi->flags & SPI_CPM1) {
out_be16(&mspi->pram->rbptr,
in_be16(&mspi->pram->rbase));
out_be16(&mspi->pram->tbptr,
in_be16(&mspi->pram->tbase));
}
}
}
static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
{
struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
unsigned int xfer_ofs;
struct fsl_spi_reg *reg_base = mspi->reg_base;
xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
if (mspi->rx_dma == mspi->dma_dummy_rx)
out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
else
out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
out_be16(&rx_bd->cbd_datlen, 0);
out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
if (mspi->tx_dma == mspi->dma_dummy_tx)
out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
else
out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
out_be16(&tx_bd->cbd_datlen, xfer_len);
out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
BD_SC_LAST);
/* start transfer */
mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
}
int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
struct spi_transfer *t, bool is_dma_mapped)
{
struct device *dev = mspi->dev;
struct fsl_spi_reg *reg_base = mspi->reg_base;
if (is_dma_mapped) {
mspi->map_tx_dma = 0;
mspi->map_rx_dma = 0;
} else {
mspi->map_tx_dma = 1;
mspi->map_rx_dma = 1;
}
if (!t->tx_buf) {
mspi->tx_dma = mspi->dma_dummy_tx;
mspi->map_tx_dma = 0;
}
if (!t->rx_buf) {
mspi->rx_dma = mspi->dma_dummy_rx;
mspi->map_rx_dma = 0;
}
if (mspi->map_tx_dma) {
void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, mspi->tx_dma)) {
dev_err(dev, "unable to map tx dma\n");
return -ENOMEM;
}
} else if (t->tx_buf) {
mspi->tx_dma = t->tx_dma;
}
if (mspi->map_rx_dma) {
mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
DMA_FROM_DEVICE);
if (dma_mapping_error(dev, mspi->rx_dma)) {
dev_err(dev, "unable to map rx dma\n");
goto err_rx_dma;
}
} else if (t->rx_buf) {
mspi->rx_dma = t->rx_dma;
}
/* enable rx ints */
mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
mspi->xfer_in_progress = t;
mspi->count = t->len;
/* start CPM transfers */
fsl_spi_cpm_bufs_start(mspi);
return 0;
err_rx_dma:
if (mspi->map_tx_dma)
dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
return -ENOMEM;
}
void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
{
struct device *dev = mspi->dev;
struct spi_transfer *t = mspi->xfer_in_progress;
if (mspi->map_tx_dma)
dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
if (mspi->map_rx_dma)
dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
mspi->xfer_in_progress = NULL;
}
void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
{
u16 len;
struct fsl_spi_reg *reg_base = mspi->reg_base;
dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
len = in_be16(&mspi->rx_bd->cbd_datlen);
if (len > mspi->count) {
WARN_ON(1);
len = mspi->count;
}
/* Clear the events */
mpc8xxx_spi_write_reg(&reg_base->event, events);
mspi->count -= len;
if (mspi->count)
fsl_spi_cpm_bufs_start(mspi);
else
complete(&mspi->done);
}
static void *fsl_spi_alloc_dummy_rx(void)
{
mutex_lock(&fsl_dummy_rx_lock);
if (!fsl_dummy_rx)
fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
if (fsl_dummy_rx)
fsl_dummy_rx_refcnt++;
mutex_unlock(&fsl_dummy_rx_lock);
return fsl_dummy_rx;
}
static void fsl_spi_free_dummy_rx(void)
{
mutex_lock(&fsl_dummy_rx_lock);
switch (fsl_dummy_rx_refcnt) {
case 0:
WARN_ON(1);
break;
case 1:
kfree(fsl_dummy_rx);
fsl_dummy_rx = NULL;
/* fall through */
default:
fsl_dummy_rx_refcnt--;
break;
}
mutex_unlock(&fsl_dummy_rx_lock);
}
static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
{
struct device *dev = mspi->dev;
struct device_node *np = dev->of_node;
const u32 *iprop;
int size;
void __iomem *spi_base;
unsigned long pram_ofs = -ENOMEM;
/* Can't use of_address_to_resource(), QE muram isn't at 0. */
iprop = of_get_property(np, "reg", &size);
/* QE with a fixed pram location? */
if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
/* QE but with a dynamic pram location? */
if (mspi->flags & SPI_QE) {
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
return pram_ofs;
}
spi_base = of_iomap(np, 1);
if (spi_base == NULL)
return -EINVAL;
if (mspi->flags & SPI_CPM2) {
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
out_be16(spi_base, pram_ofs);
} else {
struct spi_pram __iomem *pram = spi_base;
u16 rpbase = in_be16(&pram->rpbase);
/* Microcode relocation patch applied? */
if (rpbase) {
pram_ofs = rpbase;
} else {
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
out_be16(spi_base, pram_ofs);
}
}
iounmap(spi_base);
return pram_ofs;
}
int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
{
struct device *dev = mspi->dev;
struct device_node *np = dev->of_node;
const u32 *iprop;
int size;
unsigned long pram_ofs;
unsigned long bds_ofs;
if (!(mspi->flags & SPI_CPM_MODE))
return 0;
if (!fsl_spi_alloc_dummy_rx())
return -ENOMEM;
if (mspi->flags & SPI_QE) {
iprop = of_get_property(np, "cell-index", &size);
if (iprop && size == sizeof(*iprop))
mspi->subblock = *iprop;
switch (mspi->subblock) {
default:
dev_warn(dev, "cell-index unspecified, assuming SPI1");
/* fall through */
case 0:
mspi->subblock = QE_CR_SUBBLOCK_SPI1;
break;
case 1:
mspi->subblock = QE_CR_SUBBLOCK_SPI2;
break;
}
}
pram_ofs = fsl_spi_cpm_get_pram(mspi);
if (IS_ERR_VALUE(pram_ofs)) {
dev_err(dev, "can't allocate spi parameter ram\n");
goto err_pram;
}
bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
sizeof(*mspi->rx_bd), 8);
if (IS_ERR_VALUE(bds_ofs)) {
dev_err(dev, "can't allocate bds\n");
goto err_bds;
}
mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
dev_err(dev, "unable to map dummy tx buffer\n");
goto err_dummy_tx;
}
mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
DMA_FROM_DEVICE);
if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
dev_err(dev, "unable to map dummy rx buffer\n");
goto err_dummy_rx;
}
mspi->pram = cpm_muram_addr(pram_ofs);
mspi->tx_bd = cpm_muram_addr(bds_ofs);
mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
/* Initialize parameter ram. */
out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
out_be16(&mspi->pram->mrblr, SPI_MRBLR);
out_be32(&mspi->pram->rstate, 0);
out_be32(&mspi->pram->rdp, 0);
out_be16(&mspi->pram->rbptr, 0);
out_be16(&mspi->pram->rbc, 0);
out_be32(&mspi->pram->rxtmp, 0);
out_be32(&mspi->pram->tstate, 0);
out_be32(&mspi->pram->tdp, 0);
out_be16(&mspi->pram->tbptr, 0);
out_be16(&mspi->pram->tbc, 0);
out_be32(&mspi->pram->txtmp, 0);
return 0;
err_dummy_rx:
dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
err_dummy_tx:
cpm_muram_free(bds_ofs);
err_bds:
cpm_muram_free(pram_ofs);
err_pram:
fsl_spi_free_dummy_rx();
return -ENOMEM;
}
void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
{
struct device *dev = mspi->dev;
if (!(mspi->flags & SPI_CPM_MODE))
return;
dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
cpm_muram_free(cpm_muram_offset(mspi->pram));
fsl_spi_free_dummy_rx();
}
/*
* Freescale SPI controller driver cpm functions.
*
* Maintainer: Kumar Gala
*
* Copyright (C) 2006 Polycom, Inc.
* Copyright 2010 Freescale Semiconductor, Inc.
*
* CPM SPI and QE buffer descriptors mode support:
* Copyright (c) 2009 MontaVista Software, Inc.
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __SPI_FSL_CPM_H__
#define __SPI_FSL_CPM_H__
#include "spi-fsl-lib.h"
#ifdef CONFIG_FSL_SOC
extern void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi);
extern int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
struct spi_transfer *t, bool is_dma_mapped);
extern void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi);
extern void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events);
extern int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi);
extern void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi);
#else
static inline void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi) { }
static inline int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
struct spi_transfer *t,
bool is_dma_mapped) { return 0; }
static inline void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) { }
static inline void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) { }
static inline int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) { return 0; }
static inline void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) { }
#endif
#endif /* __SPI_FSL_CPM_H__ */
......@@ -23,7 +23,9 @@
#include <linux/mm.h>
#include <linux/of_platform.h>
#include <linux/spi/spi.h>
#ifdef CONFIG_FSL_SOC
#include <sysdev/fsl_soc.h>
#endif
#include "spi-fsl-lib.h"
......@@ -208,6 +210,7 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
/* Allocate bus num dynamically. */
pdata->bus_num = -1;
#ifdef CONFIG_FSL_SOC
/* SPI controller is either clocked from QE or SoC clock. */
pdata->sysclk = get_brgfreq();
if (pdata->sysclk == -1) {
......@@ -217,6 +220,11 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
goto err;
}
}
#else
ret = of_property_read_u32(np, "clock-frequency", &pdata->sysclk);
if (ret)
goto err;
#endif
prop = of_get_property(np, "mode", NULL);
if (prop && !strcmp(prop, "cpu-qe"))
......
......@@ -34,8 +34,10 @@ struct mpc8xxx_spi {
int subblock;
struct spi_pram __iomem *pram;
#ifdef CONFIG_FSL_SOC
struct cpm_buf_desc __iomem *tx_bd;
struct cpm_buf_desc __iomem *rx_bd;
#endif
struct spi_transfer *xfer_in_progress;
......@@ -67,6 +69,15 @@ struct mpc8xxx_spi {
unsigned int flags;
#ifdef CONFIG_SPI_FSL_SPI
int type;
int native_chipselects;
u8 max_bits_per_word;
void (*set_shifts)(u32 *rx_shift, u32 *tx_shift,
int bits_per_word, int msb_first);
#endif
struct workqueue_struct *workqueue;
struct work_struct work;
......@@ -87,12 +98,12 @@ struct spi_mpc8xxx_cs {
static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
{
out_be32(reg, val);
iowrite32be(val, reg);
}
static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
{
return in_be32(reg);
return ioread32be(reg);
}
struct mpc8xxx_spi_probe_info {
......
This diff is collapsed.
/*
* Freescale SPI controller driver.
*
* Maintainer: Kumar Gala
*
* Copyright (C) 2006 Polycom, Inc.
* Copyright 2010 Freescale Semiconductor, Inc.
*
* CPM SPI and QE buffer descriptors mode support:
* Copyright (c) 2009 MontaVista Software, Inc.
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
*
* GRLIB support:
* Copyright (c) 2012 Aeroflex Gaisler AB.
* Author: Andreas Larsson <andreas@gaisler.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __SPI_FSL_SPI_H__
#define __SPI_FSL_SPI_H__
/* SPI Controller registers */
struct fsl_spi_reg {
__be32 cap; /* TYPE_GRLIB specific */
u8 res1[0x1C];
__be32 mode;
__be32 event;
__be32 mask;
__be32 command;
__be32 transmit;
__be32 receive;
__be32 slvsel; /* TYPE_GRLIB specific */
};
/* SPI Controller mode register definitions */
#define SPMODE_LOOP (1 << 30)
#define SPMODE_CI_INACTIVEHIGH (1 << 29)
#define SPMODE_CP_BEGIN_EDGECLK (1 << 28)
#define SPMODE_DIV16 (1 << 27)
#define SPMODE_REV (1 << 26)
#define SPMODE_MS (1 << 25)
#define SPMODE_ENABLE (1 << 24)
#define SPMODE_LEN(x) ((x) << 20)
#define SPMODE_PM(x) ((x) << 16)
#define SPMODE_OP (1 << 14)
#define SPMODE_CG(x) ((x) << 7)
/* TYPE_GRLIB SPI Controller capability register definitions */
#define SPCAP_SSEN(x) (((x) >> 16) & 0x1)
#define SPCAP_SSSZ(x) (((x) >> 24) & 0xff)
#define SPCAP_MAXWLEN(x) (((x) >> 20) & 0xf)
/*
* Default for SPI Mode:
* SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
*/
#define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
/* SPIE register values */
#define SPIE_NE 0x00000200 /* Not empty */
#define SPIE_NF 0x00000100 /* Not full */
/* SPIM register values */
#define SPIM_NE 0x00000200 /* Not empty */
#define SPIM_NF 0x00000100 /* Not full */
#endif /* __SPI_FSL_SPI_H__ */
......@@ -265,9 +265,9 @@ static int spi_gpio_setup(struct spi_device *spi)
}
}
if (!status) {
status = spi_bitbang_setup(spi);
/* in case it was initialized from static board data */
spi_gpio->cs_gpios[spi->chip_select] = cs;
status = spi_bitbang_setup(spi);
}
if (status) {
......
......@@ -28,6 +28,7 @@
#include <linux/clk.h>
#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
#include <linux/gpio.h>
#include <asm/mpc52xx_psc.h>
struct mpc512x_psc_spi {
......@@ -113,7 +114,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
out_be32(&psc->ccr, ccr);
mps->bits_per_word = cs->bits_per_word;
if (mps->cs_control)
if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
}
......@@ -121,7 +122,7 @@ static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)
{
struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
if (mps->cs_control)
if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
}
......@@ -148,6 +149,9 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
in_8(&psc->mode);
out_8(&psc->mode, 0x0);
/* enable transmiter/receiver */
out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
while (len) {
int count;
int i;
......@@ -176,10 +180,6 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY);
/* enable transmiter/receiver */
out_8(&psc->command,
MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
wait_for_completion(&mps->done);
mdelay(1);
......@@ -204,9 +204,6 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
while (in_be32(&fifo->rxcnt)) {
in_8(&fifo->rxdata_8);
}
out_8(&psc->command,
MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
}
/* disable transmiter/receiver and fifo interrupt */
out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
......@@ -278,6 +275,7 @@ static int mpc512x_psc_spi_setup(struct spi_device *spi)
struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
struct mpc512x_psc_spi_cs *cs = spi->controller_state;
unsigned long flags;
int ret;
if (spi->bits_per_word % 8)
return -EINVAL;
......@@ -286,6 +284,19 @@ static int mpc512x_psc_spi_setup(struct spi_device *spi)
cs = kzalloc(sizeof *cs, GFP_KERNEL);
if (!cs)
return -ENOMEM;
if (gpio_is_valid(spi->cs_gpio)) {
ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev));
if (ret) {
dev_err(&spi->dev, "can't get CS gpio: %d\n",
ret);
kfree(cs);
return ret;
}
gpio_direction_output(spi->cs_gpio,
spi->mode & SPI_CS_HIGH ? 0 : 1);
}
spi->controller_state = cs;
}
......@@ -319,6 +330,8 @@ static int mpc512x_psc_spi_transfer(struct spi_device *spi,
static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
{
if (gpio_is_valid(spi->cs_gpio))
gpio_free(spi->cs_gpio);
kfree(spi->controller_state);
}
......@@ -405,6 +418,11 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
return IRQ_NONE;
}
static void mpc512x_spi_cs_control(struct spi_device *spi, bool onoff)
{
gpio_set_value(spi->cs_gpio, onoff);
}
/* bus_num is used only for the case dev->platform_data == NULL */
static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
u32 size, unsigned int irq,
......@@ -425,12 +443,9 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
mps->irq = irq;
if (pdata == NULL) {
dev_err(dev, "probe called without platform data, no "
"cs_control function will be called\n");
mps->cs_control = NULL;
mps->cs_control = mpc512x_spi_cs_control;
mps->sysclk = 0;
master->bus_num = bus_num;
master->num_chipselect = 255;
} else {
mps->cs_control = pdata->cs_control;
mps->sysclk = pdata->sysclk;
......
......@@ -612,6 +612,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
ssp->dmach = dma_request_channel(mask, mxs_ssp_dma_filter, ssp);
if (!ssp->dmach) {
dev_err(ssp->dev, "Failed to request DMA\n");
ret = -ENODEV;
goto out_master_free;
}
......
......@@ -393,8 +393,6 @@ static const struct of_device_id tiny_spi_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, tiny_spi_match);
#else /* CONFIG_OF */
#define tiny_spi_match NULL
#endif /* CONFIG_OF */
static struct platform_driver tiny_spi_driver = {
......@@ -404,7 +402,7 @@ static struct platform_driver tiny_spi_driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = NULL,
.of_match_table = tiny_spi_match,
.of_match_table = of_match_ptr(tiny_spi_match),
},
};
module_platform_driver(tiny_spi_driver);
......
......@@ -285,8 +285,12 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
timeout = jiffies + msecs_to_jiffies(1000);
while (!(__raw_readl(reg) & bit)) {
if (time_after(jiffies, timeout))
return -1;
if (time_after(jiffies, timeout)) {
if (!(__raw_readl(reg) & bit))
return -ETIMEDOUT;
else
return 0;
}
cpu_relax();
}
return 0;
......@@ -805,6 +809,10 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
return 0;
}
/*
* Note that we currently allow DMA only if we get a channel
* for both rx and tx. Otherwise we'll do PIO for both rx and tx.
*/
static int omap2_mcspi_request_dma(struct spi_device *spi)
{
struct spi_master *master = spi->master;
......@@ -823,21 +831,22 @@ static int omap2_mcspi_request_dma(struct spi_device *spi)
dma_cap_set(DMA_SLAVE, mask);
sig = mcspi_dma->dma_rx_sync_dev;
mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
if (!mcspi_dma->dma_rx) {
dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n");
return -EAGAIN;
}
if (!mcspi_dma->dma_rx)
goto no_dma;
sig = mcspi_dma->dma_tx_sync_dev;
mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
if (!mcspi_dma->dma_tx) {
dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n");
dma_release_channel(mcspi_dma->dma_rx);
mcspi_dma->dma_rx = NULL;
return -EAGAIN;
goto no_dma;
}
return 0;
no_dma:
dev_warn(&spi->dev, "not using DMA for McSPI\n");
return -EAGAIN;
}
static int omap2_mcspi_setup(struct spi_device *spi)
......@@ -870,7 +879,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) {
ret = omap2_mcspi_request_dma(spi);
if (ret < 0)
if (ret < 0 && ret != -EAGAIN)
return ret;
}
......@@ -928,6 +937,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
struct spi_device *spi;
struct spi_transfer *t = NULL;
struct spi_master *master;
struct omap2_mcspi_dma *mcspi_dma;
int cs_active = 0;
struct omap2_mcspi_cs *cs;
struct omap2_mcspi_device_config *cd;
......@@ -937,6 +947,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
spi = m->spi;
master = spi->master;
mcspi_dma = mcspi->dma_channels + spi->chip_select;
cs = spi->controller_state;
cd = spi->controller_data;
......@@ -993,7 +1004,8 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
__raw_writel(0, cs->base
+ OMAP2_MCSPI_TX0);
if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
(m->is_dma_mapped || t->len >= DMA_MIN_BYTES))
count = omap2_mcspi_txrx_dma(spi, t);
else
count = omap2_mcspi_txrx_pio(spi, t);
......@@ -1040,10 +1052,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
static int omap2_mcspi_transfer_one_message(struct spi_master *master,
struct spi_message *m)
{
struct spi_device *spi;
struct omap2_mcspi *mcspi;
struct omap2_mcspi_dma *mcspi_dma;
struct spi_transfer *t;
spi = m->spi;
mcspi = spi_master_get_devdata(master);
mcspi_dma = mcspi->dma_channels + spi->chip_select;
m->actual_length = 0;
m->status = 0;
......@@ -1078,7 +1094,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
if (m->is_dma_mapped || len < DMA_MIN_BYTES)
continue;
if (tx_buf != NULL) {
if (mcspi_dma->dma_tx && tx_buf != NULL) {
t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf,
len, DMA_TO_DEVICE);
if (dma_mapping_error(mcspi->dev, t->tx_dma)) {
......@@ -1087,7 +1103,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
return -EINVAL;
}
}
if (rx_buf != NULL) {
if (mcspi_dma->dma_rx && rx_buf != NULL) {
t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len,
DMA_FROM_DEVICE);
if (dma_mapping_error(mcspi->dev, t->rx_dma)) {
......@@ -1277,7 +1293,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
pm_runtime_enable(&pdev->dev);
if (status || omap2_mcspi_master_setup(mcspi) < 0)
status = omap2_mcspi_master_setup(mcspi);
if (status < 0)
goto disable_pm;
status = spi_register_master(master);
......
......@@ -22,7 +22,7 @@ static int ce4100_spi_probe(struct pci_dev *dev,
return ret;
ret = pcim_iomap_regions(dev, 1 << 0, "PXA2xx SPI");
if (!ret)
if (ret)
return ret;
memset(&spi_pdata, 0, sizeof(spi_pdata));
......@@ -47,8 +47,8 @@ static int ce4100_spi_probe(struct pci_dev *dev,
pi.size_data = sizeof(spi_pdata);
pdev = platform_device_register_full(&pi);
if (!pdev)
return -ENOMEM;
if (IS_ERR(pdev))
return PTR_ERR(pdev);
pci_set_drvdata(dev, pdev);
......
......@@ -22,6 +22,7 @@
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/spi/pxa2xx_spi.h>
......@@ -68,6 +69,7 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define LPSS_TX_HITHRESH_DFLT 224
/* Offset from drv_data->lpss_base */
#define SSP_REG 0x0c
#define SPI_CS_CONTROL 0x18
#define SPI_CS_CONTROL_SW_MODE BIT(0)
#define SPI_CS_CONTROL_CS_HIGH BIT(1)
......@@ -138,6 +140,10 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
/* Enable software chip select control */
value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH;
__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
/* Enable multiblock DMA transfers */
if (drv_data->master_info->enable_dma)
__lpss_ssp_write_priv(drv_data, SSP_REG, 1);
}
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
......@@ -1083,11 +1089,9 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
ssp = &pdata->ssp;
ssp->phys_base = res->start;
ssp->mmio_base = devm_request_and_ioremap(&pdev->dev, res);
if (!ssp->mmio_base) {
dev_err(&pdev->dev, "failed to ioremap mmio_base\n");
return NULL;
}
ssp->mmio_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ssp->mmio_base))
return PTR_ERR(ssp->mmio_base);
ssp->clk = devm_clk_get(&pdev->dev, NULL);
ssp->irq = platform_get_irq(pdev, 0);
......
This diff is collapsed.
......@@ -764,8 +764,6 @@ static const struct of_device_id sh_msiof_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, sh_msiof_match);
#else
#define sh_msiof_match NULL
#endif
static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = {
......@@ -780,7 +778,7 @@ static struct platform_driver sh_msiof_spi_drv = {
.name = "spi_sh_msiof",
.owner = THIS_MODULE,
.pm = &sh_msiof_spi_dev_pm_ops,
.of_match_table = sh_msiof_match,
.of_match_table = of_match_ptr(sh_msiof_match),
},
};
module_platform_driver(sh_msiof_spi_drv);
......
......@@ -660,7 +660,7 @@ static const struct of_device_id spi_sirfsoc_of_match[] = {
{ .compatible = "sirf,marco-spi", },
{}
};
MODULE_DEVICE_TABLE(of, sirfsoc_spi_of_match);
MODULE_DEVICE_TABLE(of, spi_sirfsoc_of_match);
static struct platform_driver spi_sirfsoc_driver = {
.driver = {
......
This diff is collapsed.
......@@ -33,7 +33,6 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-tegra.h>
#include <linux/clk/tegra.h>
#define SPI_COMMAND 0x000
......@@ -439,23 +438,13 @@ static irqreturn_t tegra_sflash_isr(int irq, void *context_data)
return handle_cpu_based_xfer(tsd);
}
static struct tegra_spi_platform_data *tegra_sflash_parse_dt(
struct platform_device *pdev)
static void tegra_sflash_parse_dt(struct tegra_sflash_data *tsd)
{
struct tegra_spi_platform_data *pdata;
struct device_node *np = pdev->dev.of_node;
u32 max_freq;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev, "Memory alloc for pdata failed\n");
return NULL;
}
if (!of_property_read_u32(np, "spi-max-frequency", &max_freq))
pdata->spi_max_frequency = max_freq;
struct device_node *np = tsd->dev->of_node;
return pdata;
if (of_property_read_u32(np, "spi-max-frequency",
&tsd->spi_max_frequency))
tsd->spi_max_frequency = 25000000; /* 25MHz */
}
static struct of_device_id tegra_sflash_of_match[] = {
......@@ -469,28 +458,15 @@ static int tegra_sflash_probe(struct platform_device *pdev)
struct spi_master *master;
struct tegra_sflash_data *tsd;
struct resource *r;
struct tegra_spi_platform_data *pdata = pdev->dev.platform_data;
int ret;
const struct of_device_id *match;
match = of_match_device(of_match_ptr(tegra_sflash_of_match),
&pdev->dev);
match = of_match_device(tegra_sflash_of_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "Error: No device match found\n");
return -ENODEV;
}
if (!pdata && pdev->dev.of_node)
pdata = tegra_sflash_parse_dt(pdev);
if (!pdata) {
dev_err(&pdev->dev, "No platform data, exiting\n");
return -ENODEV;
}
if (!pdata->spi_max_frequency)
pdata->spi_max_frequency = 25000000; /* 25MHz */
master = spi_alloc_master(&pdev->dev, sizeof(*tsd));
if (!master) {
dev_err(&pdev->dev, "master allocation failed\n");
......@@ -510,6 +486,8 @@ static int tegra_sflash_probe(struct platform_device *pdev)
tsd->dev = &pdev->dev;
spin_lock_init(&tsd->lock);
tegra_sflash_parse_dt(tsd);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(&pdev->dev, "No IO memory resource\n");
......@@ -538,7 +516,6 @@ static int tegra_sflash_probe(struct platform_device *pdev)
goto exit_free_irq;
}
tsd->spi_max_frequency = pdata->spi_max_frequency;
init_completion(&tsd->xfer_completion);
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
......@@ -658,7 +635,7 @@ static struct platform_driver tegra_sflash_driver = {
.name = "spi-tegra-sflash",
.owner = THIS_MODULE,
.pm = &slink_pm_ops,
.of_match_table = of_match_ptr(tegra_sflash_of_match),
.of_match_table = tegra_sflash_of_match,
},
.probe = tegra_sflash_probe,
.remove = tegra_sflash_remove,
......
......@@ -34,7 +34,6 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-tegra.h>
#include <linux/clk/tegra.h>
#define SLINK_COMMAND 0x000
......@@ -189,7 +188,6 @@ struct tegra_slink_data {
unsigned dma_buf_size;
unsigned max_buf_size;
bool is_curr_dma_xfer;
bool is_hw_based_cs;
struct completion rx_dma_complete;
struct completion tx_dma_complete;
......@@ -375,9 +373,6 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
read_words += tspi->curr_dma_words;
} else {
unsigned int bits_per_word;
bits_per_word = t->bits_per_word;
for (count = 0; count < rx_full_count; count++) {
x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
for (i = 0; (i < tspi->bytes_per_word); i++)
......@@ -720,7 +715,6 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
u8 bits_per_word;
unsigned total_fifo_words;
int ret;
struct tegra_spi_device_controller_data *cdata = spi->controller_data;
unsigned long command;
unsigned long command2;
......@@ -743,39 +737,11 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
command = tspi->def_command_reg;
command |= SLINK_BIT_LENGTH(bits_per_word - 1);
command |= SLINK_CS_SW | SLINK_CS_VALUE;
command2 = tspi->def_command2_reg;
command2 |= SLINK_SS_EN_CS(spi->chip_select);
/* possibly use the hw based chip select */
tspi->is_hw_based_cs = false;
if (cdata && cdata->is_hw_based_cs && is_single_xfer &&
((tspi->curr_dma_words * tspi->bytes_per_word) ==
(t->len - tspi->cur_pos))) {
int setup_count;
int sts2;
setup_count = cdata->cs_setup_clk_count >> 1;
setup_count = max(setup_count, 3);
command2 |= SLINK_SS_SETUP(setup_count);
if (tspi->chip_data->cs_hold_time) {
int hold_count;
hold_count = cdata->cs_hold_clk_count;
hold_count = max(hold_count, 0xF);
sts2 = tegra_slink_readl(tspi, SLINK_STATUS2);
sts2 &= ~SLINK_SS_HOLD_TIME(0xF);
sts2 |= SLINK_SS_HOLD_TIME(hold_count);
tegra_slink_writel(tspi, sts2, SLINK_STATUS2);
}
tspi->is_hw_based_cs = true;
}
if (tspi->is_hw_based_cs)
command &= ~SLINK_CS_SW;
else
command |= SLINK_CS_SW | SLINK_CS_VALUE;
command &= ~SLINK_MODES;
if (spi->mode & SPI_CPHA)
command |= SLINK_CK_SDA;
......@@ -1065,36 +1031,25 @@ static irqreturn_t tegra_slink_isr(int irq, void *context_data)
return IRQ_WAKE_THREAD;
}
static struct tegra_spi_platform_data *tegra_slink_parse_dt(
struct platform_device *pdev)
static void tegra_slink_parse_dt(struct tegra_slink_data *tspi)
{
struct tegra_spi_platform_data *pdata;
const unsigned int *prop;
struct device_node *np = pdev->dev.of_node;
struct device_node *np = tspi->dev->of_node;
u32 of_dma[2];
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev, "Memory alloc for pdata failed\n");
return NULL;
}
if (of_property_read_u32_array(np, "nvidia,dma-request-selector",
of_dma, 2) >= 0)
pdata->dma_req_sel = of_dma[1];
prop = of_get_property(np, "spi-max-frequency", NULL);
if (prop)
pdata->spi_max_frequency = be32_to_cpup(prop);
tspi->dma_req_sel = of_dma[1];
return pdata;
if (of_property_read_u32(np, "spi-max-frequency",
&tspi->spi_max_frequency))
tspi->spi_max_frequency = 25000000; /* 25MHz */
}
const struct tegra_slink_chip_data tegra30_spi_cdata = {
static const struct tegra_slink_chip_data tegra30_spi_cdata = {
.cs_hold_time = true,
};
const struct tegra_slink_chip_data tegra20_spi_cdata = {
static const struct tegra_slink_chip_data tegra20_spi_cdata = {
.cs_hold_time = false,
};
......@@ -1110,27 +1065,16 @@ static int tegra_slink_probe(struct platform_device *pdev)
struct spi_master *master;
struct tegra_slink_data *tspi;
struct resource *r;
struct tegra_spi_platform_data *pdata = pdev->dev.platform_data;
int ret, spi_irq;
const struct tegra_slink_chip_data *cdata = NULL;
const struct of_device_id *match;
match = of_match_device(of_match_ptr(tegra_slink_of_match), &pdev->dev);
match = of_match_device(tegra_slink_of_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "Error: No device match found\n");
return -ENODEV;
}
cdata = match->data;
if (!pdata && pdev->dev.of_node)
pdata = tegra_slink_parse_dt(pdev);
if (!pdata) {
dev_err(&pdev->dev, "No platform data, exiting\n");
return -ENODEV;
}
if (!pdata->spi_max_frequency)
pdata->spi_max_frequency = 25000000; /* 25MHz */
master = spi_alloc_master(&pdev->dev, sizeof(*tspi));
if (!master) {
......@@ -1148,11 +1092,12 @@ static int tegra_slink_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, master);
tspi = spi_master_get_devdata(master);
tspi->master = master;
tspi->dma_req_sel = pdata->dma_req_sel;
tspi->dev = &pdev->dev;
tspi->chip_data = cdata;
spin_lock_init(&tspi->lock);
tegra_slink_parse_dt(tspi);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(&pdev->dev, "No IO memory resource\n");
......@@ -1186,9 +1131,8 @@ static int tegra_slink_probe(struct platform_device *pdev)
tspi->max_buf_size = SLINK_FIFO_DEPTH << 2;
tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN;
tspi->spi_max_frequency = pdata->spi_max_frequency;
if (pdata->dma_req_sel) {
if (tspi->dma_req_sel) {
ret = tegra_slink_init_dma_param(tspi, true);
if (ret < 0) {
dev_err(&pdev->dev, "RxDma Init failed, err %d\n", ret);
......@@ -1331,7 +1275,7 @@ static struct platform_driver tegra_slink_driver = {
.name = "spi-tegra-slink",
.owner = THIS_MODULE,
.pm = &slink_pm_ops,
.of_match_table = of_match_ptr(tegra_slink_of_match),
.of_match_table = tegra_slink_of_match,
},
.probe = tegra_slink_probe,
.remove = tegra_slink_remove,
......
......@@ -615,7 +615,7 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
int size;
u32 n_writes;
int j;
struct spi_message *pmsg;
struct spi_message *pmsg, *tmp;
const u8 *tx_buf;
const u16 *tx_sbuf;
......@@ -656,7 +656,7 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
if (!data->pkt_rx_buff) {
/* flush queue and set status of all transfers to -ENOMEM */
dev_err(&data->master->dev, "%s :kzalloc failed\n", __func__);
list_for_each_entry(pmsg, data->queue.next, queue) {
list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) {
pmsg->status = -ENOMEM;
if (pmsg->complete != 0)
......@@ -703,7 +703,7 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
static void pch_spi_nomore_transfer(struct pch_spi_data *data)
{
struct spi_message *pmsg;
struct spi_message *pmsg, *tmp;
dev_dbg(&data->master->dev, "%s called\n", __func__);
/* Invoke complete callback
* [To the spi core..indicating end of transfer] */
......@@ -740,7 +740,7 @@ static void pch_spi_nomore_transfer(struct pch_spi_data *data)
dev_dbg(&data->master->dev,
"%s suspend/remove initiated, flushing queue\n",
__func__);
list_for_each_entry(pmsg, data->queue.next, queue) {
list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) {
pmsg->status = -EIO;
if (pmsg->complete)
......@@ -1187,7 +1187,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
static void pch_spi_process_messages(struct work_struct *pwork)
{
struct spi_message *pmsg;
struct spi_message *pmsg, *tmp;
struct pch_spi_data *data;
int bpw;
......@@ -1199,7 +1199,7 @@ static void pch_spi_process_messages(struct work_struct *pwork)
if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
dev_dbg(&data->master->dev, "%s suspend/remove initiated,"
"flushing queue\n", __func__);
list_for_each_entry(pmsg, data->queue.next, queue) {
list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) {
pmsg->status = -EIO;
if (pmsg->complete != 0) {
......@@ -1789,8 +1789,10 @@ static int __init pch_spi_init(void)
return ret;
ret = pci_register_driver(&pch_spi_pcidev_driver);
if (ret)
if (ret) {
platform_driver_unregister(&pch_spi_pd_driver);
return ret;
}
return 0;
}
......
......@@ -1376,6 +1376,14 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
xfer->bits_per_word = spi->bits_per_word;
if (!xfer->speed_hz)
xfer->speed_hz = spi->max_speed_hz;
if (master->bits_per_word_mask) {
/* Only 32 bits fit in the mask */
if (xfer->bits_per_word > 32)
return -EINVAL;
if (!(master->bits_per_word_mask &
BIT(xfer->bits_per_word - 1)))
return -EINVAL;
}
}
message->spi = spi;
......
......@@ -603,7 +603,7 @@ static int spidev_probe(struct spi_device *spi)
dev = device_create(spidev_class, &spi->dev, spidev->devt,
spidev, "spidev%d.%d",
spi->master->bus_num, spi->chip_select);
status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
status = PTR_RET(dev);
} else {
dev_dbg(&spi->dev, "no minor number available!\n");
status = -ENODEV;
......
......@@ -11,6 +11,8 @@
#ifndef __S3C64XX_PLAT_SPI_H
#define __S3C64XX_PLAT_SPI_H
#include <linux/dmaengine.h>
struct platform_device;
/**
......@@ -38,6 +40,7 @@ struct s3c64xx_spi_info {
int src_clk_nr;
int num_cs;
int (*cfg_gpio)(void);
dma_filter_fn filter;
};
/**
......
/*
* spi-tegra.h: SPI interface for Nvidia Tegra20 SLINK controller.
*
* Copyright (C) 2011 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _LINUX_SPI_TEGRA_H
#define _LINUX_SPI_TEGRA_H
struct tegra_spi_platform_data {
int dma_req_sel;
unsigned int spi_max_frequency;
};
/*
* Controller data from device to pass some info like
* hw based chip select can be used or not and if yes
* then CS hold and setup time.
*/
struct tegra_spi_device_controller_data {
bool is_hw_based_cs;
int cs_setup_clk_count;
int cs_hold_clk_count;
};
#endif /* _LINUX_SPI_TEGRA_H */
......@@ -228,6 +228,11 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* every chipselect is connected to a slave.
* @dma_alignment: SPI controller constraint on DMA buffers alignment.
* @mode_bits: flags understood by this controller driver
* @bits_per_word_mask: A mask indicating which values of bits_per_word are
* supported by the driver. Bit n indicates that a bits_per_word n+1 is
* suported. If set, the SPI core will reject any transfer with an
* unsupported bits_per_word. If not set, this value is simply ignored,
* and it's up to the individual driver to perform any validation.
* @flags: other constraints relevant to this driver
* @bus_lock_spinlock: spinlock for SPI bus locking
* @bus_lock_mutex: mutex for SPI bus locking
......@@ -301,6 +306,9 @@ struct spi_master {
/* spi_device.mode flags understood by this controller driver */
u16 mode_bits;
/* bitmask of supported bits_per_word for transfers */
u32 bits_per_word_mask;
/* other constraints relevant to this driver */
u16 flags;
#define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */
......
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