Merge tag 'spi-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2016 21:11:43 +0000 (14:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2016 21:11:43 +0000 (14:11 -0700)
Pull spi updates from Mark Brown:
 "Quite a lot of cleanup and maintainence work going on this release in
  various drivers, and also a fix for a nasty locking issue in the core:

   - A fix for locking issues when external drivers explicitly locked
     the bus with spi_bus_lock() - we were using the same lock to both
     control access to the physical bus in multi-threaded I/O operations
     and exclude multiple callers.

     Confusion between these two caused us to have scenarios where we
     were dropping locks.  These are fixed by splitting into two
     separate locks like should have been done originally, making
     everything much clearer and correct.

   - Support for DMA in spi_flash_read().

   - Support for instantiating spidev on ACPI systems, including some
     test devices used in Windows validation.

   - Use of the core DMA mapping functionality in the McSPI driver.

   - Start of support for ThunderX SPI controllers, involving a very big
     set of changes to the Cavium driver.

   - Support for Braswell, Exynos 5433, Kaby Lake, Merrifield, RK3036,
     RK3228, RK3368 controllers"

* tag 'spi-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (64 commits)
  spi: Split bus and I/O locking
  spi: octeon: Split driver into Octeon specific and common parts
  spi: octeon: Move include file from arch/mips to drivers/spi
  spi: octeon: Put register offsets into a struct
  spi: octeon: Store system clock freqency in struct octeon_spi
  spi: octeon: Convert driver to use readq()/writeq() functions
  spi: pic32-sqi: fixup wait_for_completion_timeout return handling
  spi: pic32: fixup wait_for_completion_timeout return handling
  spi: rockchip: limit transfers to (64K - 1) bytes
  spi: xilinx: Return IRQ_NONE if no interrupts were detected
  spi: xilinx: Handle errors from platform_get_irq()
  spi: s3c64xx: restore removed comments
  spi: s3c64xx: add Exynos5433 compatible for ioclk handling
  spi: s3c64xx: use error code from clk_prepare_enable()
  spi: s3c64xx: rename goto labels to meaningful names
  spi: s3c64xx: document the clocks and the clock-name property
  spi: s3c64xx: add exynos5433 spi compatible
  spi: s3c64xx: fix reference leak to master in s3c64xx_spi_remove()
  spi: spi-sh: Remove deprecated create_singlethread_workqueue
  spi: spi-topcliff-pch: Remove deprecated create_singlethread_workqueue
  ...

43 files changed:
Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
Documentation/devicetree/bindings/spi/spi-bus.txt
Documentation/devicetree/bindings/spi/spi-clps711x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi-davinci.txt
Documentation/devicetree/bindings/spi/spi-orion.txt
Documentation/devicetree/bindings/spi/spi-rockchip.txt
Documentation/devicetree/bindings/spi/spi-samsung.txt
Documentation/devicetree/bindings/spi/ti_qspi.txt
MAINTAINERS
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-bfin-sport.c
drivers/spi/spi-bfin5xx.c
drivers/spi/spi-cavium-octeon.c [new file with mode: 0644]
drivers/spi/spi-cavium.c [new file with mode: 0644]
drivers/spi/spi-cavium.h [moved from arch/mips/include/asm/octeon/cvmx-mpi-defs.h with 84% similarity]
drivers/spi/spi-clps711x.c
drivers/spi/spi-imx.c
drivers/spi/spi-loopback-test.c
drivers/spi/spi-mpc52xx-psc.c
drivers/spi/spi-octeon.c [deleted file]
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-orion.c
drivers/spi/spi-pic32-sqi.c
drivers/spi/spi-pic32.c
drivers/spi/spi-pxa2xx-dma.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-pxa2xx.h
drivers/spi/spi-rockchip.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-sh.c
drivers/spi/spi-sun4i.c
drivers/spi/spi-sun6i.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-topcliff-pch.c
drivers/spi/spi-txx9.c
drivers/spi/spi-xilinx.c
drivers/spi/spi.c
drivers/spi/spidev.c
include/linux/platform_data/spi-s3c64xx.h
include/linux/spi/spi.h

index 523341a0e1131a3e7b51878632b4040fb3a428c9..8bc95e2fc47fadf7eb75d215494f48af45107922 100644 (file)
@@ -11,7 +11,6 @@ Required properties:
   - "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51
 - reg : Offset and length of the register set for the device
 - interrupts : Should contain CSPI/eCSPI interrupt
-- fsl,spi-num-chipselects : Contains the number of the chipselect
 - cs-gpios : Specifies the gpio pins to be used for chipselects.
 - clocks : Clock specifiers for both ipg and per clocks.
 - clock-names : Clock names should include both "ipg" and "per"
@@ -21,6 +20,9 @@ See the clock consumer binding,
                Documentation/devicetree/bindings/dma/dma.txt
 - dma-names: DMA request names should include "tx" and "rx" if present.
 
+Obsolete properties:
+- fsl,spi-num-chipselects : Contains the number of the chipselect
+
 Example:
 
 ecspi@70010000 {
@@ -29,7 +31,6 @@ ecspi@70010000 {
        compatible = "fsl,imx51-ecspi";
        reg = <0x70010000 0x4000>;
        interrupts = <36>;
-       fsl,spi-num-chipselects = <2>;
        cs-gpios = <&gpio3 24 0>, /* GPIO3_24 */
                   <&gpio3 25 0>; /* GPIO3_25 */
        dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
index 42d595425dfb9f3cd8040f0dac7797ad006857d7..17822860cb98c34da30cf6822f708171b9987acc 100644 (file)
@@ -8,11 +8,10 @@ in slave mode.
 
 The SPI master node requires the following properties:
 - #address-cells  - number of cells required to define a chip select
-               address on the SPI bus.
+               address on the SPI bus.
 - #size-cells     - should be zero.
 - compatible      - name of SPI bus controller following generic names
-               recommended practice.
-- cs-gpios       - (optional) gpios chip select.
+               recommended practice.
 No other properties are required in the SPI bus node.  It is assumed
 that a driver for an SPI bus device will understand that it is an SPI bus.
 However, the binding does not attempt to define the specific method for
@@ -22,11 +21,12 @@ assumption that board specific platform code will be used to manage
 chip selects.  Individual drivers can define additional properties to
 support describing the chip select layout.
 
-Optional property:
-- num-cs : total number of chipselects
+Optional properties:
+- cs-gpios       - gpios chip select.
+- num-cs         - total number of chipselects.
 
-If cs-gpios is used the number of chip select will automatically increased
-with max(cs-gpios > hw cs)
+If cs-gpios is used the number of chip selects will be increased automatically
+with max(cs-gpios > hw cs).
 
 So if for example the controller has 2 CS lines, and the cs-gpios
 property looks like this:
@@ -45,29 +45,30 @@ SPI slave nodes must be children of the SPI master node and can
 contain the following properties.
 - reg             - (required) chip select address of device.
 - compatible      - (required) name of SPI device following generic names
-               recommended practice
-- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
+               recommended practice.
+- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz.
 - spi-cpol        - (optional) Empty property indicating device requires
-               inverse clock polarity (CPOL) mode
+               inverse clock polarity (CPOL) mode.
 - spi-cpha        - (optional) Empty property indicating device requires
-               shifted clock phase (CPHA) mode
+               shifted clock phase (CPHA) mode.
 - spi-cs-high     - (optional) Empty property indicating device requires
-               chip select active high
+               chip select active high.
 - spi-3wire       - (optional) Empty property indicating device requires
-                   3-wire mode.
+               3-wire mode.
 - spi-lsb-first   - (optional) Empty property indicating device requires
                LSB first mode.
-- spi-tx-bus-width - (optional) The bus width(number of data wires) that
+- spi-tx-bus-width - (optional) The bus width (number of data wires) that is
                       used for MOSI. Defaults to 1 if not present.
-- spi-rx-bus-width - (optional) The bus width(number of data wires) that
+- spi-rx-bus-width - (optional) The bus width (number of data wires) that is
                       used for MISO. Defaults to 1 if not present.
 - spi-rx-delay-us  - (optional) Microsecond delay after a read transfer.
 - spi-tx-delay-us  - (optional) Microsecond delay after a write transfer.
 
 Some SPI controllers and devices support Dual and Quad SPI transfer mode.
-It allows data in the SPI system to be transferred in 2 wires(DUAL) or 4 wires(QUAD).
+It allows data in the SPI system to be transferred using 2 wires (DUAL) or 4
+wires (QUAD).
 Now the value that spi-tx-bus-width and spi-rx-bus-width can receive is
-only 1(SINGLE), 2(DUAL) and 4(QUAD).
+only 1 (SINGLE), 2 (DUAL) and 4 (QUAD).
 Dual/Quad mode is not allowed when 3-wire mode is used.
 
 If a gpio chipselect is used for the SPI slave the gpio number will be passed
diff --git a/Documentation/devicetree/bindings/spi/spi-clps711x.txt b/Documentation/devicetree/bindings/spi/spi-clps711x.txt
new file mode 100644 (file)
index 0000000..4c3ec13
--- /dev/null
@@ -0,0 +1,33 @@
+Serial Peripheral Interface on Cirrus Logic CL-PS71xx, EP72xx, EP73xx
+
+Required properties
+- #address-cells: must be <1>
+- #size-cells: must be <0>
+- compatible: should include "cirrus,ep7209-spi"
+- reg: Address and length of one register range
+- interrupts: one interrupt line
+- clocks: One entry, refers to the SPI bus clock
+- cs-gpios: Specifies the gpio pins to be used for chipselects.
+           See: Documentation/devicetree/bindings/spi/spi-bus.txt
+
+An additional register is present in the system controller,
+which is assumed to be in the same device tree, with and marked
+as compatible with "cirrus,ep7209-syscon3".
+
+Example:
+
+spi@80000500 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       compatible = "cirrus,ep7209-spi";
+       reg = <0x80000500 0x4>;
+       interrupts = <15>;
+       clocks = <&clks CLPS711X_CLK_SPI>;
+       status = "disabled";
+};
+
+syscon3: syscon@80002200 {
+       compatible = "cirrus,ep7209-syscon3", "syscon";
+       reg = <0x80002200 0x40>;
+};
+
index d1e914adcf6e104856aae9ac023fc57a21292c5b..f5916c92fe9149140ae7183168cecc1a0eccf918 100644 (file)
@@ -21,7 +21,7 @@ Required properties:
        IP to the interrupt controller within the SoC. Possible values
        are 0 and 1. Manual says one of the two possible interrupt
        lines can be tied to the interrupt controller. Set this
-       based on a specifc SoC configuration.
+       based on a specific SoC configuration.
 - interrupts: interrupt number mapped to CPU.
 - clocks: spi clk phandle
 
index 98bc69815eb3f72482f9d5cf6212a91e26eef34d..4f629cc7634a910757bc41d3d21740d6fe163909 100644 (file)
@@ -8,7 +8,15 @@ Required properties:
     - "marvell,armada-380-spi", for the Armada 38x SoCs
     - "marvell,armada-390-spi", for the Armada 39x SoCs
     - "marvell,armada-xp-spi", for the Armada XP SoCs
-- reg : offset and length of the register set for the device
+- reg : offset and length of the register set for the device.
+       This property can optionally have additional entries to configure
+       the SPI direct access mode that some of the Marvell SoCs support
+       additionally to the normal indirect access (PIO) mode. The values
+       for the MBus "target" and "attribute" are defined in the Marvell
+       SoC "Functional Specifications" Manual in the chapter "Marvell
+       Core Processor Address Decoding".
+       The eight register sets following the control registers refer to
+       chip-select lines 0 through 7 respectively.
 - cell-index : Which of multiple SPI controllers is this.
 Optional properties:
 - interrupts : Is currently not used.
@@ -23,3 +31,42 @@ Example:
               interrupts = <23>;
               status = "disabled";
        };
+
+Example with SPI direct mode support (optionally):
+       spi0: spi@10600 {
+               compatible = "marvell,orion-spi";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               cell-index = <0>;
+               reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */
+                     <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */
+                     <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */
+                     <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */
+                     <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */
+                     <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */
+                     <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */
+                     <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */
+                     <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */
+               interrupts = <23>;
+               status = "disabled";
+       };
+
+To enable the direct mode, the board specific 'ranges' property in the
+'soc' node needs to add the entries for the desired SPI controllers
+and its chip-selects that are used in the direct mode instead of PIO
+mode. Here an example for this (SPI controller 0, device 1 and SPI
+controller 1, device 2 are used in direct mode. All other SPI device
+are used in the default indirect (PIO) mode):
+       soc {
+               /*
+                * Enable the SPI direct access by configuring an entry
+                * here in the board-specific ranges property
+                */
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000>, /* internal regs */
+                        <MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>, /* BootROM       */
+                        <MBUS_ID(0x01, 0x5e) 0 0 0xf1100000 0x10000>,  /* SPI0-DEV1 */
+                        <MBUS_ID(0x01, 0x9a) 0 0 0xf1110000 0x10000>;  /* SPI1-DEV2 */
+
+For further information on the MBus bindings, please see the MBus
+DT documentation:
+Documentation/devicetree/bindings/bus/mvebu-mbus.txt
index 1b14d69d8903a448a1138e38bf8332828bfd551e..d2ca153614f912fcd06cca8e1e65090030eba96e 100644 (file)
@@ -6,10 +6,13 @@ 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.
-    "rockchip,rk3399-spi", "rockchip,rk3066-spi" for rk3399.
+    "rockchip,rk3036-spi" for rk3036 SoCS.
+    "rockchip,rk3066-spi" for rk3066 SoCs.
+    "rockchip,rk3188-spi" for rk3188 SoCs.
+    "rockchip,rk3228-spi" for rk3228 SoCS.
+    "rockchip,rk3288-spi" for rk3288 SoCs.
+    "rockchip,rk3368-spi" for rk3368 SoCs.
+    "rockchip,rk3399-spi" for rk3399 SoCs.
 - reg: physical base address of the controller and length of memory mapped
        region.
 - interrupts: The interrupt number to the cpu. The interrupt specifier format
index 6dbdeb3c361a9973bd26a5cdcc3c73775bf8c883..49028a4f5df18863181c472c52da7104225ccca4 100644 (file)
@@ -9,7 +9,8 @@ Required SoC Specific Properties:
     - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms
     - samsung,s3c6410-spi: for s3c6410 platforms
     - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms
-    - samsung,exynos7-spi: for exynos7 platforms
+    - samsung,exynos5433-spi: for exynos5433 compatible controllers
+    - samsung,exynos7-spi: for exynos7 platforms <DEPRECATED>
 
 - reg: physical base address of the controller and length of memory mapped
   region.
@@ -23,6 +24,15 @@ Required SoC Specific Properties:
 - dma-names: Names for the dma channels. There must be at least one channel
   named "tx" for transmit and named "rx" for receive.
 
+- clocks: specifies the clock IDs provided to the SPI controller; they are
+  required for interacting with the controller itself, for synchronizing the bus
+  and as I/O clock (the latter is required by exynos5433 and exynos7).
+
+- clock-names: string names of the clocks in the 'clocks' property; for all the
+  the devices the names must be "spi", "spi_busclkN" (where N is determined by
+  "samsung,spi-src-clk"), while Exynos5433 should specify a third clock
+  "spi_ioclk" for the I/O clock.
+
 Required Board Specific Properties:
 
 - #address-cells: should be 1.
@@ -40,6 +50,9 @@ Optional Board Specific Properties:
 
 - cs-gpios: should specify GPIOs used for chipselects (see spi-bus.txt)
 
+- no-cs-readback: the CS line is disconnected, therefore the device should not
+  operate based on CS signalling.
+
 SPI Controller specific data in SPI slave nodes:
 
 - The spi slave nodes should provide the following information which is required
index 50b14f6b53a38c6f5390c927dd18be0e9aa711e9..e65fde4a73883f0a9457200a79a4d8e91ffeca44 100644 (file)
@@ -20,7 +20,7 @@ Optional properties:
                      chipselect register and offset of that register.
 
 NOTE: TI QSPI controller requires different pinmux and IODelay
-paramaters for Mode-0 and Mode-3 operations, which needs to be set up by
+parameters for Mode-0 and Mode-3 operations, which needs to be set up by
 the bootloader (U-Boot). Default configuration only supports Mode-0
 operation. Hence, "spi-cpol" and "spi-cpha" DT properties cannot be
 specified in the slave nodes of TI QSPI controller without appropriate
index 3a7b3998e8452006422d9a0d367e3e50d6339df1..403c162b0b2849d6adb06213ac5ee39df569dcf6 100644 (file)
@@ -10921,6 +10921,7 @@ L:      linux-spi@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
 Q:     http://patchwork.kernel.org/project/spi-devel-general/list/
 S:     Maintained
+F:     Documentation/devicetree/bindings/spi/
 F:     Documentation/spi/
 F:     drivers/spi/
 F:     include/linux/spi/
index 4b931ec8d90b610f498a3e317e0523e9d1aa6900..d6fb8d4b778672fd006446c0eab710d35f6e6e3a 100644 (file)
@@ -411,6 +411,7 @@ config SPI_OMAP24XX
        tristate "McSPI driver for OMAP"
        depends on HAS_DMA
        depends on ARCH_OMAP2PLUS || COMPILE_TEST
+       select SG_SPLIT
        help
          SPI master controller for OMAP24XX and later Multichannel SPI
          (McSPI) modules.
index 3c74d003535bb9fb922392901c0a9905dd9cdcbd..185367ef65761a742ac2f9e8eea75954faf92524 100644 (file)
@@ -56,6 +56,7 @@ obj-$(CONFIG_SPI_MT65XX)                += spi-mt65xx.o
 obj-$(CONFIG_SPI_MXS)                  += spi-mxs.o
 obj-$(CONFIG_SPI_NUC900)               += spi-nuc900.o
 obj-$(CONFIG_SPI_OC_TINY)              += spi-oc-tiny.o
+spi-octeon-objs                                := spi-cavium.o spi-cavium-octeon.o
 obj-$(CONFIG_SPI_OCTEON)               += spi-octeon.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)           += spi-omap-uwire.o
 obj-$(CONFIG_SPI_OMAP_100K)            += spi-omap-100k.o
index 6c967555a56a4d3a030bd374c2ef94151039e44a..01d0ba9c5942e5f2de8dda31c322ed33578c6e5b 100644 (file)
@@ -64,8 +64,6 @@ struct bfin_sport_spi_master_data {
        /* Pin request list */
        u16 *pin_req;
 
-       /* Driver message queue */
-       struct workqueue_struct *workqueue;
        struct work_struct pump_messages;
        spinlock_t lock;
        struct list_head queue;
@@ -300,7 +298,7 @@ bfin_sport_spi_giveback(struct bfin_sport_spi_master_data *drv_data)
        drv_data->cur_msg = NULL;
        drv_data->cur_transfer = NULL;
        drv_data->cur_chip = NULL;
-       queue_work(drv_data->workqueue, &drv_data->pump_messages);
+       schedule_work(&drv_data->pump_messages);
        spin_unlock_irqrestore(&drv_data->lock, flags);
 
        if (!drv_data->cs_change)
@@ -556,7 +554,7 @@ bfin_sport_spi_transfer(struct spi_device *spi, struct spi_message *msg)
        list_add_tail(&msg->queue, &drv_data->queue);
 
        if (drv_data->run && !drv_data->busy)
-               queue_work(drv_data->workqueue, &drv_data->pump_messages);
+               schedule_work(&drv_data->pump_messages);
 
        spin_unlock_irqrestore(&drv_data->lock, flags);
 
@@ -666,12 +664,7 @@ bfin_sport_spi_init_queue(struct bfin_sport_spi_master_data *drv_data)
        tasklet_init(&drv_data->pump_transfers,
                     bfin_sport_spi_pump_transfers, (unsigned long)drv_data);
 
-       /* init messages workqueue */
        INIT_WORK(&drv_data->pump_messages, bfin_sport_spi_pump_messages);
-       drv_data->workqueue =
-           create_singlethread_workqueue(dev_name(drv_data->master->dev.parent));
-       if (drv_data->workqueue == NULL)
-               return -EBUSY;
 
        return 0;
 }
@@ -694,7 +687,7 @@ bfin_sport_spi_start_queue(struct bfin_sport_spi_master_data *drv_data)
        drv_data->cur_chip = NULL;
        spin_unlock_irqrestore(&drv_data->lock, flags);
 
-       queue_work(drv_data->workqueue, &drv_data->pump_messages);
+       schedule_work(&drv_data->pump_messages);
 
        return 0;
 }
@@ -738,7 +731,7 @@ bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data)
        if (status)
                return status;
 
-       destroy_workqueue(drv_data->workqueue);
+       flush_work(&drv_data->pump_messages);
 
        return 0;
 }
index 1e91325bf39c20f0b5fdc368680de06d566fdb6f..249c7a3677c90d2076a27ac6d25c04f220e41829 100644 (file)
@@ -67,8 +67,6 @@ struct bfin_spi_master_data {
        /* BFIN hookup */
        struct bfin5xx_spi_master *master_info;
 
-       /* Driver message queue */
-       struct workqueue_struct *workqueue;
        struct work_struct pump_messages;
        spinlock_t lock;
        struct list_head queue;
@@ -359,7 +357,7 @@ static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data)
        drv_data->cur_msg = NULL;
        drv_data->cur_transfer = NULL;
        drv_data->cur_chip = NULL;
-       queue_work(drv_data->workqueue, &drv_data->pump_messages);
+       schedule_work(&drv_data->pump_messages);
        spin_unlock_irqrestore(&drv_data->lock, flags);
 
        msg->state = NULL;
@@ -946,7 +944,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
        list_add_tail(&msg->queue, &drv_data->queue);
 
        if (drv_data->running && !drv_data->busy)
-               queue_work(drv_data->workqueue, &drv_data->pump_messages);
+               schedule_work(&drv_data->pump_messages);
 
        spin_unlock_irqrestore(&drv_data->lock, flags);
 
@@ -1177,12 +1175,7 @@ static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
        tasklet_init(&drv_data->pump_transfers,
                     bfin_spi_pump_transfers, (unsigned long)drv_data);
 
-       /* init messages workqueue */
        INIT_WORK(&drv_data->pump_messages, bfin_spi_pump_messages);
-       drv_data->workqueue = create_singlethread_workqueue(
-                               dev_name(drv_data->master->dev.parent));
-       if (drv_data->workqueue == NULL)
-               return -EBUSY;
 
        return 0;
 }
@@ -1204,7 +1197,7 @@ static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
        drv_data->cur_chip = NULL;
        spin_unlock_irqrestore(&drv_data->lock, flags);
 
-       queue_work(drv_data->workqueue, &drv_data->pump_messages);
+       schedule_work(&drv_data->pump_messages);
 
        return 0;
 }
@@ -1246,7 +1239,7 @@ static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
        if (status != 0)
                return status;
 
-       destroy_workqueue(drv_data->workqueue);
+       flush_work(&drv_data->pump_messages);
 
        return 0;
 }
diff --git a/drivers/spi/spi-cavium-octeon.c b/drivers/spi/spi-cavium-octeon.c
new file mode 100644 (file)
index 0000000..ee4703e
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011, 2012 Cavium, Inc.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/octeon/octeon.h>
+
+#include "spi-cavium.h"
+
+static int octeon_spi_probe(struct platform_device *pdev)
+{
+       struct resource *res_mem;
+       void __iomem *reg_base;
+       struct spi_master *master;
+       struct octeon_spi *p;
+       int err = -ENOENT;
+
+       master = spi_alloc_master(&pdev->dev, sizeof(struct octeon_spi));
+       if (!master)
+               return -ENOMEM;
+       p = spi_master_get_devdata(master);
+       platform_set_drvdata(pdev, master);
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       reg_base = devm_ioremap_resource(&pdev->dev, res_mem);
+       if (IS_ERR(reg_base)) {
+               err = PTR_ERR(reg_base);
+               goto fail;
+       }
+
+       p->register_base = reg_base;
+       p->sys_freq = octeon_get_io_clock_rate();
+
+       p->regs.config = 0;
+       p->regs.status = 0x08;
+       p->regs.tx = 0x10;
+       p->regs.data = 0x80;
+
+       master->num_chipselect = 4;
+       master->mode_bits = SPI_CPHA |
+                           SPI_CPOL |
+                           SPI_CS_HIGH |
+                           SPI_LSB_FIRST |
+                           SPI_3WIRE;
+
+       master->transfer_one_message = octeon_spi_transfer_one_message;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
+       master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
+
+       master->dev.of_node = pdev->dev.of_node;
+       err = devm_spi_register_master(&pdev->dev, master);
+       if (err) {
+               dev_err(&pdev->dev, "register master failed: %d\n", err);
+               goto fail;
+       }
+
+       dev_info(&pdev->dev, "OCTEON SPI bus driver\n");
+
+       return 0;
+fail:
+       spi_master_put(master);
+       return err;
+}
+
+static int octeon_spi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct octeon_spi *p = spi_master_get_devdata(master);
+
+       /* Clear the CSENA* and put everything in a known state. */
+       writeq(0, p->register_base + OCTEON_SPI_CFG(p));
+
+       return 0;
+}
+
+static const struct of_device_id octeon_spi_match[] = {
+       { .compatible = "cavium,octeon-3010-spi", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, octeon_spi_match);
+
+static struct platform_driver octeon_spi_driver = {
+       .driver = {
+               .name           = "spi-octeon",
+               .of_match_table = octeon_spi_match,
+       },
+       .probe          = octeon_spi_probe,
+       .remove         = octeon_spi_remove,
+};
+
+module_platform_driver(octeon_spi_driver);
+
+MODULE_DESCRIPTION("Cavium, Inc. OCTEON SPI bus driver");
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-cavium.c b/drivers/spi/spi-cavium.c
new file mode 100644 (file)
index 0000000..5aaf215
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011, 2012 Cavium, Inc.
+ */
+
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "spi-cavium.h"
+
+static void octeon_spi_wait_ready(struct octeon_spi *p)
+{
+       union cvmx_mpi_sts mpi_sts;
+       unsigned int loops = 0;
+
+       do {
+               if (loops++)
+                       __delay(500);
+               mpi_sts.u64 = readq(p->register_base + OCTEON_SPI_STS(p));
+       } while (mpi_sts.s.busy);
+}
+
+static int octeon_spi_do_transfer(struct octeon_spi *p,
+                                 struct spi_message *msg,
+                                 struct spi_transfer *xfer,
+                                 bool last_xfer)
+{
+       struct spi_device *spi = msg->spi;
+       union cvmx_mpi_cfg mpi_cfg;
+       union cvmx_mpi_tx mpi_tx;
+       unsigned int clkdiv;
+       int mode;
+       bool cpha, cpol;
+       const u8 *tx_buf;
+       u8 *rx_buf;
+       int len;
+       int i;
+
+       mode = spi->mode;
+       cpha = mode & SPI_CPHA;
+       cpol = mode & SPI_CPOL;
+
+       clkdiv = p->sys_freq / (2 * xfer->speed_hz);
+
+       mpi_cfg.u64 = 0;
+
+       mpi_cfg.s.clkdiv = clkdiv;
+       mpi_cfg.s.cshi = (mode & SPI_CS_HIGH) ? 1 : 0;
+       mpi_cfg.s.lsbfirst = (mode & SPI_LSB_FIRST) ? 1 : 0;
+       mpi_cfg.s.wireor = (mode & SPI_3WIRE) ? 1 : 0;
+       mpi_cfg.s.idlelo = cpha != cpol;
+       mpi_cfg.s.cslate = cpha ? 1 : 0;
+       mpi_cfg.s.enable = 1;
+
+       if (spi->chip_select < 4)
+               p->cs_enax |= 1ull << (12 + spi->chip_select);
+       mpi_cfg.u64 |= p->cs_enax;
+
+       if (mpi_cfg.u64 != p->last_cfg) {
+               p->last_cfg = mpi_cfg.u64;
+               writeq(mpi_cfg.u64, p->register_base + OCTEON_SPI_CFG(p));
+       }
+       tx_buf = xfer->tx_buf;
+       rx_buf = xfer->rx_buf;
+       len = xfer->len;
+       while (len > OCTEON_SPI_MAX_BYTES) {
+               for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {
+                       u8 d;
+                       if (tx_buf)
+                               d = *tx_buf++;
+                       else
+                               d = 0;
+                       writeq(d, p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));
+               }
+               mpi_tx.u64 = 0;
+               mpi_tx.s.csid = spi->chip_select;
+               mpi_tx.s.leavecs = 1;
+               mpi_tx.s.txnum = tx_buf ? OCTEON_SPI_MAX_BYTES : 0;
+               mpi_tx.s.totnum = OCTEON_SPI_MAX_BYTES;
+               writeq(mpi_tx.u64, p->register_base + OCTEON_SPI_TX(p));
+
+               octeon_spi_wait_ready(p);
+               if (rx_buf)
+                       for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {
+                               u64 v = readq(p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));
+                               *rx_buf++ = (u8)v;
+                       }
+               len -= OCTEON_SPI_MAX_BYTES;
+       }
+
+       for (i = 0; i < len; i++) {
+               u8 d;
+               if (tx_buf)
+                       d = *tx_buf++;
+               else
+                       d = 0;
+               writeq(d, p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));
+       }
+
+       mpi_tx.u64 = 0;
+       mpi_tx.s.csid = spi->chip_select;
+       if (last_xfer)
+               mpi_tx.s.leavecs = xfer->cs_change;
+       else
+               mpi_tx.s.leavecs = !xfer->cs_change;
+       mpi_tx.s.txnum = tx_buf ? len : 0;
+       mpi_tx.s.totnum = len;
+       writeq(mpi_tx.u64, p->register_base + OCTEON_SPI_TX(p));
+
+       octeon_spi_wait_ready(p);
+       if (rx_buf)
+               for (i = 0; i < len; i++) {
+                       u64 v = readq(p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));
+                       *rx_buf++ = (u8)v;
+               }
+
+       if (xfer->delay_usecs)
+               udelay(xfer->delay_usecs);
+
+       return xfer->len;
+}
+
+int octeon_spi_transfer_one_message(struct spi_master *master,
+                                   struct spi_message *msg)
+{
+       struct octeon_spi *p = spi_master_get_devdata(master);
+       unsigned int total_len = 0;
+       int status = 0;
+       struct spi_transfer *xfer;
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               bool last_xfer = list_is_last(&xfer->transfer_list,
+                                             &msg->transfers);
+               int r = octeon_spi_do_transfer(p, msg, xfer, last_xfer);
+               if (r < 0) {
+                       status = r;
+                       goto err;
+               }
+               total_len += r;
+       }
+err:
+       msg->status = status;
+       msg->actual_length = total_len;
+       spi_finalize_current_message(master);
+       return status;
+}
similarity index 84%
rename from arch/mips/include/asm/octeon/cvmx-mpi-defs.h
rename to drivers/spi/spi-cavium.h
index 4615b102625b78217d17c8b9858fad714d1f27fb..88c5f36e7ea756f4e8a9d7cc03022cc3cdc146db 100644 (file)
@@ -1,32 +1,33 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2012 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
+#ifndef __SPI_CAVIUM_H
+#define __SPI_CAVIUM_H
 
-#ifndef __CVMX_MPI_DEFS_H__
-#define __CVMX_MPI_DEFS_H__
+#define OCTEON_SPI_MAX_BYTES 9
+#define OCTEON_SPI_MAX_CLOCK_HZ 16000000
+
+struct octeon_spi_regs {
+       int config;
+       int status;
+       int tx;
+       int data;
+};
+
+struct octeon_spi {
+       void __iomem *register_base;
+       u64 last_cfg;
+       u64 cs_enax;
+       int sys_freq;
+       struct octeon_spi_regs regs;
+};
+
+#define OCTEON_SPI_CFG(x)      (x->regs.config)
+#define OCTEON_SPI_STS(x)      (x->regs.status)
+#define OCTEON_SPI_TX(x)       (x->regs.tx)
+#define OCTEON_SPI_DAT0(x)     (x->regs.data)
+
+int octeon_spi_transfer_one_message(struct spi_master *master,
+                                   struct spi_message *msg);
+
+/* MPI register descriptions */
 
 #define CVMX_MPI_CFG (CVMX_ADD_IO_SEG(0x0001070000001000ull))
 #define CVMX_MPI_DATX(offset) (CVMX_ADD_IO_SEG(0x0001070000001080ull) + ((offset) & 15) * 8)
@@ -325,4 +326,4 @@ union cvmx_mpi_tx {
        struct cvmx_mpi_tx_cn61xx cnf71xx;
 };
 
-#endif
+#endif /* __SPI_CAVIUM_H */
index 8c30de0315e71bf5157fd6f6e84ce31ec0ec0838..18193df2eba8ab360d5326bee453a4349fd7b7a1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  CLPS711X SPI bus driver
  *
- *  Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
+ *  Copyright (C) 2012-2016 Alexander Shiyan <shc_work@mail.ru>
  *
  * 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
@@ -12,7 +12,6 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
-#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -20,9 +19,8 @@
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/clps711x.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_data/spi-clps711x.h>
 
-#define DRIVER_NAME    "spi-clps711x"
+#define DRIVER_NAME            "clps711x-spi"
 
 #define SYNCIO_FRMLEN(x)       ((x) << 8)
 #define SYNCIO_TXFRMEN         (1 << 14)
@@ -40,6 +38,17 @@ struct spi_clps711x_data {
 
 static int spi_clps711x_setup(struct spi_device *spi)
 {
+       if (!spi->controller_state) {
+               int ret;
+
+               ret = devm_gpio_request(&spi->master->dev, spi->cs_gpio,
+                                       dev_name(&spi->master->dev));
+               if (ret)
+                       return ret;
+
+               spi->controller_state = spi;
+       }
+
        /* We are expect that SPI-device is not selected */
        gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
 
@@ -104,20 +113,9 @@ static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
 static int spi_clps711x_probe(struct platform_device *pdev)
 {
        struct spi_clps711x_data *hw;
-       struct spi_clps711x_pdata *pdata = dev_get_platdata(&pdev->dev);
        struct spi_master *master;
        struct resource *res;
-       int i, irq, ret;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "No platform data supplied\n");
-               return -EINVAL;
-       }
-
-       if (pdata->num_chipselect < 1) {
-               dev_err(&pdev->dev, "At least one CS must be defined\n");
-               return -EINVAL;
-       }
+       int irq, ret;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
@@ -127,40 +125,24 @@ static int spi_clps711x_probe(struct platform_device *pdev)
        if (!master)
                return -ENOMEM;
 
-       master->cs_gpios = devm_kzalloc(&pdev->dev, sizeof(int) *
-                                       pdata->num_chipselect, GFP_KERNEL);
-       if (!master->cs_gpios) {
-               ret = -ENOMEM;
-               goto err_out;
-       }
-
-       master->bus_num = pdev->id;
+       master->bus_num = -1;
        master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
        master->bits_per_word_mask =  SPI_BPW_RANGE_MASK(1, 8);
-       master->num_chipselect = pdata->num_chipselect;
+       master->dev.of_node = pdev->dev.of_node;
        master->setup = spi_clps711x_setup;
        master->prepare_message = spi_clps711x_prepare_message;
        master->transfer_one = spi_clps711x_transfer_one;
 
        hw = spi_master_get_devdata(master);
 
-       for (i = 0; i < master->num_chipselect; i++) {
-               master->cs_gpios[i] = pdata->chipselect[i];
-               ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i],
-                                       DRIVER_NAME);
-               if (ret) {
-                       dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
-                       goto err_out;
-               }
-       }
-
        hw->spi_clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(hw->spi_clk)) {
                ret = PTR_ERR(hw->spi_clk);
                goto err_out;
        }
 
-       hw->syscon = syscon_regmap_lookup_by_pdevname("syscon.3");
+       hw->syscon =
+               syscon_regmap_lookup_by_compatible("cirrus,ep7209-syscon3");
        if (IS_ERR(hw->syscon)) {
                ret = PTR_ERR(hw->syscon);
                goto err_out;
@@ -185,14 +167,8 @@ static int spi_clps711x_probe(struct platform_device *pdev)
                goto err_out;
 
        ret = devm_spi_register_master(&pdev->dev, master);
-       if (!ret) {
-               dev_info(&pdev->dev,
-                        "SPI bus driver initialized. Master clock %u Hz\n",
-                        master->max_speed_hz);
+       if (!ret)
                return 0;
-       }
-
-       dev_err(&pdev->dev, "Failed to register master\n");
 
 err_out:
        spi_master_put(master);
@@ -200,9 +176,16 @@ err_out:
        return ret;
 }
 
+static const struct of_device_id clps711x_spi_dt_ids[] = {
+       { .compatible = "cirrus,ep7209-spi", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, clps711x_spi_dt_ids);
+
 static struct platform_driver clps711x_spi_driver = {
        .driver = {
                .name   = DRIVER_NAME,
+               .of_match_table = clps711x_spi_dt_ids,
        },
        .probe  = spi_clps711x_probe,
 };
index 50769078e72e98316f5ea19efd69de536be91a72..f63cb30f9010ed891d99958d44527ddba4028d53 100644 (file)
@@ -59,8 +59,6 @@
 struct spi_imx_config {
        unsigned int speed_hz;
        unsigned int bpw;
-       unsigned int mode;
-       u8 cs;
 };
 
 enum spi_imx_devtype {
@@ -76,7 +74,7 @@ struct spi_imx_data;
 
 struct spi_imx_devtype_data {
        void (*intctrl)(struct spi_imx_data *, int);
-       int (*config)(struct spi_imx_data *, struct spi_imx_config *);
+       int (*config)(struct spi_device *, struct spi_imx_config *);
        void (*trigger)(struct spi_imx_data *);
        int (*rx_available)(struct spi_imx_data *);
        void (*reset)(struct spi_imx_data *);
@@ -112,7 +110,6 @@ struct spi_imx_data {
        struct completion dma_tx_completion;
 
        const struct spi_imx_devtype_data *devtype_data;
-       int chipselect[0];
 };
 
 static inline int is_imx27_cspi(struct spi_imx_data *d)
@@ -312,7 +309,7 @@ static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx,
                (post << MX51_ECSPI_CTRL_POSTDIV_OFFSET);
 }
 
-static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
        unsigned val = 0;
 
@@ -325,7 +322,7 @@ static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int
        writel(val, spi_imx->base + MX51_ECSPI_INT);
 }
 
-static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
+static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
 {
        u32 reg;
 
@@ -334,9 +331,10 @@ static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
        writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
 }
 
-static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
-               struct spi_imx_config *config)
+static int mx51_ecspi_config(struct spi_device *spi,
+                            struct spi_imx_config *config)
 {
+       struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
        u32 ctrl = MX51_ECSPI_CTRL_ENABLE;
        u32 clk = config->speed_hz, delay, reg;
        u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
@@ -355,28 +353,28 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
        spi_imx->spi_bus_clk = clk;
 
        /* set chip select to use */
-       ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
+       ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select);
 
        ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET;
 
-       cfg |= MX51_ECSPI_CONFIG_SBBCTRL(config->cs);
+       cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
 
-       if (config->mode & SPI_CPHA)
-               cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
+       if (spi->mode & SPI_CPHA)
+               cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select);
        else
-               cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
+               cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select);
 
-       if (config->mode & SPI_CPOL) {
-               cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
-               cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
+       if (spi->mode & SPI_CPOL) {
+               cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select);
+               cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select);
        } else {
-               cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
-               cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
+               cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select);
+               cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select);
        }
-       if (config->mode & SPI_CS_HIGH)
-               cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
+       if (spi->mode & SPI_CS_HIGH)
+               cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
        else
-               cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs);
+               cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
 
        if (spi_imx->usedma)
                ctrl |= MX51_ECSPI_CTRL_SMC;
@@ -385,7 +383,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
        writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
 
        reg = readl(spi_imx->base + MX51_ECSPI_TESTREG);
-       if (config->mode & SPI_LOOP)
+       if (spi->mode & SPI_LOOP)
                reg |= MX51_ECSPI_TESTREG_LBC;
        else
                reg &= ~MX51_ECSPI_TESTREG_LBC;
@@ -424,12 +422,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
        return 0;
 }
 
-static int __maybe_unused mx51_ecspi_rx_available(struct spi_imx_data *spi_imx)
+static int mx51_ecspi_rx_available(struct spi_imx_data *spi_imx)
 {
        return readl(spi_imx->base + MX51_ECSPI_STAT) & MX51_ECSPI_STAT_RR;
 }
 
-static void __maybe_unused mx51_ecspi_reset(struct spi_imx_data *spi_imx)
+static void mx51_ecspi_reset(struct spi_imx_data *spi_imx)
 {
        /* drain receive buffer */
        while (mx51_ecspi_rx_available(spi_imx))
@@ -459,7 +457,7 @@ static void __maybe_unused mx51_ecspi_reset(struct spi_imx_data *spi_imx)
  * the i.MX35 has a slightly different register layout for bits
  * we do not use here.
  */
-static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
        unsigned int val = 0;
 
@@ -471,7 +469,7 @@ static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable
        writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
+static void mx31_trigger(struct spi_imx_data *spi_imx)
 {
        unsigned int reg;
 
@@ -480,11 +478,10 @@ static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
        writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx,
-               struct spi_imx_config *config)
+static int mx31_config(struct spi_device *spi, struct spi_imx_config *config)
 {
+       struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
        unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
-       int cs = spi_imx->chipselect[config->cs];
 
        reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
                MX31_CSPICTRL_DR_SHIFT;
@@ -496,14 +493,14 @@ static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx,
                reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
        }
 
-       if (config->mode & SPI_CPHA)
+       if (spi->mode & SPI_CPHA)
                reg |= MX31_CSPICTRL_PHA;
-       if (config->mode & SPI_CPOL)
+       if (spi->mode & SPI_CPOL)
                reg |= MX31_CSPICTRL_POL;
-       if (config->mode & SPI_CS_HIGH)
+       if (spi->mode & SPI_CS_HIGH)
                reg |= MX31_CSPICTRL_SSPOL;
-       if (cs < 0)
-               reg |= (cs + 32) <<
+       if (spi->cs_gpio < 0)
+               reg |= (spi->cs_gpio + 32) <<
                        (is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT :
                                                  MX31_CSPICTRL_CS_SHIFT);
 
@@ -512,12 +509,12 @@ static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx,
        return 0;
 }
 
-static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx)
+static int mx31_rx_available(struct spi_imx_data *spi_imx)
 {
        return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
 }
 
-static void __maybe_unused mx31_reset(struct spi_imx_data *spi_imx)
+static void mx31_reset(struct spi_imx_data *spi_imx)
 {
        /* drain receive buffer */
        while (readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR)
@@ -537,7 +534,7 @@ static void __maybe_unused mx31_reset(struct spi_imx_data *spi_imx)
 #define MX21_CSPICTRL_DR_SHIFT 14
 #define MX21_CSPICTRL_CS_SHIFT 19
 
-static void __maybe_unused mx21_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void mx21_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
        unsigned int val = 0;
 
@@ -549,7 +546,7 @@ static void __maybe_unused mx21_intctrl(struct spi_imx_data *spi_imx, int enable
        writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx)
+static void mx21_trigger(struct spi_imx_data *spi_imx)
 {
        unsigned int reg;
 
@@ -558,37 +555,36 @@ static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx)
        writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int __maybe_unused mx21_config(struct spi_imx_data *spi_imx,
-               struct spi_imx_config *config)
+static int mx21_config(struct spi_device *spi, struct spi_imx_config *config)
 {
+       struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
        unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER;
-       int cs = spi_imx->chipselect[config->cs];
        unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18;
 
        reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max) <<
                MX21_CSPICTRL_DR_SHIFT;
        reg |= config->bpw - 1;
 
-       if (config->mode & SPI_CPHA)
+       if (spi->mode & SPI_CPHA)
                reg |= MX21_CSPICTRL_PHA;
-       if (config->mode & SPI_CPOL)
+       if (spi->mode & SPI_CPOL)
                reg |= MX21_CSPICTRL_POL;
-       if (config->mode & SPI_CS_HIGH)
+       if (spi->mode & SPI_CS_HIGH)
                reg |= MX21_CSPICTRL_SSPOL;
-       if (cs < 0)
-               reg |= (cs + 32) << MX21_CSPICTRL_CS_SHIFT;
+       if (spi->cs_gpio < 0)
+               reg |= (spi->cs_gpio + 32) << MX21_CSPICTRL_CS_SHIFT;
 
        writel(reg, spi_imx->base + MXC_CSPICTRL);
 
        return 0;
 }
 
-static int __maybe_unused mx21_rx_available(struct spi_imx_data *spi_imx)
+static int mx21_rx_available(struct spi_imx_data *spi_imx)
 {
        return readl(spi_imx->base + MXC_CSPIINT) & MX21_INTREG_RR;
 }
 
-static void __maybe_unused mx21_reset(struct spi_imx_data *spi_imx)
+static void mx21_reset(struct spi_imx_data *spi_imx)
 {
        writel(1, spi_imx->base + MXC_RESET);
 }
@@ -604,7 +600,7 @@ static void __maybe_unused mx21_reset(struct spi_imx_data *spi_imx)
 #define MX1_CSPICTRL_MASTER    (1 << 10)
 #define MX1_CSPICTRL_DR_SHIFT  13
 
-static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
        unsigned int val = 0;
 
@@ -616,7 +612,7 @@ static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
        writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx)
+static void mx1_trigger(struct spi_imx_data *spi_imx)
 {
        unsigned int reg;
 
@@ -625,18 +621,18 @@ static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx)
        writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx,
-               struct spi_imx_config *config)
+static int mx1_config(struct spi_device *spi, struct spi_imx_config *config)
 {
+       struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
        unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
 
        reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
                MX1_CSPICTRL_DR_SHIFT;
        reg |= config->bpw - 1;
 
-       if (config->mode & SPI_CPHA)
+       if (spi->mode & SPI_CPHA)
                reg |= MX1_CSPICTRL_PHA;
-       if (config->mode & SPI_CPOL)
+       if (spi->mode & SPI_CPOL)
                reg |= MX1_CSPICTRL_POL;
 
        writel(reg, spi_imx->base + MXC_CSPICTRL);
@@ -644,12 +640,12 @@ static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx,
        return 0;
 }
 
-static int __maybe_unused mx1_rx_available(struct spi_imx_data *spi_imx)
+static int mx1_rx_available(struct spi_imx_data *spi_imx)
 {
        return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR;
 }
 
-static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx)
+static void mx1_reset(struct spi_imx_data *spi_imx)
 {
        writel(1, spi_imx->base + MXC_RESET);
 }
@@ -747,15 +743,13 @@ MODULE_DEVICE_TABLE(of, spi_imx_dt_ids);
 
 static void spi_imx_chipselect(struct spi_device *spi, int is_active)
 {
-       struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
-       int gpio = spi_imx->chipselect[spi->chip_select];
        int active = is_active != BITBANG_CS_INACTIVE;
        int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH);
 
-       if (!gpio_is_valid(gpio))
+       if (!gpio_is_valid(spi->cs_gpio))
                return;
 
-       gpio_set_value(gpio, dev_is_lowactive ^ active);
+       gpio_set_value(spi->cs_gpio, dev_is_lowactive ^ active);
 }
 
 static void spi_imx_push(struct spi_imx_data *spi_imx)
@@ -859,8 +853,6 @@ static int spi_imx_setupxfer(struct spi_device *spi,
 
        config.bpw = t ? t->bits_per_word : spi->bits_per_word;
        config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
-       config.mode = spi->mode;
-       config.cs = spi->chip_select;
 
        if (!config.speed_hz)
                config.speed_hz = spi->max_speed_hz;
@@ -891,7 +883,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
                        return ret;
        }
 
-       spi_imx->devtype_data->config(spi_imx, &config);
+       spi_imx->devtype_data->config(spi, &config);
 
        return 0;
 }
@@ -1050,6 +1042,8 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
                                struct spi_transfer *transfer)
 {
        struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+       unsigned long transfer_timeout;
+       unsigned long timeout;
 
        spi_imx->tx_buf = transfer->tx_buf;
        spi_imx->rx_buf = transfer->rx_buf;
@@ -1062,7 +1056,15 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
 
        spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE);
 
-       wait_for_completion(&spi_imx->xfer_done);
+       transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
+
+       timeout = wait_for_completion_timeout(&spi_imx->xfer_done,
+                                             transfer_timeout);
+       if (!timeout) {
+               dev_err(&spi->dev, "I/O Error in PIO\n");
+               spi_imx->devtype_data->reset(spi_imx);
+               return -ETIMEDOUT;
+       }
 
        return transfer->len;
 }
@@ -1080,14 +1082,12 @@ static int spi_imx_transfer(struct spi_device *spi,
 
 static int spi_imx_setup(struct spi_device *spi)
 {
-       struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
-       int gpio = spi_imx->chipselect[spi->chip_select];
-
        dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__,
                 spi->mode, spi->bits_per_word, spi->max_speed_hz);
 
-       if (gpio_is_valid(gpio))
-               gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
+       if (gpio_is_valid(spi->cs_gpio))
+               gpio_direction_output(spi->cs_gpio,
+                                     spi->mode & SPI_CS_HIGH ? 0 : 1);
 
        spi_imx_chipselect(spi, BITBANG_CS_INACTIVE);
 
@@ -1137,31 +1137,21 @@ static int spi_imx_probe(struct platform_device *pdev)
        struct spi_master *master;
        struct spi_imx_data *spi_imx;
        struct resource *res;
-       int i, ret, num_cs, irq;
+       int i, ret, irq;
 
        if (!np && !mxc_platform_info) {
                dev_err(&pdev->dev, "can't get the platform data\n");
                return -EINVAL;
        }
 
-       ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
-       if (ret < 0) {
-               if (mxc_platform_info)
-                       num_cs = mxc_platform_info->num_chipselect;
-               else
-                       return ret;
-       }
-
-       master = spi_alloc_master(&pdev->dev,
-                       sizeof(struct spi_imx_data) + sizeof(int) * num_cs);
+       master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
        if (!master)
                return -ENOMEM;
 
        platform_set_drvdata(pdev, master);
 
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
-       master->bus_num = pdev->id;
-       master->num_chipselect = num_cs;
+       master->bus_num = np ? -1 : pdev->id;
 
        spi_imx = spi_master_get_devdata(master);
        spi_imx->bitbang.master = master;
@@ -1170,22 +1160,16 @@ static int spi_imx_probe(struct platform_device *pdev)
        spi_imx->devtype_data = of_id ? of_id->data :
                (struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
 
-       for (i = 0; i < master->num_chipselect; i++) {
-               int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
-               if (!gpio_is_valid(cs_gpio) && mxc_platform_info)
-                       cs_gpio = mxc_platform_info->chipselect[i];
+       if (mxc_platform_info) {
+               master->num_chipselect = mxc_platform_info->num_chipselect;
+               master->cs_gpios = devm_kzalloc(&master->dev,
+                       sizeof(int) * master->num_chipselect, GFP_KERNEL);
+               if (!master->cs_gpios)
+                       return -ENOMEM;
 
-               spi_imx->chipselect[i] = cs_gpio;
-               if (!gpio_is_valid(cs_gpio))
-                       continue;
-
-               ret = devm_gpio_request(&pdev->dev, spi_imx->chipselect[i],
-                                       DRIVER_NAME);
-               if (ret) {
-                       dev_err(&pdev->dev, "can't get cs gpios\n");
-                       goto out_master_put;
-               }
-       }
+               for (i = 0; i < master->num_chipselect; i++)
+                       master->cs_gpios[i] = mxc_platform_info->chipselect[i];
+       }
 
        spi_imx->bitbang.chipselect = spi_imx_chipselect;
        spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
@@ -1267,6 +1251,19 @@ static int spi_imx_probe(struct platform_device *pdev)
                goto out_clk_put;
        }
 
+       for (i = 0; i < master->num_chipselect; i++) {
+               if (!gpio_is_valid(master->cs_gpios[i]))
+                       continue;
+
+               ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i],
+                                       DRIVER_NAME);
+               if (ret) {
+                       dev_err(&pdev->dev, "Can't get CS GPIO %i\n",
+                               master->cs_gpios[i]);
+                       goto out_clk_put;
+               }
+       }
+
        dev_info(&pdev->dev, "probed\n");
 
        clk_disable(spi_imx->clk_ipg);
index cf4bb36bee25c9bdf8ad39a570ceb61fda3a7421..faa1b133b0f1a4903b0ec1737a7f89638a33873c 100644 (file)
@@ -536,7 +536,7 @@ static int spi_test_check_loopback_result(struct spi_device *spi,
 
 mismatch_error:
        dev_err(&spi->dev,
-               "loopback strangeness - transfer missmatch on byte %04zx - expected 0x%02x, but got 0x%02x\n",
+               "loopback strangeness - transfer mismatch on byte %04zx - expected 0x%02x, but got 0x%02x\n",
                i, txb, rxb);
 
        return -EINVAL;
index 72d11ebefb2890cc538b186ee6a97a8513426e0a..42a8b8521f8f790cec466aea0cac8263babeb2f0 100644 (file)
@@ -42,7 +42,6 @@ struct mpc52xx_psc_spi {
        u8 bits_per_word;
        u8 busy;
 
-       struct workqueue_struct *workqueue;
        struct work_struct work;
 
        struct list_head queue;
@@ -299,7 +298,7 @@ static int mpc52xx_psc_spi_transfer(struct spi_device *spi,
 
        spin_lock_irqsave(&mps->lock, flags);
        list_add_tail(&m->queue, &mps->queue);
-       queue_work(mps->workqueue, &mps->work);
+       schedule_work(&mps->work);
        spin_unlock_irqrestore(&mps->lock, flags);
 
        return 0;
@@ -425,21 +424,12 @@ static int mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
        INIT_WORK(&mps->work, mpc52xx_psc_spi_work);
        INIT_LIST_HEAD(&mps->queue);
 
-       mps->workqueue = create_singlethread_workqueue(
-               dev_name(master->dev.parent));
-       if (mps->workqueue == NULL) {
-               ret = -EBUSY;
-               goto free_irq;
-       }
-
        ret = spi_register_master(master);
        if (ret < 0)
-               goto unreg_master;
+               goto free_irq;
 
        return ret;
 
-unreg_master:
-       destroy_workqueue(mps->workqueue);
 free_irq:
        free_irq(mps->irq, mps);
 free_master:
@@ -484,8 +474,7 @@ static int mpc52xx_psc_spi_of_remove(struct platform_device *op)
        struct spi_master *master = spi_master_get(platform_get_drvdata(op));
        struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
 
-       flush_workqueue(mps->workqueue);
-       destroy_workqueue(mps->workqueue);
+       flush_work(&mps->work);
        spi_unregister_master(master);
        free_irq(mps->irq, mps);
        if (mps->psc)
diff --git a/drivers/spi/spi-octeon.c b/drivers/spi/spi-octeon.c
deleted file mode 100644 (file)
index 3b17009..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2011, 2012 Cavium, Inc.
- */
-
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/spi/spi.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/of.h>
-
-#include <asm/octeon/octeon.h>
-#include <asm/octeon/cvmx-mpi-defs.h>
-
-#define OCTEON_SPI_CFG 0
-#define OCTEON_SPI_STS 0x08
-#define OCTEON_SPI_TX 0x10
-#define OCTEON_SPI_DAT0 0x80
-
-#define OCTEON_SPI_MAX_BYTES 9
-
-#define OCTEON_SPI_MAX_CLOCK_HZ 16000000
-
-struct octeon_spi {
-       u64 register_base;
-       u64 last_cfg;
-       u64 cs_enax;
-};
-
-static void octeon_spi_wait_ready(struct octeon_spi *p)
-{
-       union cvmx_mpi_sts mpi_sts;
-       unsigned int loops = 0;
-
-       do {
-               if (loops++)
-                       __delay(500);
-               mpi_sts.u64 = cvmx_read_csr(p->register_base + OCTEON_SPI_STS);
-       } while (mpi_sts.s.busy);
-}
-
-static int octeon_spi_do_transfer(struct octeon_spi *p,
-                                 struct spi_message *msg,
-                                 struct spi_transfer *xfer,
-                                 bool last_xfer)
-{
-       struct spi_device *spi = msg->spi;
-       union cvmx_mpi_cfg mpi_cfg;
-       union cvmx_mpi_tx mpi_tx;
-       unsigned int clkdiv;
-       unsigned int speed_hz;
-       int mode;
-       bool cpha, cpol;
-       const u8 *tx_buf;
-       u8 *rx_buf;
-       int len;
-       int i;
-
-       mode = spi->mode;
-       cpha = mode & SPI_CPHA;
-       cpol = mode & SPI_CPOL;
-
-       speed_hz = xfer->speed_hz;
-
-       clkdiv = octeon_get_io_clock_rate() / (2 * speed_hz);
-
-       mpi_cfg.u64 = 0;
-
-       mpi_cfg.s.clkdiv = clkdiv;
-       mpi_cfg.s.cshi = (mode & SPI_CS_HIGH) ? 1 : 0;
-       mpi_cfg.s.lsbfirst = (mode & SPI_LSB_FIRST) ? 1 : 0;
-       mpi_cfg.s.wireor = (mode & SPI_3WIRE) ? 1 : 0;
-       mpi_cfg.s.idlelo = cpha != cpol;
-       mpi_cfg.s.cslate = cpha ? 1 : 0;
-       mpi_cfg.s.enable = 1;
-
-       if (spi->chip_select < 4)
-               p->cs_enax |= 1ull << (12 + spi->chip_select);
-       mpi_cfg.u64 |= p->cs_enax;
-
-       if (mpi_cfg.u64 != p->last_cfg) {
-               p->last_cfg = mpi_cfg.u64;
-               cvmx_write_csr(p->register_base + OCTEON_SPI_CFG, mpi_cfg.u64);
-       }
-       tx_buf = xfer->tx_buf;
-       rx_buf = xfer->rx_buf;
-       len = xfer->len;
-       while (len > OCTEON_SPI_MAX_BYTES) {
-               for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {
-                       u8 d;
-                       if (tx_buf)
-                               d = *tx_buf++;
-                       else
-                               d = 0;
-                       cvmx_write_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i), d);
-               }
-               mpi_tx.u64 = 0;
-               mpi_tx.s.csid = spi->chip_select;
-               mpi_tx.s.leavecs = 1;
-               mpi_tx.s.txnum = tx_buf ? OCTEON_SPI_MAX_BYTES : 0;
-               mpi_tx.s.totnum = OCTEON_SPI_MAX_BYTES;
-               cvmx_write_csr(p->register_base + OCTEON_SPI_TX, mpi_tx.u64);
-
-               octeon_spi_wait_ready(p);
-               if (rx_buf)
-                       for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {
-                               u64 v = cvmx_read_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i));
-                               *rx_buf++ = (u8)v;
-                       }
-               len -= OCTEON_SPI_MAX_BYTES;
-       }
-
-       for (i = 0; i < len; i++) {
-               u8 d;
-               if (tx_buf)
-                       d = *tx_buf++;
-               else
-                       d = 0;
-               cvmx_write_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i), d);
-       }
-
-       mpi_tx.u64 = 0;
-       mpi_tx.s.csid = spi->chip_select;
-       if (last_xfer)
-               mpi_tx.s.leavecs = xfer->cs_change;
-       else
-               mpi_tx.s.leavecs = !xfer->cs_change;
-       mpi_tx.s.txnum = tx_buf ? len : 0;
-       mpi_tx.s.totnum = len;
-       cvmx_write_csr(p->register_base + OCTEON_SPI_TX, mpi_tx.u64);
-
-       octeon_spi_wait_ready(p);
-       if (rx_buf)
-               for (i = 0; i < len; i++) {
-                       u64 v = cvmx_read_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i));
-                       *rx_buf++ = (u8)v;
-               }
-
-       if (xfer->delay_usecs)
-               udelay(xfer->delay_usecs);
-
-       return xfer->len;
-}
-
-static int octeon_spi_transfer_one_message(struct spi_master *master,
-                                          struct spi_message *msg)
-{
-       struct octeon_spi *p = spi_master_get_devdata(master);
-       unsigned int total_len = 0;
-       int status = 0;
-       struct spi_transfer *xfer;
-
-       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               bool last_xfer = list_is_last(&xfer->transfer_list,
-                                             &msg->transfers);
-               int r = octeon_spi_do_transfer(p, msg, xfer, last_xfer);
-               if (r < 0) {
-                       status = r;
-                       goto err;
-               }
-               total_len += r;
-       }
-err:
-       msg->status = status;
-       msg->actual_length = total_len;
-       spi_finalize_current_message(master);
-       return status;
-}
-
-static int octeon_spi_probe(struct platform_device *pdev)
-{
-       struct resource *res_mem;
-       void __iomem *reg_base;
-       struct spi_master *master;
-       struct octeon_spi *p;
-       int err = -ENOENT;
-
-       master = spi_alloc_master(&pdev->dev, sizeof(struct octeon_spi));
-       if (!master)
-               return -ENOMEM;
-       p = spi_master_get_devdata(master);
-       platform_set_drvdata(pdev, master);
-
-       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       reg_base = devm_ioremap_resource(&pdev->dev, res_mem);
-       if (IS_ERR(reg_base)) {
-               err = PTR_ERR(reg_base);
-               goto fail;
-       }
-
-       p->register_base = (u64)reg_base;
-
-       master->num_chipselect = 4;
-       master->mode_bits = SPI_CPHA |
-                           SPI_CPOL |
-                           SPI_CS_HIGH |
-                           SPI_LSB_FIRST |
-                           SPI_3WIRE;
-
-       master->transfer_one_message = octeon_spi_transfer_one_message;
-       master->bits_per_word_mask = SPI_BPW_MASK(8);
-       master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
-
-       master->dev.of_node = pdev->dev.of_node;
-       err = devm_spi_register_master(&pdev->dev, master);
-       if (err) {
-               dev_err(&pdev->dev, "register master failed: %d\n", err);
-               goto fail;
-       }
-
-       dev_info(&pdev->dev, "OCTEON SPI bus driver\n");
-
-       return 0;
-fail:
-       spi_master_put(master);
-       return err;
-}
-
-static int octeon_spi_remove(struct platform_device *pdev)
-{
-       struct spi_master *master = platform_get_drvdata(pdev);
-       struct octeon_spi *p = spi_master_get_devdata(master);
-       u64 register_base = p->register_base;
-
-       /* Clear the CSENA* and put everything in a known state. */
-       cvmx_write_csr(register_base + OCTEON_SPI_CFG, 0);
-
-       return 0;
-}
-
-static const struct of_device_id octeon_spi_match[] = {
-       { .compatible = "cavium,octeon-3010-spi", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, octeon_spi_match);
-
-static struct platform_driver octeon_spi_driver = {
-       .driver = {
-               .name           = "spi-octeon",
-               .of_match_table = octeon_spi_match,
-       },
-       .probe          = octeon_spi_probe,
-       .remove         = octeon_spi_remove,
-};
-
-module_platform_driver(octeon_spi_driver);
-
-MODULE_DESCRIPTION("Cavium, Inc. OCTEON SPI bus driver");
-MODULE_AUTHOR("David Daney");
-MODULE_LICENSE("GPL");
index 1d237e93a2895c3f05ecca846df0d1c1db99ba5a..d5157b2222ce1d8837ed204598107f4968218aef 100644 (file)
@@ -419,16 +419,13 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
 
        if (mcspi_dma->dma_tx) {
                struct dma_async_tx_descriptor *tx;
-               struct scatterlist sg;
 
                dmaengine_slave_config(mcspi_dma->dma_tx, &cfg);
 
-               sg_init_table(&sg, 1);
-               sg_dma_address(&sg) = xfer->tx_dma;
-               sg_dma_len(&sg) = xfer->len;
-
-               tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1,
-               DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl,
+                                            xfer->tx_sg.nents,
+                                            DMA_MEM_TO_DEV,
+                                            DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
                if (tx) {
                        tx->callback = omap2_mcspi_tx_callback;
                        tx->callback_param = spi;
@@ -449,7 +446,10 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
 {
        struct omap2_mcspi      *mcspi;
        struct omap2_mcspi_dma  *mcspi_dma;
-       unsigned int            count, dma_count;
+       unsigned int            count, transfer_reduction = 0;
+       struct scatterlist      *sg_out[2];
+       int                     nb_sizes = 0, out_mapped_nents[2], ret, x;
+       size_t                  sizes[2];
        u32                     l;
        int                     elements = 0;
        int                     word_len, element_count;
@@ -457,10 +457,14 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
        mcspi = spi_master_get_devdata(spi->master);
        mcspi_dma = &mcspi->dma_channels[spi->chip_select];
        count = xfer->len;
-       dma_count = xfer->len;
 
+       /*
+        *  In the "End-of-Transfer Procedure" section for DMA RX in OMAP35x TRM
+        *  it mentions reducing DMA transfer length by one element in master
+        *  normal mode.
+        */
        if (mcspi->fifo_depth == 0)
-               dma_count -= es;
+               transfer_reduction = es;
 
        word_len = cs->word_len;
        l = mcspi_cached_chconf0(spi);
@@ -474,20 +478,46 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
 
        if (mcspi_dma->dma_rx) {
                struct dma_async_tx_descriptor *tx;
-               struct scatterlist sg;
 
                dmaengine_slave_config(mcspi_dma->dma_rx, &cfg);
 
+               /*
+                *  Reduce DMA transfer length by one more if McSPI is
+                *  configured in turbo mode.
+                */
                if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0)
-                       dma_count -= es;
+                       transfer_reduction += es;
+
+               if (transfer_reduction) {
+                       /* Split sgl into two. The second sgl won't be used. */
+                       sizes[0] = count - transfer_reduction;
+                       sizes[1] = transfer_reduction;
+                       nb_sizes = 2;
+               } else {
+                       /*
+                        * Don't bother splitting the sgl. This essentially
+                        * clones the original sgl.
+                        */
+                       sizes[0] = count;
+                       nb_sizes = 1;
+               }
+
+               ret = sg_split(xfer->rx_sg.sgl, xfer->rx_sg.nents,
+                              0, nb_sizes,
+                              sizes,
+                              sg_out, out_mapped_nents,
+                              GFP_KERNEL);
 
-               sg_init_table(&sg, 1);
-               sg_dma_address(&sg) = xfer->rx_dma;
-               sg_dma_len(&sg) = dma_count;
+               if (ret < 0) {
+                       dev_err(&spi->dev, "sg_split failed\n");
+                       return 0;
+               }
 
-               tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1,
-                               DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT |
-                               DMA_CTRL_ACK);
+               tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx,
+                                            sg_out[0],
+                                            out_mapped_nents[0],
+                                            DMA_DEV_TO_MEM,
+                                            DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
                if (tx) {
                        tx->callback = omap2_mcspi_rx_callback;
                        tx->callback_param = spi;
@@ -501,12 +531,17 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
        omap2_mcspi_set_dma_req(spi, 1, 1);
 
        wait_for_completion(&mcspi_dma->dma_rx_completion);
-       dma_unmap_single(mcspi->dev, xfer->rx_dma, count,
-                        DMA_FROM_DEVICE);
+
+       for (x = 0; x < nb_sizes; x++)
+               kfree(sg_out[x]);
 
        if (mcspi->fifo_depth > 0)
                return count;
 
+       /*
+        *  Due to the DMA transfer length reduction the missing bytes must
+        *  be read manually to receive all of the expected data.
+        */
        omap2_mcspi_set_enable(spi, 0);
 
        elements = element_count - 1;
@@ -615,8 +650,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 
        if (tx != NULL) {
                wait_for_completion(&mcspi_dma->dma_tx_completion);
-               dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,
-                                DMA_TO_DEVICE);
 
                if (mcspi->fifo_depth > 0) {
                        irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS;
@@ -1074,8 +1107,9 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
                gpio_free(spi->cs_gpio);
 }
 
-static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi,
-               struct spi_device *spi, struct spi_transfer *t)
+static int omap2_mcspi_transfer_one(struct spi_master *master,
+                                   struct spi_device *spi,
+                                   struct spi_transfer *t)
 {
 
        /* We only enable one channel at a time -- the one whose message is
@@ -1085,7 +1119,7 @@ static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi,
         * chipselect with the FORCE bit ... CS != channel enable.
         */
 
-       struct spi_master               *master;
+       struct omap2_mcspi              *mcspi;
        struct omap2_mcspi_dma          *mcspi_dma;
        struct omap2_mcspi_cs           *cs;
        struct omap2_mcspi_device_config *cd;
@@ -1093,7 +1127,7 @@ static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi,
        int                             status = 0;
        u32                             chconf;
 
-       master = spi->master;
+       mcspi = spi_master_get_devdata(master);
        mcspi_dma = mcspi->dma_channels + spi->chip_select;
        cs = spi->controller_state;
        cd = spi->controller_data;
@@ -1153,7 +1187,8 @@ static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi,
                unsigned        count;
 
                if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
-                   (t->len >= DMA_MIN_BYTES))
+                   master->cur_msg_mapped &&
+                   master->can_dma(master, spi, t))
                        omap2_mcspi_set_fifo(spi, t, 1);
 
                omap2_mcspi_set_enable(spi, 1);
@@ -1164,7 +1199,8 @@ static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi,
                                        + OMAP2_MCSPI_TX0);
 
                if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
-                   (t->len >= DMA_MIN_BYTES))
+                   master->cur_msg_mapped &&
+                   master->can_dma(master, spi, t))
                        count = omap2_mcspi_txrx_dma(spi, t);
                else
                        count = omap2_mcspi_txrx_pio(spi, t);
@@ -1233,55 +1269,11 @@ static int omap2_mcspi_prepare_message(struct spi_master *master,
        return 0;
 }
 
-static int omap2_mcspi_transfer_one(struct spi_master *master,
-               struct spi_device *spi, struct spi_transfer *t)
+static bool omap2_mcspi_can_dma(struct spi_master *master,
+                               struct spi_device *spi,
+                               struct spi_transfer *xfer)
 {
-       struct omap2_mcspi      *mcspi;
-       struct omap2_mcspi_dma  *mcspi_dma;
-       const void      *tx_buf = t->tx_buf;
-       void            *rx_buf = t->rx_buf;
-       unsigned        len = t->len;
-
-       mcspi = spi_master_get_devdata(master);
-       mcspi_dma = mcspi->dma_channels + spi->chip_select;
-
-       if ((len && !(rx_buf || tx_buf))) {
-               dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
-                               t->speed_hz,
-                               len,
-                               tx_buf ? "tx" : "",
-                               rx_buf ? "rx" : "",
-                               t->bits_per_word);
-               return -EINVAL;
-       }
-
-       if (len < DMA_MIN_BYTES)
-               goto skip_dma_map;
-
-       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)) {
-                       dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
-                                       'T', len);
-                       return -EINVAL;
-               }
-       }
-       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)) {
-                       dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
-                                       'R', len);
-                       if (tx_buf != NULL)
-                               dma_unmap_single(mcspi->dev, t->tx_dma,
-                                               len, DMA_TO_DEVICE);
-                       return -EINVAL;
-               }
-       }
-
-skip_dma_map:
-       return omap2_mcspi_work_one(mcspi, spi, t);
+       return (xfer->len >= DMA_MIN_BYTES);
 }
 
 static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
@@ -1361,6 +1353,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
        master->setup = omap2_mcspi_setup;
        master->auto_runtime_pm = true;
        master->prepare_message = omap2_mcspi_prepare_message;
+       master->can_dma = omap2_mcspi_can_dma;
        master->transfer_one = omap2_mcspi_transfer_one;
        master->set_cs = omap2_mcspi_set_cs;
        master->cleanup = omap2_mcspi_cleanup;
index a87cfd4ba17b38f47a8e6c823c335c308c482dc8..ded37025b445834d0367ef41cac7aa80b2c656cf 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/sizes.h>
@@ -43,6 +44,9 @@
 #define ORION_SPI_INT_CAUSE_REG                0x10
 #define ORION_SPI_TIMING_PARAMS_REG    0x18
 
+/* Register for the "Direct Mode" */
+#define SPI_DIRECT_WRITE_CONFIG_REG    0x20
+
 #define ORION_SPI_TMISO_SAMPLE_MASK    (0x3 << 6)
 #define ORION_SPI_TMISO_SAMPLE_1       (1 << 6)
 #define ORION_SPI_TMISO_SAMPLE_2       (2 << 6)
@@ -78,11 +82,18 @@ struct orion_spi_dev {
        bool                    is_errata_50mhz_ac;
 };
 
+struct orion_direct_acc {
+       void __iomem            *vaddr;
+       u32                     size;
+};
+
 struct orion_spi {
        struct spi_master       *master;
        void __iomem            *base;
        struct clk              *clk;
        const struct orion_spi_dev *devdata;
+
+       struct orion_direct_acc direct_access[ORION_NUM_CHIPSELECTS];
 };
 
 static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
@@ -372,10 +383,39 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 {
        unsigned int count;
        int word_len;
+       struct orion_spi *orion_spi;
+       int cs = spi->chip_select;
 
        word_len = spi->bits_per_word;
        count = xfer->len;
 
+       orion_spi = spi_master_get_devdata(spi->master);
+
+       /*
+        * Use SPI direct write mode if base address is available. Otherwise
+        * fall back to PIO mode for this transfer.
+        */
+       if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) &&
+           (word_len == 8)) {
+               unsigned int cnt = count / 4;
+               unsigned int rem = count % 4;
+
+               /*
+                * Send the TX-data to the SPI device via the direct
+                * mapped address window
+                */
+               iowrite32_rep(orion_spi->direct_access[cs].vaddr,
+                             xfer->tx_buf, cnt);
+               if (rem) {
+                       u32 *buf = (u32 *)xfer->tx_buf;
+
+                       iowrite8_rep(orion_spi->direct_access[cs].vaddr,
+                                    &buf[cnt], rem);
+               }
+
+               return count;
+       }
+
        if (word_len == 8) {
                const u8 *tx = xfer->tx_buf;
                u8 *rx = xfer->rx_buf;
@@ -425,6 +465,10 @@ static int orion_spi_reset(struct orion_spi *orion_spi)
 {
        /* Verify that the CS is deasserted */
        orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+
+       /* Don't deassert CS between the direct mapped SPI transfers */
+       writel(0, spi_reg(orion_spi, SPI_DIRECT_WRITE_CONFIG_REG));
+
        return 0;
 }
 
@@ -504,6 +548,7 @@ static int orion_spi_probe(struct platform_device *pdev)
        struct resource *r;
        unsigned long tclk_hz;
        int status = 0;
+       struct device_node *np;
 
        master = spi_alloc_master(&pdev->dev, sizeof(*spi));
        if (master == NULL) {
@@ -576,6 +621,49 @@ static int orion_spi_probe(struct platform_device *pdev)
                goto out_rel_clk;
        }
 
+       /* Scan all SPI devices of this controller for direct mapped devices */
+       for_each_available_child_of_node(pdev->dev.of_node, np) {
+               u32 cs;
+
+               /* Get chip-select number from the "reg" property */
+               status = of_property_read_u32(np, "reg", &cs);
+               if (status) {
+                       dev_err(&pdev->dev,
+                               "%s has no valid 'reg' property (%d)\n",
+                               np->full_name, status);
+                       status = 0;
+                       continue;
+               }
+
+               /*
+                * Check if an address is configured for this SPI device. If
+                * not, the MBus mapping via the 'ranges' property in the 'soc'
+                * node is not configured and this device should not use the
+                * direct mode. In this case, just continue with the next
+                * device.
+                */
+               status = of_address_to_resource(pdev->dev.of_node, cs + 1, r);
+               if (status)
+                       continue;
+
+               /*
+                * Only map one page for direct access. This is enough for the
+                * simple TX transfer which only writes to the first word.
+                * This needs to get extended for the direct SPI-NOR / SPI-NAND
+                * support, once this gets implemented.
+                */
+               spi->direct_access[cs].vaddr = devm_ioremap(&pdev->dev,
+                                                           r->start,
+                                                           PAGE_SIZE);
+               if (!spi->direct_access[cs].vaddr) {
+                       status = -ENOMEM;
+                       goto out_rel_clk;
+               }
+               spi->direct_access[cs].size = PAGE_SIZE;
+
+               dev_info(&pdev->dev, "CS%d configured for direct access\n", cs);
+       }
+
        pm_runtime_set_active(&pdev->dev);
        pm_runtime_use_autosuspend(&pdev->dev);
        pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
index ca3c8d94b2902de8cee54381ba033f7279d5afb7..c41abddab31893a1d1948f6bb912459b2973a00f 100644 (file)
@@ -354,6 +354,7 @@ static int pic32_sqi_one_message(struct spi_master *master,
        struct spi_transfer *xfer;
        struct pic32_sqi *sqi;
        int ret = 0, mode;
+       unsigned long timeout;
        u32 val;
 
        sqi = spi_master_get_devdata(master);
@@ -419,10 +420,10 @@ static int pic32_sqi_one_message(struct spi_master *master,
        writel(val, sqi->regs + PESQI_BD_CTRL_REG);
 
        /* wait for xfer completion */
-       ret = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ);
-       if (ret <= 0) {
+       timeout = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ);
+       if (timeout == 0) {
                dev_err(&sqi->master->dev, "wait timedout/interrupted\n");
-               ret = -EIO;
+               ret = -ETIMEDOUT;
                msg->status = ret;
        } else {
                /* success */
index 73db87f805a1fb1b76d57518da9748d2bed4a164..fefb688a34328f863953b106052d1e9589e526f6 100644 (file)
@@ -507,6 +507,7 @@ static int pic32_spi_one_transfer(struct spi_master *master,
 {
        struct pic32_spi *pic32s;
        bool dma_issued = false;
+       unsigned long timeout;
        int ret;
 
        pic32s = spi_master_get_devdata(master);
@@ -553,8 +554,8 @@ static int pic32_spi_one_transfer(struct spi_master *master,
        }
 
        /* wait for completion */
-       ret = wait_for_completion_timeout(&pic32s->xfer_done, 2 * HZ);
-       if (ret <= 0) {
+       timeout = wait_for_completion_timeout(&pic32s->xfer_done, 2 * HZ);
+       if (timeout == 0) {
                dev_err(&spi->dev, "wait error/timedout\n");
                if (dma_issued) {
                        dmaengine_terminate_all(master->dma_rx);
index a18a03d0afb709a51eb9515cfee7d8acf181d2e6..db3ae1dd829e6a48d82ba36a265d3c33ecc282c7 100644 (file)
 
 #include "spi-pxa2xx.h"
 
-static int pxa2xx_spi_map_dma_buffer(struct driver_data *drv_data,
-                                    enum dma_data_direction dir)
-{
-       int i, nents, len = drv_data->len;
-       struct scatterlist *sg;
-       struct device *dmadev;
-       struct sg_table *sgt;
-       void *buf, *pbuf;
-
-       if (dir == DMA_TO_DEVICE) {
-               dmadev = drv_data->tx_chan->device->dev;
-               sgt = &drv_data->tx_sgt;
-               buf = drv_data->tx;
-       } else {
-               dmadev = drv_data->rx_chan->device->dev;
-               sgt = &drv_data->rx_sgt;
-               buf = drv_data->rx;
-       }
-
-       nents = DIV_ROUND_UP(len, SZ_2K);
-       if (nents != sgt->nents) {
-               int ret;
-
-               sg_free_table(sgt);
-               ret = sg_alloc_table(sgt, nents, GFP_ATOMIC);
-               if (ret)
-                       return ret;
-       }
-
-       pbuf = buf;
-       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-               size_t bytes = min_t(size_t, len, SZ_2K);
-
-               sg_set_buf(sg, pbuf, bytes);
-               pbuf += bytes;
-               len -= bytes;
-       }
-
-       nents = dma_map_sg(dmadev, sgt->sgl, sgt->nents, dir);
-       if (!nents)
-               return -ENOMEM;
-
-       return nents;
-}
-
-static void pxa2xx_spi_unmap_dma_buffer(struct driver_data *drv_data,
-                                       enum dma_data_direction dir)
-{
-       struct device *dmadev;
-       struct sg_table *sgt;
-
-       if (dir == DMA_TO_DEVICE) {
-               dmadev = drv_data->tx_chan->device->dev;
-               sgt = &drv_data->tx_sgt;
-       } else {
-               dmadev = drv_data->rx_chan->device->dev;
-               sgt = &drv_data->rx_sgt;
-       }
-
-       dma_unmap_sg(dmadev, sgt->sgl, sgt->nents, dir);
-}
-
-static void pxa2xx_spi_unmap_dma_buffers(struct driver_data *drv_data)
-{
-       if (!drv_data->dma_mapped)
-               return;
-
-       pxa2xx_spi_unmap_dma_buffer(drv_data, DMA_FROM_DEVICE);
-       pxa2xx_spi_unmap_dma_buffer(drv_data, DMA_TO_DEVICE);
-
-       drv_data->dma_mapped = 0;
-}
-
 static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
                                             bool error)
 {
@@ -125,8 +52,6 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
                        pxa2xx_spi_write(drv_data, SSTO, 0);
 
                if (!error) {
-                       pxa2xx_spi_unmap_dma_buffers(drv_data);
-
                        msg->actual_length += drv_data->len;
                        msg->state = pxa2xx_spi_next_transfer(drv_data);
                } else {
@@ -152,11 +77,12 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
                           enum dma_transfer_direction dir)
 {
        struct chip_data *chip = drv_data->cur_chip;
+       struct spi_transfer *xfer = drv_data->cur_transfer;
        enum dma_slave_buswidth width;
        struct dma_slave_config cfg;
        struct dma_chan *chan;
        struct sg_table *sgt;
-       int nents, ret;
+       int ret;
 
        switch (drv_data->n_bytes) {
        case 1:
@@ -178,17 +104,15 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
                cfg.dst_addr_width = width;
                cfg.dst_maxburst = chip->dma_burst_size;
 
-               sgt = &drv_data->tx_sgt;
-               nents = drv_data->tx_nents;
-               chan = drv_data->tx_chan;
+               sgt = &xfer->tx_sg;
+               chan = drv_data->master->dma_tx;
        } else {
                cfg.src_addr = drv_data->ssdr_physical;
                cfg.src_addr_width = width;
                cfg.src_maxburst = chip->dma_burst_size;
 
-               sgt = &drv_data->rx_sgt;
-               nents = drv_data->rx_nents;
-               chan = drv_data->rx_chan;
+               sgt = &xfer->rx_sg;
+               chan = drv_data->master->dma_rx;
        }
 
        ret = dmaengine_slave_config(chan, &cfg);
@@ -197,46 +121,10 @@ pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
                return NULL;
        }
 
-       return dmaengine_prep_slave_sg(chan, sgt->sgl, nents, dir,
+       return dmaengine_prep_slave_sg(chan, sgt->sgl, sgt->nents, dir,
                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 }
 
-bool pxa2xx_spi_dma_is_possible(size_t len)
-{
-       return len <= MAX_DMA_LEN;
-}
-
-int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
-{
-       const struct chip_data *chip = drv_data->cur_chip;
-       int ret;
-
-       if (!chip->enable_dma)
-               return 0;
-
-       /* Don't bother with DMA if we can't do even a single burst */
-       if (drv_data->len < chip->dma_burst_size)
-               return 0;
-
-       ret = pxa2xx_spi_map_dma_buffer(drv_data, DMA_TO_DEVICE);
-       if (ret <= 0) {
-               dev_warn(&drv_data->pdev->dev, "failed to DMA map TX\n");
-               return 0;
-       }
-
-       drv_data->tx_nents = ret;
-
-       ret = pxa2xx_spi_map_dma_buffer(drv_data, DMA_FROM_DEVICE);
-       if (ret <= 0) {
-               pxa2xx_spi_unmap_dma_buffer(drv_data, DMA_TO_DEVICE);
-               dev_warn(&drv_data->pdev->dev, "failed to DMA map RX\n");
-               return 0;
-       }
-
-       drv_data->rx_nents = ret;
-       return 1;
-}
-
 irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
 {
        u32 status;
@@ -245,8 +133,8 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
        if (status & SSSR_ROR) {
                dev_err(&drv_data->pdev->dev, "FIFO overrun\n");
 
-               dmaengine_terminate_async(drv_data->rx_chan);
-               dmaengine_terminate_async(drv_data->tx_chan);
+               dmaengine_terminate_async(drv_data->master->dma_rx);
+               dmaengine_terminate_async(drv_data->master->dma_tx);
 
                pxa2xx_spi_dma_transfer_complete(drv_data, true);
                return IRQ_HANDLED;
@@ -285,16 +173,15 @@ int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst)
        return 0;
 
 err_rx:
-       dmaengine_terminate_async(drv_data->tx_chan);
+       dmaengine_terminate_async(drv_data->master->dma_tx);
 err_tx:
-       pxa2xx_spi_unmap_dma_buffers(drv_data);
        return err;
 }
 
 void pxa2xx_spi_dma_start(struct driver_data *drv_data)
 {
-       dma_async_issue_pending(drv_data->rx_chan);
-       dma_async_issue_pending(drv_data->tx_chan);
+       dma_async_issue_pending(drv_data->master->dma_rx);
+       dma_async_issue_pending(drv_data->master->dma_tx);
 
        atomic_set(&drv_data->dma_running, 1);
 }
@@ -303,21 +190,22 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
 {
        struct pxa2xx_spi_master *pdata = drv_data->master_info;
        struct device *dev = &drv_data->pdev->dev;
+       struct spi_master *master = drv_data->master;
        dma_cap_mask_t mask;
 
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
-       drv_data->tx_chan = dma_request_slave_channel_compat(mask,
+       master->dma_tx = dma_request_slave_channel_compat(mask,
                                pdata->dma_filter, pdata->tx_param, dev, "tx");
-       if (!drv_data->tx_chan)
+       if (!master->dma_tx)
                return -ENODEV;
 
-       drv_data->rx_chan = dma_request_slave_channel_compat(mask,
+       master->dma_rx = dma_request_slave_channel_compat(mask,
                                pdata->dma_filter, pdata->rx_param, dev, "rx");
-       if (!drv_data->rx_chan) {
-               dma_release_channel(drv_data->tx_chan);
-               drv_data->tx_chan = NULL;
+       if (!master->dma_rx) {
+               dma_release_channel(master->dma_tx);
+               master->dma_tx = NULL;
                return -ENODEV;
        }
 
@@ -326,17 +214,17 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
 
 void pxa2xx_spi_dma_release(struct driver_data *drv_data)
 {
-       if (drv_data->rx_chan) {
-               dmaengine_terminate_sync(drv_data->rx_chan);
-               dma_release_channel(drv_data->rx_chan);
-               sg_free_table(&drv_data->rx_sgt);
-               drv_data->rx_chan = NULL;
+       struct spi_master *master = drv_data->master;
+
+       if (master->dma_rx) {
+               dmaengine_terminate_sync(master->dma_rx);
+               dma_release_channel(master->dma_rx);
+               master->dma_rx = NULL;
        }
-       if (drv_data->tx_chan) {
-               dmaengine_terminate_sync(drv_data->tx_chan);
-               dma_release_channel(drv_data->tx_chan);
-               sg_free_table(&drv_data->tx_sgt);
-               drv_data->tx_chan = NULL;
+       if (master->dma_tx) {
+               dmaengine_terminate_sync(master->dma_tx);
+               dma_release_channel(master->dma_tx);
+               master->dma_tx = NULL;
        }
 }
 
index 5202de94f792c4bf8e38bf0d6c1da94586ae26f9..f3df522db93bac9fec31dc5f27ebcdddda57c87a 100644 (file)
@@ -1,24 +1,26 @@
 /*
  * CE4100's SPI device is more or less the same one as found on PXA
  *
+ * Copyright (C) 2016, Intel Corporation
  */
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
-#include <linux/of_device.h>
-#include <linux/module.h>
 #include <linux/spi/pxa2xx_spi.h>
-#include <linux/clk-provider.h>
 
 #include <linux/dmaengine.h>
 #include <linux/platform_data/dma-dw.h>
 
 enum {
-       PORT_CE4100,
+       PORT_QUARK_X1000,
        PORT_BYT,
+       PORT_MRFLD,
        PORT_BSW0,
        PORT_BSW1,
        PORT_BSW2,
-       PORT_QUARK_X1000,
+       PORT_CE4100,
        PORT_LPT,
 };
 
@@ -29,8 +31,11 @@ struct pxa_spi_info {
        unsigned long max_clk_rate;
 
        /* DMA channel request parameters */
+       bool (*dma_filter)(struct dma_chan *chan, void *param);
        void *tx_param;
        void *rx_param;
+
+       int (*setup)(struct pci_dev *pdev, struct pxa_spi_info *c);
 };
 
 static struct dw_dma_slave byt_tx_param = { .dst_id = 0 };
@@ -57,6 +62,56 @@ static bool lpss_dma_filter(struct dma_chan *chan, void *param)
        return true;
 }
 
+static int lpss_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
+{
+       struct pci_dev *dma_dev;
+
+       c->num_chipselect = 1;
+       c->max_clk_rate = 50000000;
+
+       dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+
+       if (c->tx_param) {
+               struct dw_dma_slave *slave = c->tx_param;
+
+               slave->dma_dev = &dma_dev->dev;
+               slave->m_master = 0;
+               slave->p_master = 1;
+       }
+
+       if (c->rx_param) {
+               struct dw_dma_slave *slave = c->rx_param;
+
+               slave->dma_dev = &dma_dev->dev;
+               slave->m_master = 0;
+               slave->p_master = 1;
+       }
+
+       c->dma_filter = lpss_dma_filter;
+       return 0;
+}
+
+static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
+{
+       switch (PCI_FUNC(dev->devfn)) {
+       case 0:
+               c->port_id = 3;
+               c->num_chipselect = 1;
+               break;
+       case 1:
+               c->port_id = 5;
+               c->num_chipselect = 4;
+               break;
+       case 2:
+               c->port_id = 6;
+               c->num_chipselect = 1;
+               break;
+       default:
+               return -ENODEV;
+       }
+       return 0;
+}
+
 static struct pxa_spi_info spi_info_configs[] = {
        [PORT_CE4100] = {
                .type = PXA25x_SSP,
@@ -67,35 +122,36 @@ static struct pxa_spi_info spi_info_configs[] = {
        [PORT_BYT] = {
                .type = LPSS_BYT_SSP,
                .port_id = 0,
-               .num_chipselect = 1,
-               .max_clk_rate = 50000000,
+               .setup = lpss_spi_setup,
                .tx_param = &byt_tx_param,
                .rx_param = &byt_rx_param,
        },
        [PORT_BSW0] = {
-               .type = LPSS_BYT_SSP,
+               .type = LPSS_BSW_SSP,
                .port_id = 0,
-               .num_chipselect = 1,
-               .max_clk_rate = 50000000,
+               .setup = lpss_spi_setup,
                .tx_param = &bsw0_tx_param,
                .rx_param = &bsw0_rx_param,
        },
        [PORT_BSW1] = {
-               .type = LPSS_BYT_SSP,
+               .type = LPSS_BSW_SSP,
                .port_id = 1,
-               .num_chipselect = 1,
-               .max_clk_rate = 50000000,
+               .setup = lpss_spi_setup,
                .tx_param = &bsw1_tx_param,
                .rx_param = &bsw1_rx_param,
        },
        [PORT_BSW2] = {
-               .type = LPSS_BYT_SSP,
+               .type = LPSS_BSW_SSP,
                .port_id = 2,
-               .num_chipselect = 1,
-               .max_clk_rate = 50000000,
+               .setup = lpss_spi_setup,
                .tx_param = &bsw2_tx_param,
                .rx_param = &bsw2_rx_param,
        },
+       [PORT_MRFLD] = {
+               .type = PXA27x_SSP,
+               .max_clk_rate = 25000000,
+               .setup = mrfld_spi_setup,
+       },
        [PORT_QUARK_X1000] = {
                .type = QUARK_X1000_SSP,
                .port_id = -1,
@@ -105,8 +161,7 @@ static struct pxa_spi_info spi_info_configs[] = {
        [PORT_LPT] = {
                .type = LPSS_LPT_SSP,
                .port_id = 0,
-               .num_chipselect = 1,
-               .max_clk_rate = 50000000,
+               .setup = lpss_spi_setup,
                .tx_param = &lpt_tx_param,
                .rx_param = &lpt_rx_param,
        },
@@ -122,7 +177,6 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
        struct ssp_device *ssp;
        struct pxa_spi_info *c;
        char buf[40];
-       struct pci_dev *dma_dev;
 
        ret = pcim_enable_device(dev);
        if (ret)
@@ -133,30 +187,15 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
                return ret;
 
        c = &spi_info_configs[ent->driver_data];
-
-       memset(&spi_pdata, 0, sizeof(spi_pdata));
-       spi_pdata.num_chipselect = (c->num_chipselect > 0) ?
-                                       c->num_chipselect : dev->devfn;
-
-       dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
-
-       if (c->tx_param) {
-               struct dw_dma_slave *slave = c->tx_param;
-
-               slave->dma_dev = &dma_dev->dev;
-               slave->m_master = 0;
-               slave->p_master = 1;
+       if (c->setup) {
+               ret = c->setup(dev, c);
+               if (ret)
+                       return ret;
        }
 
-       if (c->rx_param) {
-               struct dw_dma_slave *slave = c->rx_param;
-
-               slave->dma_dev = &dma_dev->dev;
-               slave->m_master = 0;
-               slave->p_master = 1;
-       }
-
-       spi_pdata.dma_filter = lpss_dma_filter;
+       memset(&spi_pdata, 0, sizeof(spi_pdata));
+       spi_pdata.num_chipselect = (c->num_chipselect > 0) ? c->num_chipselect : dev->devfn;
+       spi_pdata.dma_filter = c->dma_filter;
        spi_pdata.tx_param = c->tx_param;
        spi_pdata.rx_param = c->rx_param;
        spi_pdata.enable_dma = c->rx_param && c->tx_param;
@@ -164,10 +203,6 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
        ssp = &spi_pdata.ssp;
        ssp->phys_base = pci_resource_start(dev, 0);
        ssp->mmio_base = pcim_iomap_table(dev)[0];
-       if (!ssp->mmio_base) {
-               dev_err(&dev->dev, "failed to ioremap() registers\n");
-               return -EIO;
-       }
        ssp->irq = dev->irq;
        ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn;
        ssp->type = c->type;
@@ -208,12 +243,13 @@ static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
 }
 
 static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
-       { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 },
        { PCI_VDEVICE(INTEL, 0x0935), PORT_QUARK_X1000 },
        { PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT },
+       { PCI_VDEVICE(INTEL, 0x1194), PORT_MRFLD },
        { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 },
        { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 },
        { PCI_VDEVICE(INTEL, 0x22ac), PORT_BSW2 },
+       { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 },
        { PCI_VDEVICE(INTEL, 0x9ce6), PORT_LPT },
        { },
 };
index fe07c0592b44c9eac5faf22409203392cdbc9e3a..87150a1049bdf4a79b4656042edaadad858f01ce 100644 (file)
@@ -585,7 +585,14 @@ static void reset_sccr1(struct driver_data *drv_data)
        u32 sccr1_reg;
 
        sccr1_reg = pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1;
-       sccr1_reg &= ~SSCR1_RFT;
+       switch (drv_data->ssp_type) {
+       case QUARK_X1000_SSP:
+               sccr1_reg &= ~QUARK_X1000_SSCR1_RFT;
+               break;
+       default:
+               sccr1_reg &= ~SSCR1_RFT;
+               break;
+       }
        sccr1_reg |= chip->threshold;
        pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg);
 }
@@ -912,9 +919,21 @@ static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
        return clk_div << 8;
 }
 
+static bool pxa2xx_spi_can_dma(struct spi_master *master,
+                              struct spi_device *spi,
+                              struct spi_transfer *xfer)
+{
+       struct chip_data *chip = spi_get_ctldata(spi);
+
+       return chip->enable_dma &&
+              xfer->len <= MAX_DMA_LEN &&
+              xfer->len >= chip->dma_burst_size;
+}
+
 static void pump_transfers(unsigned long data)
 {
        struct driver_data *drv_data = (struct driver_data *)data;
+       struct spi_master *master = drv_data->master;
        struct spi_message *message = NULL;
        struct spi_transfer *transfer = NULL;
        struct spi_transfer *previous = NULL;
@@ -928,6 +947,7 @@ static void pump_transfers(unsigned long data)
        u32 dma_burst = drv_data->cur_chip->dma_burst_size;
        u32 change_mask = pxa2xx_spi_get_ssrc1_change_mask(drv_data);
        int err;
+       int dma_mapped;
 
        /* Get current state information */
        message = drv_data->cur_msg;
@@ -962,7 +982,7 @@ static void pump_transfers(unsigned long data)
        }
 
        /* Check if we can DMA this transfer */
-       if (!pxa2xx_spi_dma_is_possible(transfer->len) && chip->enable_dma) {
+       if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
 
                /* reject already-mapped transfers; PIO won't always work */
                if (message->is_dma_mapped
@@ -1039,10 +1059,10 @@ static void pump_transfers(unsigned long data)
 
        message->state = RUNNING_STATE;
 
-       drv_data->dma_mapped = 0;
-       if (pxa2xx_spi_dma_is_possible(drv_data->len))
-               drv_data->dma_mapped = pxa2xx_spi_map_dma_buffers(drv_data);
-       if (drv_data->dma_mapped) {
+       dma_mapped = master->can_dma &&
+                    master->can_dma(master, message->spi, transfer) &&
+                    master->cur_msg_mapped;
+       if (dma_mapped) {
 
                /* Ensure we have the correct interrupt handler */
                drv_data->transfer_handler = pxa2xx_spi_dma_transfer;
@@ -1072,14 +1092,14 @@ static void pump_transfers(unsigned long data)
        cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits);
        if (!pxa25x_ssp_comp(drv_data))
                dev_dbg(&message->spi->dev, "%u Hz actual, %s\n",
-                       drv_data->master->max_speed_hz
+                       master->max_speed_hz
                                / (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)),
-                       drv_data->dma_mapped ? "DMA" : "PIO");
+                       dma_mapped ? "DMA" : "PIO");
        else
                dev_dbg(&message->spi->dev, "%u Hz actual, %s\n",
-                       drv_data->master->max_speed_hz / 2
+                       master->max_speed_hz / 2
                                / (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)),
-                       drv_data->dma_mapped ? "DMA" : "PIO");
+                       dma_mapped ? "DMA" : "PIO");
 
        if (is_lpss_ssp(drv_data)) {
                if ((pxa2xx_spi_read(drv_data, SSIRF) & 0xff)
@@ -1240,7 +1260,7 @@ static int setup(struct spi_device *spi)
                        chip->frm = spi->chip_select;
                } else
                        chip->gpio_cs = -1;
-               chip->enable_dma = 0;
+               chip->enable_dma = drv_data->master_info->enable_dma;
                chip->timeout = TIMOUT_DFLT;
        }
 
@@ -1259,17 +1279,9 @@ static int setup(struct spi_device *spi)
                        tx_hi_thres = chip_info->tx_hi_threshold;
                if (chip_info->rx_threshold)
                        rx_thres = chip_info->rx_threshold;
-               chip->enable_dma = drv_data->master_info->enable_dma;
                chip->dma_threshold = 0;
                if (chip_info->enable_loopback)
                        chip->cr1 = SSCR1_LBM;
-       } else if (ACPI_HANDLE(&spi->dev)) {
-               /*
-                * Slave devices enumerated from ACPI namespace don't
-                * usually have chip_info but we still might want to use
-                * DMA with them.
-                */
-               chip->enable_dma = drv_data->master_info->enable_dma;
        }
 
        chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres);
@@ -1389,6 +1401,9 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
        /* SPT-H */
        { PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP },
        { PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP },
+       /* KBL-H */
+       { PCI_VDEVICE(INTEL, 0xa2a9), LPSS_SPT_SSP },
+       { PCI_VDEVICE(INTEL, 0xa2aa), LPSS_SPT_SSP },
        /* BXT A-Step */
        { PCI_VDEVICE(INTEL, 0x0ac2), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x0ac4), LPSS_BXT_SSP },
@@ -1601,6 +1616,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
                if (status) {
                        dev_dbg(dev, "no DMA channels available, using PIO\n");
                        platform_info->enable_dma = false;
+               } else {
+                       master->can_dma = pxa2xx_spi_can_dma;
                }
        }
 
index e6b09000ff145f072f0b7e12aaf11a8eeba7624f..d217ad55cc124dfc147a71c258a604d39defffa5 100644 (file)
@@ -50,12 +50,6 @@ struct driver_data {
        struct tasklet_struct pump_transfers;
 
        /* DMA engine support */
-       struct dma_chan *rx_chan;
-       struct dma_chan *tx_chan;
-       struct sg_table rx_sgt;
-       struct sg_table tx_sgt;
-       int rx_nents;
-       int tx_nents;
        atomic_t dma_running;
 
        /* Current message transfer state info */
@@ -67,7 +61,6 @@ struct driver_data {
        void *tx_end;
        void *rx;
        void *rx_end;
-       int dma_mapped;
        u8 n_bytes;
        int (*write)(struct driver_data *drv_data);
        int (*read)(struct driver_data *drv_data);
@@ -145,8 +138,6 @@ extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data);
 #define MAX_DMA_LEN            SZ_64K
 #define DEFAULT_DMA_CR1                (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL)
 
-extern bool pxa2xx_spi_dma_is_possible(size_t len);
-extern int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data);
 extern irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data);
 extern int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst);
 extern void pxa2xx_spi_dma_start(struct driver_data *drv_data);
index 1026e180eed79019f0ec55d9ed5ba427ce71cefa..0f89c2169c244e433a36e7cc7e672d385d3c6560 100644 (file)
 /* sclk_out: spi master internal logic in rk3x can support 50Mhz */
 #define MAX_SCLK_OUT           50000000
 
+/*
+ * SPI_CTRLR1 is 16-bits, so we should support lengths of 0xffff + 1. However,
+ * the controller seems to hang when given 0x10000, so stick with this for now.
+ */
+#define ROCKCHIP_SPI_MAX_TRANLEN               0xffff
+
 enum rockchip_ssi_type {
        SSI_MOTO_SPI = 0,
        SSI_TI_SSP,
@@ -573,6 +579,11 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
        dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div);
 }
 
+static size_t rockchip_spi_max_transfer_size(struct spi_device *spi)
+{
+       return ROCKCHIP_SPI_MAX_TRANLEN;
+}
+
 static int rockchip_spi_transfer_one(
                struct spi_master *master,
                struct spi_device *spi,
@@ -589,6 +600,11 @@ static int rockchip_spi_transfer_one(
                return -EINVAL;
        }
 
+       if (xfer->len > ROCKCHIP_SPI_MAX_TRANLEN) {
+               dev_err(rs->dev, "Transfer is too long (%d)\n", xfer->len);
+               return -EINVAL;
+       }
+
        rs->speed = xfer->speed_hz;
        rs->bpw = xfer->bits_per_word;
        rs->n_bytes = rs->bpw >> 3;
@@ -730,6 +746,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
        master->prepare_message = rockchip_spi_prepare_message;
        master->unprepare_message = rockchip_spi_unprepare_message;
        master->transfer_one = rockchip_spi_transfer_one;
+       master->max_transfer_size = rockchip_spi_max_transfer_size;
        master->handle_err = rockchip_spi_handle_err;
 
        rs->dma_tx.ch = dma_request_chan(rs->dev, "tx");
@@ -894,9 +911,12 @@ static const struct dev_pm_ops rockchip_spi_pm = {
 };
 
 static const struct of_device_id rockchip_spi_dt_match[] = {
+       { .compatible = "rockchip,rk3036-spi", },
        { .compatible = "rockchip,rk3066-spi", },
        { .compatible = "rockchip,rk3188-spi", },
+       { .compatible = "rockchip,rk3228-spi", },
        { .compatible = "rockchip,rk3288-spi", },
+       { .compatible = "rockchip,rk3368-spi", },
        { .compatible = "rockchip,rk3399-spi", },
        { },
 };
index 5a76a50063b562362ff7023956977c81caf1f708..3c09e94cf827f63b20f9e53d4523cbdaeba7718d 100644 (file)
@@ -156,12 +156,14 @@ struct s3c64xx_spi_port_config {
        int     quirks;
        bool    high_speed;
        bool    clk_from_cmu;
+       bool    clk_ioclk;
 };
 
 /**
  * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
  * @clk: Pointer to the spi clock.
  * @src_clk: Pointer to the clock used to generate SPI signals.
+ * @ioclk: Pointer to the i/o clock between master and slave
  * @master: Pointer to the SPI Protocol master.
  * @cntrlr_info: Platform specific data for the controller this driver manages.
  * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
@@ -181,6 +183,7 @@ struct s3c64xx_spi_driver_data {
        void __iomem                    *regs;
        struct clk                      *clk;
        struct clk                      *src_clk;
+       struct clk                      *ioclk;
        struct platform_device          *pdev;
        struct spi_master               *master;
        struct s3c64xx_spi_info  *cntrlr_info;
@@ -310,44 +313,63 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
        dma_async_issue_pending(dma->ch);
 }
 
+static void s3c64xx_spi_set_cs(struct spi_device *spi, bool enable)
+{
+       struct s3c64xx_spi_driver_data *sdd =
+                                       spi_master_get_devdata(spi->master);
+
+       if (sdd->cntrlr_info->no_cs)
+               return;
+
+       if (enable) {
+               if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO)) {
+                       writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+               } else {
+                       u32 ssel = readl(sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+
+                       ssel |= (S3C64XX_SPI_SLAVE_AUTO |
+                                               S3C64XX_SPI_SLAVE_NSC_CNT_2);
+                       writel(ssel, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+               }
+       } else {
+               if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
+                       writel(S3C64XX_SPI_SLAVE_SIG_INACT,
+                              sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       }
+}
+
 static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
 {
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
        dma_filter_fn filter = sdd->cntrlr_info->filter;
        struct device *dev = &sdd->pdev->dev;
        dma_cap_mask_t mask;
-       int ret;
 
-       if (!is_polling(sdd)) {
-               dma_cap_zero(mask);
-               dma_cap_set(DMA_SLAVE, mask);
-
-               /* Acquire DMA channels */
-               sdd->rx_dma.ch = dma_request_slave_channel_compat(mask, filter,
-                                  sdd->cntrlr_info->dma_rx, dev, "rx");
-               if (!sdd->rx_dma.ch) {
-                       dev_err(dev, "Failed to get RX DMA channel\n");
-                       ret = -EBUSY;
-                       goto out;
-               }
-               spi->dma_rx = sdd->rx_dma.ch;
-
-               sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter,
-                                  sdd->cntrlr_info->dma_tx, dev, "tx");
-               if (!sdd->tx_dma.ch) {
-                       dev_err(dev, "Failed to get TX DMA channel\n");
-                       ret = -EBUSY;
-                       goto out_rx;
-               }
-               spi->dma_tx = sdd->tx_dma.ch;
+       if (is_polling(sdd))
+               return 0;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       /* Acquire DMA channels */
+       sdd->rx_dma.ch = dma_request_slave_channel_compat(mask, filter,
+                          sdd->cntrlr_info->dma_rx, dev, "rx");
+       if (!sdd->rx_dma.ch) {
+               dev_err(dev, "Failed to get RX DMA channel\n");
+               return -EBUSY;
        }
+       spi->dma_rx = sdd->rx_dma.ch;
 
-       return 0;
+       sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter,
+                          sdd->cntrlr_info->dma_tx, dev, "tx");
+       if (!sdd->tx_dma.ch) {
+               dev_err(dev, "Failed to get TX DMA channel\n");
+               dma_release_channel(sdd->rx_dma.ch);
+               return -EBUSY;
+       }
+       spi->dma_tx = sdd->tx_dma.ch;
 
-out_rx:
-       dma_release_channel(sdd->rx_dma.ch);
-out:
-       return ret;
+       return 0;
 }
 
 static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
@@ -577,9 +599,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
        u32 val;
 
        /* Disable Clock */
-       if (sdd->port_conf->clk_from_cmu) {
-               clk_disable_unprepare(sdd->src_clk);
-       } else {
+       if (!sdd->port_conf->clk_from_cmu) {
                val = readl(regs + S3C64XX_SPI_CLK_CFG);
                val &= ~S3C64XX_SPI_ENCLK_ENABLE;
                writel(val, regs + S3C64XX_SPI_CLK_CFG);
@@ -622,11 +642,8 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
        writel(val, regs + S3C64XX_SPI_MODE_CFG);
 
        if (sdd->port_conf->clk_from_cmu) {
-               /* Configure Clock */
-               /* There is half-multiplier before the SPI */
+               /* The src_clk clock is divided internally by 2 */
                clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
-               /* Enable Clock */
-               clk_prepare_enable(sdd->src_clk);
        } else {
                /* Configure Clock */
                val = readl(regs + S3C64XX_SPI_CLK_CFG);
@@ -651,16 +668,6 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,
        struct spi_device *spi = msg->spi;
        struct s3c64xx_spi_csinfo *cs = spi->controller_data;
 
-       /* If Master's(controller) state differs from that needed by Slave */
-       if (sdd->cur_speed != spi->max_speed_hz
-                       || sdd->cur_mode != spi->mode
-                       || sdd->cur_bpw != spi->bits_per_word) {
-               sdd->cur_bpw = spi->bits_per_word;
-               sdd->cur_speed = spi->max_speed_hz;
-               sdd->cur_mode = spi->mode;
-               s3c64xx_spi_config(sdd);
-       }
-
        /* Configure feedback delay */
        writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
 
@@ -687,6 +694,7 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
        if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
                sdd->cur_bpw = bpw;
                sdd->cur_speed = speed;
+               sdd->cur_mode = spi->mode;
                s3c64xx_spi_config(sdd);
        }
 
@@ -706,12 +714,7 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
        enable_datapath(sdd, spi, xfer, use_dma);
 
        /* Start the signals */
-       if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
-               writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
-       else
-               writel(readl(sdd->regs + S3C64XX_SPI_SLAVE_SEL)
-                       | S3C64XX_SPI_SLAVE_AUTO | S3C64XX_SPI_SLAVE_NSC_CNT_2,
-                       sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       s3c64xx_spi_set_cs(spi, true);
 
        spin_unlock_irqrestore(&sdd->lock, flags);
 
@@ -861,16 +864,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
 
        pm_runtime_mark_last_busy(&sdd->pdev->dev);
        pm_runtime_put_autosuspend(&sdd->pdev->dev);
-       if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
-               writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       s3c64xx_spi_set_cs(spi, false);
+
        return 0;
 
 setup_exit:
        pm_runtime_mark_last_busy(&sdd->pdev->dev);
        pm_runtime_put_autosuspend(&sdd->pdev->dev);
        /* setup() returns with device de-selected */
-       if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
-               writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       s3c64xx_spi_set_cs(spi, false);
 
        if (gpio_is_valid(spi->cs_gpio))
                gpio_free(spi->cs_gpio);
@@ -944,7 +946,9 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
 
        sdd->cur_speed = 0;
 
-       if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
+       if (sci->no_cs)
+               writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+       else if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
                writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
        /* Disable Interrupts - we use Polling if not DMA mode */
@@ -999,6 +1003,8 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
                sci->num_cs = temp;
        }
 
+       sci->no_cs = of_property_read_bool(dev->of_node, "broken-cs");
+
        return sci;
 }
 #else
@@ -1076,7 +1082,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
                if (ret < 0) {
                        dev_err(&pdev->dev, "failed to get alias id, errno %d\n",
                                ret);
-                       goto err0;
+                       goto err_deref_master;
                }
                sdd->port_id = ret;
        } else {
@@ -1114,13 +1120,13 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res);
        if (IS_ERR(sdd->regs)) {
                ret = PTR_ERR(sdd->regs);
-               goto err0;
+               goto err_deref_master;
        }
 
        if (sci->cfg_gpio && sci->cfg_gpio()) {
                dev_err(&pdev->dev, "Unable to config gpio\n");
                ret = -EBUSY;
-               goto err0;
+               goto err_deref_master;
        }
 
        /* Setup clocks */
@@ -1128,13 +1134,13 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        if (IS_ERR(sdd->clk)) {
                dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
                ret = PTR_ERR(sdd->clk);
-               goto err0;
+               goto err_deref_master;
        }
 
-       if (clk_prepare_enable(sdd->clk)) {
+       ret = clk_prepare_enable(sdd->clk);
+       if (ret) {
                dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
-               ret = -EBUSY;
-               goto err0;
+               goto err_deref_master;
        }
 
        sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr);
@@ -1143,13 +1149,28 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
                dev_err(&pdev->dev,
                        "Unable to acquire clock '%s'\n", clk_name);
                ret = PTR_ERR(sdd->src_clk);
-               goto err2;
+               goto err_disable_clk;
        }
 
-       if (clk_prepare_enable(sdd->src_clk)) {
+       ret = clk_prepare_enable(sdd->src_clk);
+       if (ret) {
                dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
-               ret = -EBUSY;
-               goto err2;
+               goto err_disable_clk;
+       }
+
+       if (sdd->port_conf->clk_ioclk) {
+               sdd->ioclk = devm_clk_get(&pdev->dev, "spi_ioclk");
+               if (IS_ERR(sdd->ioclk)) {
+                       dev_err(&pdev->dev, "Unable to acquire 'ioclk'\n");
+                       ret = PTR_ERR(sdd->ioclk);
+                       goto err_disable_src_clk;
+               }
+
+               ret = clk_prepare_enable(sdd->ioclk);
+               if (ret) {
+                       dev_err(&pdev->dev, "Couldn't enable clock 'ioclk'\n");
+                       goto err_disable_src_clk;
+               }
        }
 
        pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
@@ -1169,7 +1190,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n",
                        irq, ret);
-               goto err3;
+               goto err_pm_put;
        }
 
        writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN |
@@ -1179,7 +1200,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        ret = devm_spi_register_master(&pdev->dev, master);
        if (ret != 0) {
                dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret);
-               goto err3;
+               goto err_pm_put;
        }
 
        dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n",
@@ -1193,15 +1214,17 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 
        return 0;
 
-err3:
+err_pm_put:
        pm_runtime_put_noidle(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        pm_runtime_set_suspended(&pdev->dev);
 
+       clk_disable_unprepare(sdd->ioclk);
+err_disable_src_clk:
        clk_disable_unprepare(sdd->src_clk);
-err2:
+err_disable_clk:
        clk_disable_unprepare(sdd->clk);
-err0:
+err_deref_master:
        spi_master_put(master);
 
        return ret;
@@ -1209,13 +1232,15 @@ err0:
 
 static int s3c64xx_spi_remove(struct platform_device *pdev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct spi_master *master = platform_get_drvdata(pdev);
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
        pm_runtime_get_sync(&pdev->dev);
 
        writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
 
+       clk_disable_unprepare(sdd->ioclk);
+
        clk_disable_unprepare(sdd->src_clk);
 
        clk_disable_unprepare(sdd->clk);
@@ -1274,6 +1299,7 @@ static int s3c64xx_spi_runtime_suspend(struct device *dev)
 
        clk_disable_unprepare(sdd->clk);
        clk_disable_unprepare(sdd->src_clk);
+       clk_disable_unprepare(sdd->ioclk);
 
        return 0;
 }
@@ -1284,17 +1310,28 @@ static int s3c64xx_spi_runtime_resume(struct device *dev)
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
        int ret;
 
+       if (sdd->port_conf->clk_ioclk) {
+               ret = clk_prepare_enable(sdd->ioclk);
+               if (ret != 0)
+                       return ret;
+       }
+
        ret = clk_prepare_enable(sdd->src_clk);
        if (ret != 0)
-               return ret;
+               goto err_disable_ioclk;
 
        ret = clk_prepare_enable(sdd->clk);
-       if (ret != 0) {
-               clk_disable_unprepare(sdd->src_clk);
-               return ret;
-       }
+       if (ret != 0)
+               goto err_disable_src_clk;
 
        return 0;
+
+err_disable_src_clk:
+       clk_disable_unprepare(sdd->src_clk);
+err_disable_ioclk:
+       clk_disable_unprepare(sdd->ioclk);
+
+       return ret;
 }
 #endif /* CONFIG_PM */
 
@@ -1350,6 +1387,16 @@ static struct s3c64xx_spi_port_config exynos7_spi_port_config = {
        .quirks         = S3C64XX_SPI_QUIRK_CS_AUTO,
 };
 
+static struct s3c64xx_spi_port_config exynos5433_spi_port_config = {
+       .fifo_lvl_mask  = { 0x1ff, 0x7f, 0x7f, 0x7f, 0x7f, 0x1ff},
+       .rx_lvl_offset  = 15,
+       .tx_st_done     = 25,
+       .high_speed     = true,
+       .clk_from_cmu   = true,
+       .clk_ioclk      = true,
+       .quirks         = S3C64XX_SPI_QUIRK_CS_AUTO,
+};
+
 static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
        {
                .name           = "s3c2443-spi",
@@ -1380,6 +1427,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = {
        { .compatible = "samsung,exynos7-spi",
                        .data = (void *)&exynos7_spi_port_config,
        },
+       { .compatible = "samsung,exynos5433-spi",
+                       .data = (void *)&exynos5433_spi_port_config,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match);
index a7934ab00b96505f3753fa38266238f3abcc6f64..0f83ad1d5a5858dd6ff808773fe359479a54b796 100644 (file)
@@ -45,7 +45,6 @@ struct sh_msiof_spi_priv {
        void __iomem *mapbase;
        struct clk *clk;
        struct platform_device *pdev;
-       const struct sh_msiof_chipdata *chipdata;
        struct sh_msiof_spi_info *info;
        struct completion done;
        unsigned int tx_fifo_size;
@@ -271,7 +270,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
 
        scr = sh_msiof_spi_div_table[k].brdv | SCR_BRPS(brps);
        sh_msiof_write(p, TSCR, scr);
-       if (!(p->chipdata->master_flags & SPI_MASTER_MUST_TX))
+       if (!(p->master->flags & SPI_MASTER_MUST_TX))
                sh_msiof_write(p, RSCR, scr);
 }
 
@@ -336,7 +335,7 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
        tmp |= lsb_first << MDR1_BITLSB_SHIFT;
        tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p);
        sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON);
-       if (p->chipdata->master_flags & SPI_MASTER_MUST_TX) {
+       if (p->master->flags & SPI_MASTER_MUST_TX) {
                /* These bits are reserved if RX needs TX */
                tmp &= ~0x0000ffff;
        }
@@ -360,7 +359,7 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
 {
        u32 dr2 = MDR2_BITLEN1(bits) | MDR2_WDLEN1(words);
 
-       if (tx_buf || (p->chipdata->master_flags & SPI_MASTER_MUST_TX))
+       if (tx_buf || (p->master->flags & SPI_MASTER_MUST_TX))
                sh_msiof_write(p, TMDR2, dr2);
        else
                sh_msiof_write(p, TMDR2, dr2 | MDR2_GRPMASK1);
@@ -1152,6 +1151,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 {
        struct resource *r;
        struct spi_master *master;
+       const struct sh_msiof_chipdata *chipdata;
        const struct of_device_id *of_id;
        struct sh_msiof_spi_priv *p;
        int i;
@@ -1170,10 +1170,10 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 
        of_id = of_match_device(sh_msiof_match, &pdev->dev);
        if (of_id) {
-               p->chipdata = of_id->data;
+               chipdata = of_id->data;
                p->info = sh_msiof_spi_parse_dt(&pdev->dev);
        } else {
-               p->chipdata = (const void *)pdev->id_entry->driver_data;
+               chipdata = (const void *)pdev->id_entry->driver_data;
                p->info = dev_get_platdata(&pdev->dev);
        }
 
@@ -1217,8 +1217,8 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
 
        /* Platform data may override FIFO sizes */
-       p->tx_fifo_size = p->chipdata->tx_fifo_size;
-       p->rx_fifo_size = p->chipdata->rx_fifo_size;
+       p->tx_fifo_size = chipdata->tx_fifo_size;
+       p->rx_fifo_size = chipdata->rx_fifo_size;
        if (p->info->tx_fifo_override)
                p->tx_fifo_size = p->info->tx_fifo_override;
        if (p->info->rx_fifo_override)
@@ -1227,7 +1227,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
        /* init master code */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
        master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
-       master->flags = p->chipdata->master_flags;
+       master->flags = chipdata->master_flags;
        master->bus_num = pdev->id;
        master->dev.of_node = pdev->dev.of_node;
        master->num_chipselect = p->info->num_chipselect;
index 502501187c9e839ea1222bbffedf5e57acb17a6a..2bf53f0e27d9e0fe7bb179c2d3a143c012010a55 100644 (file)
@@ -82,7 +82,6 @@ struct spi_sh_data {
        int irq;
        struct spi_master *master;
        struct list_head queue;
-       struct workqueue_struct *workqueue;
        struct work_struct ws;
        unsigned long cr1;
        wait_queue_head_t wait;
@@ -380,7 +379,7 @@ static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg)
        spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
 
        list_add_tail(&mesg->queue, &ss->queue);
-       queue_work(ss->workqueue, &ss->ws);
+       schedule_work(&ss->ws);
 
        spin_unlock_irqrestore(&ss->lock, flags);
 
@@ -425,7 +424,7 @@ static int spi_sh_remove(struct platform_device *pdev)
        struct spi_sh_data *ss = platform_get_drvdata(pdev);
 
        spi_unregister_master(ss->master);
-       destroy_workqueue(ss->workqueue);
+       flush_work(&ss->ws);
        free_irq(ss->irq, ss);
 
        return 0;
@@ -484,18 +483,11 @@ static int spi_sh_probe(struct platform_device *pdev)
        spin_lock_init(&ss->lock);
        INIT_WORK(&ss->ws, spi_sh_work);
        init_waitqueue_head(&ss->wait);
-       ss->workqueue = create_singlethread_workqueue(
-                                       dev_name(master->dev.parent));
-       if (ss->workqueue == NULL) {
-               dev_err(&pdev->dev, "create workqueue error\n");
-               ret = -EBUSY;
-               goto error1;
-       }
 
        ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss);
        if (ret < 0) {
                dev_err(&pdev->dev, "request_irq error\n");
-               goto error2;
+               goto error1;
        }
 
        master->num_chipselect = 2;
@@ -514,8 +506,6 @@ static int spi_sh_probe(struct platform_device *pdev)
 
  error3:
        free_irq(irq, ss);
- error2:
-       destroy_workqueue(ss->workqueue);
  error1:
        spi_master_put(master);
 
index cf007f3b83ec92f1d8f976ea2b68978dbdd36f20..4969dc10684a4c48135a12e46823be3afc7c5c56 100644 (file)
@@ -167,6 +167,11 @@ static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
        sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
 }
 
+static size_t sun4i_spi_max_transfer_size(struct spi_device *spi)
+{
+       return SUN4I_FIFO_DEPTH - 1;
+}
+
 static int sun4i_spi_transfer_one(struct spi_master *master,
                                  struct spi_device *spi,
                                  struct spi_transfer *tfr)
@@ -402,6 +407,8 @@ static int sun4i_spi_probe(struct platform_device *pdev)
        }
 
        sspi->master = master;
+       master->max_speed_hz = 100 * 1000 * 1000;
+       master->min_speed_hz = 3 * 1000;
        master->set_cs = sun4i_spi_set_cs;
        master->transfer_one = sun4i_spi_transfer_one;
        master->num_chipselect = 4;
@@ -409,6 +416,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->dev.of_node = pdev->dev.of_node;
        master->auto_runtime_pm = true;
+       master->max_transfer_size = sun4i_spi_max_transfer_size;
 
        sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(sspi->hclk)) {
index 7fce79a60608873d42af3b4b5203b4a94942ade1..9918a57a6a6e643456d95dfaf53a6d85e428cbac 100644 (file)
@@ -153,6 +153,10 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
        sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
 }
 
+static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
+{
+       return SUN6I_FIFO_DEPTH - 1;
+}
 
 static int sun6i_spi_transfer_one(struct spi_master *master,
                                  struct spi_device *spi,
@@ -394,6 +398,8 @@ static int sun6i_spi_probe(struct platform_device *pdev)
        }
 
        sspi->master = master;
+       master->max_speed_hz = 100 * 1000 * 1000;
+       master->min_speed_hz = 3 * 1000;
        master->set_cs = sun6i_spi_set_cs;
        master->transfer_one = sun6i_spi_transfer_one;
        master->num_chipselect = 4;
@@ -401,6 +407,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->dev.of_node = pdev->dev.of_node;
        master->auto_runtime_pm = true;
+       master->max_transfer_size = sun6i_spi_max_transfer_size;
 
        sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(sspi->hclk)) {
index 29ea8d2f982498c4290e4afc15093165656e7897..ac0b072815a34d44727978cfead5ec01d6a96b67 100644 (file)
@@ -141,7 +141,7 @@ static int ti_qspi_setup(struct spi_device *spi)
        u32 clk_ctrl_reg, clk_rate, clk_mask;
 
        if (spi->master->busy) {
-               dev_dbg(qspi->dev, "master busy doing other trasnfers\n");
+               dev_dbg(qspi->dev, "master busy doing other transfers\n");
                return -EBUSY;
        }
 
index 93dfcee0f987b705be1329893c950ad19989ccd8..c54ee667447101abd8957bdc2c976c174d137d4c 100644 (file)
@@ -133,8 +133,6 @@ struct pch_spi_dma_ctrl {
  * @io_remap_addr:             The remapped PCI base address
  * @master:                    Pointer to the SPI master structure
  * @work:                      Reference to work queue handler
- * @wk:                                Workqueue for carrying out execution of the
- *                             requests
  * @wait:                      Wait queue for waking up upon receiving an
  *                             interrupt.
  * @transfer_complete:         Status of SPI Transfer
@@ -169,7 +167,6 @@ struct pch_spi_data {
        unsigned long io_base_addr;
        struct spi_master *master;
        struct work_struct work;
-       struct workqueue_struct *wk;
        wait_queue_head_t wait;
        u8 transfer_complete;
        u8 bcurrent_msg_processing;
@@ -517,8 +514,7 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
 
        dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
 
-       /* schedule work queue to run */
-       queue_work(data->wk, &data->work);
+       schedule_work(&data->work);
        dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__);
 
        retval = 0;
@@ -674,7 +670,7 @@ static void pch_spi_nomore_transfer(struct pch_spi_data *data)
                 *more messages)
                 */
                dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__);
-               queue_work(data->wk, &data->work);
+               schedule_work(&data->work);
        } else if (data->board_dat->suspend_sts ||
                   data->status == STATUS_EXITING) {
                dev_dbg(&data->master->dev,
@@ -1266,14 +1262,7 @@ static void pch_spi_free_resources(struct pch_spi_board_data *board_dat,
 {
        dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
 
-       /* free workqueue */
-       if (data->wk != NULL) {
-               destroy_workqueue(data->wk);
-               data->wk = NULL;
-               dev_dbg(&board_dat->pdev->dev,
-                       "%s destroy_workqueue invoked successfully\n",
-                       __func__);
-       }
+       flush_work(&data->work);
 }
 
 static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
@@ -1283,14 +1272,6 @@ static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
 
        dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
 
-       /* create workqueue */
-       data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
-       if (!data->wk) {
-               dev_err(&board_dat->pdev->dev,
-                       "%s create_singlet hread_workqueue failed\n", __func__);
-               retval = -EBUSY;
-               goto err_return;
-       }
 
        /* reset PCH SPI h/w */
        pch_spi_reset(data->master);
@@ -1299,7 +1280,6 @@ static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
 
        dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
 
-err_return:
        if (retval != 0) {
                dev_err(&board_dat->pdev->dev,
                        "%s FAIL:invoking pch_spi_free_resources\n", __func__);
index d69f8f8f3fa698d1eb34c744ea25e0058035ad82..7492ea346b43ed5bcbe89c04d71319d94e31dc14 100644 (file)
@@ -72,7 +72,6 @@
 
 
 struct txx9spi {
-       struct workqueue_struct *workqueue;
        struct work_struct work;
        spinlock_t lock;        /* protect 'queue' */
        struct list_head queue;
@@ -315,7 +314,7 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
 
        spin_lock_irqsave(&c->lock, flags);
        list_add_tail(&m->queue, &c->queue);
-       queue_work(c->workqueue, &c->work);
+       schedule_work(&c->work);
        spin_unlock_irqrestore(&c->lock, flags);
 
        return 0;
@@ -374,10 +373,6 @@ static int txx9spi_probe(struct platform_device *dev)
        if (ret)
                goto exit;
 
-       c->workqueue = create_singlethread_workqueue(
-                               dev_name(master->dev.parent));
-       if (!c->workqueue)
-               goto exit_busy;
        c->last_chipselect = -1;
 
        dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
@@ -400,8 +395,6 @@ static int txx9spi_probe(struct platform_device *dev)
 exit_busy:
        ret = -EBUSY;
 exit:
-       if (c->workqueue)
-               destroy_workqueue(c->workqueue);
        clk_disable(c->clk);
        spi_master_put(master);
        return ret;
@@ -412,7 +405,7 @@ static int txx9spi_remove(struct platform_device *dev)
        struct spi_master *master = platform_get_drvdata(dev);
        struct txx9spi *c = spi_master_get_devdata(master);
 
-       destroy_workqueue(c->workqueue);
+       flush_work(&c->work);
        clk_disable(c->clk);
        return 0;
 }
index 3009121173cdbc9ad1a0537a4cf19a029ceb86b8..bc7100b93dfcf0c24213f479f9a5fffc41666315 100644 (file)
@@ -341,9 +341,10 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
 
        if (ipif_isr & XSPI_INTR_TX_EMPTY) {    /* Transmission completed */
                complete(&xspi->done);
+               return IRQ_HANDLED;
        }
 
-       return IRQ_HANDLED;
+       return IRQ_NONE;
 }
 
 static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi)
@@ -455,7 +456,10 @@ static int xilinx_spi_probe(struct platform_device *pdev)
        xspi->buffer_size = xilinx_spi_find_buffer_size(xspi);
 
        xspi->irq = platform_get_irq(pdev, 0);
-       if (xspi->irq >= 0) {
+       if (xspi->irq < 0 && xspi->irq != -ENXIO) {
+               ret = xspi->irq;
+               goto put_master;
+       } else if (xspi->irq >= 0) {
                /* Register for SPI Interrupt */
                ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
                                dev_name(&pdev->dev), xspi);
index 7589c8af4368a7c2c4558531d216a332003f8102..51ad42fad567913339ab8d9deaf531b779865a87 100644 (file)
@@ -851,6 +851,20 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
        return 0;
 }
 #else /* !CONFIG_HAS_DMA */
+static inline int spi_map_buf(struct spi_master *master,
+                             struct device *dev, struct sg_table *sgt,
+                             void *buf, size_t len,
+                             enum dma_data_direction dir)
+{
+       return -EINVAL;
+}
+
+static inline void spi_unmap_buf(struct spi_master *master,
+                                struct device *dev, struct sg_table *sgt,
+                                enum dma_data_direction dir)
+{
+}
+
 static inline int __spi_map_msg(struct spi_master *master,
                                struct spi_message *msg)
 {
@@ -1057,7 +1071,6 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
  * __spi_pump_messages - function which processes spi message queue
  * @master: master to process queue for
  * @in_kthread: true if we are in the context of the message pump thread
- * @bus_locked: true if the bus mutex is held when calling this function
  *
  * This function checks if there is any spi message in the queue that
  * needs processing and if so call out to the driver to initialize hardware
@@ -1067,8 +1080,7 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
  * inside spi_sync(); the queue extraction handling at the top of the
  * function should deal with this safely.
  */
-static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
-                               bool bus_locked)
+static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
 {
        unsigned long flags;
        bool was_busy = false;
@@ -1140,6 +1152,8 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
                master->busy = true;
        spin_unlock_irqrestore(&master->queue_lock, flags);
 
+       mutex_lock(&master->io_mutex);
+
        if (!was_busy && master->auto_runtime_pm) {
                ret = pm_runtime_get_sync(master->dev.parent);
                if (ret < 0) {
@@ -1164,9 +1178,6 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
                }
        }
 
-       if (!bus_locked)
-               mutex_lock(&master->bus_lock_mutex);
-
        trace_spi_message_start(master->cur_msg);
 
        if (master->prepare_message) {
@@ -1196,8 +1207,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
        }
 
 out:
-       if (!bus_locked)
-               mutex_unlock(&master->bus_lock_mutex);
+       mutex_unlock(&master->io_mutex);
 
        /* Prod the scheduler in case transfer_one() was busy waiting */
        if (!ret)
@@ -1213,7 +1223,7 @@ static void spi_pump_messages(struct kthread_work *work)
        struct spi_master *master =
                container_of(work, struct spi_master, pump_messages);
 
-       __spi_pump_messages(master, true, master->bus_lock_flag);
+       __spi_pump_messages(master, true);
 }
 
 static int spi_init_queue(struct spi_master *master)
@@ -1886,6 +1896,7 @@ int spi_register_master(struct spi_master *master)
        spin_lock_init(&master->queue_lock);
        spin_lock_init(&master->bus_lock_spinlock);
        mutex_init(&master->bus_lock_mutex);
+       mutex_init(&master->io_mutex);
        master->bus_lock_flag = 0;
        init_completion(&master->xfer_completion);
        if (!master->max_dma_len)
@@ -2738,6 +2749,7 @@ int spi_flash_read(struct spi_device *spi,
 
 {
        struct spi_master *master = spi->master;
+       struct device *rx_dev = NULL;
        int ret;
 
        if ((msg->opcode_nbits == SPI_NBITS_DUAL ||
@@ -2763,9 +2775,24 @@ int spi_flash_read(struct spi_device *spi,
                        return ret;
                }
        }
+
        mutex_lock(&master->bus_lock_mutex);
+       mutex_lock(&master->io_mutex);
+       if (master->dma_rx) {
+               rx_dev = master->dma_rx->device->dev;
+               ret = spi_map_buf(master, rx_dev, &msg->rx_sg,
+                                 msg->buf, msg->len,
+                                 DMA_FROM_DEVICE);
+               if (!ret)
+                       msg->cur_msg_mapped = true;
+       }
        ret = master->spi_flash_read(spi, msg);
+       if (msg->cur_msg_mapped)
+               spi_unmap_buf(master, rx_dev, &msg->rx_sg,
+                             DMA_FROM_DEVICE);
+       mutex_unlock(&master->io_mutex);
        mutex_unlock(&master->bus_lock_mutex);
+
        if (master->auto_runtime_pm)
                pm_runtime_put(master->dev.parent);
 
@@ -2785,8 +2812,7 @@ static void spi_complete(void *arg)
        complete(arg);
 }
 
-static int __spi_sync(struct spi_device *spi, struct spi_message *message,
-                     int bus_locked)
+static int __spi_sync(struct spi_device *spi, struct spi_message *message)
 {
        DECLARE_COMPLETION_ONSTACK(done);
        int status;
@@ -2804,9 +2830,6 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
        SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_sync);
        SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_sync);
 
-       if (!bus_locked)
-               mutex_lock(&master->bus_lock_mutex);
-
        /* If we're not using the legacy transfer method then we will
         * try to transfer in the calling context so special case.
         * This code would be less tricky if we could remove the
@@ -2824,9 +2847,6 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
                status = spi_async_locked(spi, message);
        }
 
-       if (!bus_locked)
-               mutex_unlock(&master->bus_lock_mutex);
-
        if (status == 0) {
                /* Push out the messages in the calling context if we
                 * can.
@@ -2836,7 +2856,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
                                                       spi_sync_immediate);
                        SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics,
                                                       spi_sync_immediate);
-                       __spi_pump_messages(master, false, bus_locked);
+                       __spi_pump_messages(master, false);
                }
 
                wait_for_completion(&done);
@@ -2869,7 +2889,13 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
  */
 int spi_sync(struct spi_device *spi, struct spi_message *message)
 {
-       return __spi_sync(spi, message, spi->master->bus_lock_flag);
+       int ret;
+
+       mutex_lock(&spi->master->bus_lock_mutex);
+       ret = __spi_sync(spi, message);
+       mutex_unlock(&spi->master->bus_lock_mutex);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(spi_sync);
 
@@ -2891,7 +2917,7 @@ EXPORT_SYMBOL_GPL(spi_sync);
  */
 int spi_sync_locked(struct spi_device *spi, struct spi_message *message)
 {
-       return __spi_sync(spi, message, 1);
+       return __spi_sync(spi, message);
 }
 EXPORT_SYMBOL_GPL(spi_sync_locked);
 
index e3c19f30f591115a823467033702ff1b232c5ebc..2e05046f866bd01bf87edcdeff0d5b76d4d0aea7 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/compat.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/acpi.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spidev.h>
@@ -700,6 +701,43 @@ static const struct of_device_id spidev_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, spidev_dt_ids);
 #endif
 
+#ifdef CONFIG_ACPI
+
+/* Dummy SPI devices not to be used in production systems */
+#define SPIDEV_ACPI_DUMMY      1
+
+static const struct acpi_device_id spidev_acpi_ids[] = {
+       /*
+        * The ACPI SPT000* devices are only meant for development and
+        * testing. Systems used in production should have a proper ACPI
+        * description of the connected peripheral and they should also use
+        * a proper driver instead of poking directly to the SPI bus.
+        */
+       { "SPT0001", SPIDEV_ACPI_DUMMY },
+       { "SPT0002", SPIDEV_ACPI_DUMMY },
+       { "SPT0003", SPIDEV_ACPI_DUMMY },
+       {},
+};
+MODULE_DEVICE_TABLE(acpi, spidev_acpi_ids);
+
+static void spidev_probe_acpi(struct spi_device *spi)
+{
+       const struct acpi_device_id *id;
+
+       if (!has_acpi_companion(&spi->dev))
+               return;
+
+       id = acpi_match_device(spidev_acpi_ids, &spi->dev);
+       if (WARN_ON(!id))
+               return;
+
+       if (id->driver_data == SPIDEV_ACPI_DUMMY)
+               dev_warn(&spi->dev, "do not use this driver in production systems!\n");
+}
+#else
+static inline void spidev_probe_acpi(struct spi_device *spi) {}
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int spidev_probe(struct spi_device *spi)
@@ -719,6 +757,8 @@ static int spidev_probe(struct spi_device *spi)
                        !of_match_device(spidev_dt_ids, &spi->dev));
        }
 
+       spidev_probe_acpi(spi);
+
        /* Allocate driver data */
        spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
        if (!spidev)
@@ -789,6 +829,7 @@ static struct spi_driver spidev_spi_driver = {
        .driver = {
                .name =         "spidev",
                .of_match_table = of_match_ptr(spidev_dt_ids),
+               .acpi_match_table = ACPI_PTR(spidev_acpi_ids),
        },
        .probe =        spidev_probe,
        .remove =       spidev_remove,
index fb5625bcca9a5b73895eac8d38d9cc3864610898..5c1e21c8727080d40ac03fe3af96b3e2f5a5e9c1 100644 (file)
@@ -38,6 +38,7 @@ struct s3c64xx_spi_csinfo {
 struct s3c64xx_spi_info {
        int src_clk_nr;
        int num_cs;
+       bool no_cs;
        int (*cfg_gpio)(void);
        dma_filter_fn filter;
        void *dma_tx;
index 1f03483f61e5714b1c07708fee2fe3d7ffa946e3..072cb2aa24139981b0459eaa8f01d28406b384b4 100644 (file)
@@ -312,8 +312,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @flags: other constraints relevant to this driver
  * @max_transfer_size: function that returns the max transfer size for
  *     a &spi_device; may be %NULL, so the default %SIZE_MAX will be used.
+ * @io_mutex: mutex for physical bus access
  * @bus_lock_spinlock: spinlock for SPI bus locking
- * @bus_lock_mutex: mutex for SPI bus locking
+ * @bus_lock_mutex: mutex for exclusion of multiple callers
  * @bus_lock_flag: indicates that the SPI bus is locked for exclusive use
  * @setup: updates the device mode and clocking records used by a
  *     device's SPI controller; protocol code may call this.  This
@@ -446,6 +447,9 @@ struct spi_master {
         */
        size_t (*max_transfer_size)(struct spi_device *spi);
 
+       /* I/O mutex */
+       struct mutex            io_mutex;
+
        /* lock and mutex for SPI bus locking */
        spinlock_t              bus_lock_spinlock;
        struct mutex            bus_lock_mutex;
@@ -1143,6 +1147,8 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd)
  * @opcode_nbits: number of lines to send opcode
  * @addr_nbits: number of lines to send address
  * @data_nbits: number of lines for data
+ * @rx_sg: Scatterlist for receive data read from flash
+ * @cur_msg_mapped: message has been mapped for DMA
  */
 struct spi_flash_read_message {
        void *buf;
@@ -1155,6 +1161,8 @@ struct spi_flash_read_message {
        u8 opcode_nbits;
        u8 addr_nbits;
        u8 data_nbits;
+       struct sg_table rx_sg;
+       bool cur_msg_mapped;
 };
 
 /* SPI core interface for flash read support */