summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/spi/mxs-spi.txt22
-rw-r--r--Documentation/devicetree/bindings/spi/spi-bus.txt3
-rw-r--r--Documentation/devicetree/bindings/spi/spi-gpio.txt29
-rw-r--r--Documentation/devicetree/bindings/spi/spi-sc18is602.txt23
-rw-r--r--Documentation/devicetree/bindings/spi/spi_pl022.txt22
-rw-r--r--Documentation/spi/spi-sc18is60236
-rw-r--r--arch/arm/mach-u300/core.c3
-rw-r--r--drivers/clk/mxs/Makefile2
-rw-r--r--drivers/clk/mxs/clk-ssp.c62
-rw-r--r--drivers/mmc/host/mxs-mmc.c323
-rw-r--r--drivers/spi/Kconfig15
-rw-r--r--drivers/spi/Makefile3
-rw-r--r--drivers/spi/spi-altera.c4
-rw-r--r--drivers/spi/spi-gpio.c131
-rw-r--r--drivers/spi/spi-imx.c6
-rw-r--r--drivers/spi/spi-mpc512x-psc.c3
-rw-r--r--drivers/spi/spi-mpc52xx-psc.c3
-rw-r--r--drivers/spi/spi-mpc52xx.c9
-rw-r--r--drivers/spi/spi-mxs.c674
-rw-r--r--drivers/spi/spi-omap2-mcspi.c321
-rw-r--r--drivers/spi/spi-orion.c209
-rw-r--r--drivers/spi/spi-pl022.c251
-rw-r--r--drivers/spi/spi-s3c24xx.c1
-rw-r--r--drivers/spi/spi-s3c64xx.c11
-rw-r--r--drivers/spi/spi-sc18is602.c364
-rw-r--r--drivers/spi/spi-sh-hspi.c5
-rw-r--r--drivers/spi/spi-stmp.c6
-rw-r--r--drivers/spi/spi-tegra.c647
-rw-r--r--drivers/spi/spi-tle62x0.c13
-rw-r--r--drivers/spi/spi-topcliff-pch.c2
-rw-r--r--include/linux/amba/pl022.h2
-rw-r--r--include/linux/platform_data/sc18is602.h19
-rw-r--r--include/linux/spi/mxs-spi.h150
33 files changed, 2114 insertions, 1260 deletions
diff --git a/Documentation/devicetree/bindings/spi/mxs-spi.txt b/Documentation/devicetree/bindings/spi/mxs-spi.txt
new file mode 100644
index 000000000000..e2e13957c2a4
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/mxs-spi.txt
@@ -0,0 +1,22 @@
+* Freescale MX233/MX28 SSP/SPI
+
+Required properties:
+- compatible: Should be "fsl,<soc>-spi", where soc is "imx23" or "imx28"
+- reg: Offset and length of the register set for the device
+- interrupts: Should contain SSP interrupts (error irq first, dma irq second)
+- fsl,ssp-dma-channel: APBX DMA channel for the SSP
+
+Optional properties:
+- clock-frequency : Input clock frequency to the SPI block in Hz.
+		    Default is 160000000 Hz.
+
+Example:
+
+ssp0: ssp@80010000 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "fsl,imx28-spi";
+	reg = <0x80010000 0x2000>;
+	interrupts = <96 82>;
+	fsl,ssp-dma-channel = <0>;
+};
diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
index e782add2e457..d2c33d0f533e 100644
--- a/Documentation/devicetree/bindings/spi/spi-bus.txt
+++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -21,6 +21,9 @@ 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
+
 SPI slave nodes must be children of the SPI master node and can
 contain the following properties.
 - reg             - (required) chip select address of device.
diff --git a/Documentation/devicetree/bindings/spi/spi-gpio.txt b/Documentation/devicetree/bindings/spi/spi-gpio.txt
new file mode 100644
index 000000000000..8a824be15754
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-gpio.txt
@@ -0,0 +1,29 @@
+SPI-GPIO devicetree bindings
+
+Required properties:
+
+ - compatible: should be set to "spi-gpio"
+ - #address-cells: should be set to <0x1>
+ - ranges
+ - gpio-sck: GPIO spec for the SCK line to use
+ - gpio-miso: GPIO spec for the MISO line to use
+ - gpio-mosi: GPIO spec for the MOSI line to use
+ - cs-gpios: GPIOs to use for chipselect lines
+ - num-chipselects: number of chipselect lines
+
+Example:
+
+	spi {
+		compatible = "spi-gpio";
+		#address-cells = <0x1>;
+		ranges;
+
+		gpio-sck = <&gpio 95 0>;
+		gpio-miso = <&gpio 98 0>;
+		gpio-mosi = <&gpio 97 0>;
+		cs-gpios = <&gpio 125 0>;
+		num-chipselects = <1>;
+
+		/* clients */
+	};
+
diff --git a/Documentation/devicetree/bindings/spi/spi-sc18is602.txt b/Documentation/devicetree/bindings/spi/spi-sc18is602.txt
new file mode 100644
index 000000000000..02f9033270a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-sc18is602.txt
@@ -0,0 +1,23 @@
+NXP SC18IS602/SCIS603
+
+Required properties:
+	- compatible : Should be one of
+		"nxp,sc18is602"
+		"nxp,sc18is602b"
+		"nxp,sc18is603"
+	- reg: I2C bus address
+
+Optional properties:
+	- clock-frequency : external oscillator clock frequency. If not
+	  specified, the SC18IS602 default frequency (7372000) will be used.
+
+The clock-frequency property is relevant and needed only if the chip has an
+external oscillator (SC18IS603).
+
+Example:
+
+	sc18is603@28 {
+		compatible = "nxp,sc18is603";
+		reg = <0x28>;
+		clock-frequency = <14744000>;
+	}
diff --git a/Documentation/devicetree/bindings/spi/spi_pl022.txt b/Documentation/devicetree/bindings/spi/spi_pl022.txt
index 306ec3ff3c0e..f158fd31cfda 100644
--- a/Documentation/devicetree/bindings/spi/spi_pl022.txt
+++ b/Documentation/devicetree/bindings/spi/spi_pl022.txt
@@ -6,7 +6,29 @@ Required properties:
 - interrupts : Should contain SPI controller interrupt
 
 Optional properties:
+- num-cs : total number of chipselects
 - cs-gpios : should specify GPIOs used for chipselects.
   The gpios will be referred to as reg = <index> in the SPI child nodes.
   If unspecified, a single SPI device without a chip select can be used.
+- pl022,autosuspend-delay : delay in ms following transfer completion before
+			    the runtime power management system suspends the
+			    device. A setting of 0 indicates no delay and the
+                            device will be suspended immediately
+- pl022,rt : indicates the controller should run the message pump with realtime
+             priority to minimise the transfer latency on the bus (boolean)
+
+
+SPI slave nodes must be children of the SPI master node and can
+contain the following properties.
+
+- pl022,interface : interface type:
+	0: SPI
+	1: Texas Instruments Synchronous Serial Frame Format
+	2: Microwire (Half Duplex)
+- pl022,com-mode : polling, interrupt or dma
+- pl022,rx-level-trig : Rx FIFO watermark level
+- pl022,tx-level-trig : Tx FIFO watermark level
+- pl022,ctrl-len : Microwire interface: Control length
+- pl022,wait-state : Microwire interface: Wait state
+- pl022,duplex : Microwire interface: Full/Half duplex
 
diff --git a/Documentation/spi/spi-sc18is602 b/Documentation/spi/spi-sc18is602
new file mode 100644
index 000000000000..a45702865a38
--- /dev/null
+++ b/Documentation/spi/spi-sc18is602
@@ -0,0 +1,36 @@
+Kernel driver spi-sc18is602
+===========================
+
+Supported chips:
+  * NXP SI18IS602/602B/603
+    Datasheet: http://www.nxp.com/documents/data_sheet/SC18IS602_602B_603.pdf
+
+Author:
+        Guenter Roeck <linux@roeck-us.net>
+
+
+Description
+-----------
+
+This driver provides connects a NXP SC18IS602/603 I2C-bus to SPI bridge to the
+kernel's SPI core subsystem.
+
+The driver does not probe for supported chips, since the SI18IS602/603 does not
+support Chip ID registers. You will have to instantiate the devices explicitly.
+Please see Documentation/i2c/instantiating-devices for details.
+
+
+Usage Notes
+-----------
+
+This driver requires the I2C adapter driver to support raw I2C messages. I2C
+adapter drivers which can only handle the SMBus protocol are not supported.
+
+The maximum SPI message size supported by SC18IS602/603 is 200 bytes. Attempts
+to initiate longer transfers will fail with -EINVAL. EEPROM read operations and
+similar large accesses have to be split into multiple chunks of no more than
+200 bytes per SPI message (128 bytes of data per message is recommended). This
+means that programs such as "cp" or "od", which automatically use large block
+sizes to access a device, can not be used directly to read data from EEPROM.
+Programs such as dd, where the block size can be specified, should be used
+instead.
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index ef6f602b7e48..b8efac4daed8 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1557,9 +1557,6 @@ static struct u300_mux_hog u300_mux_hogs[] = {
 		.dev = &uart0_device.dev,
 	},
 	{
-		.dev = &pl022_device.dev,
-	},
-	{
 		.dev = &mmcsd_device.dev,
 	},
 };
diff --git a/drivers/clk/mxs/Makefile b/drivers/clk/mxs/Makefile
index 7bedeec08524..a6a22237e860 100644
--- a/drivers/clk/mxs/Makefile
+++ b/drivers/clk/mxs/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mxs specific clk
 #
 
-obj-y += clk.o clk-pll.o clk-ref.o clk-div.o clk-frac.o
+obj-y += clk.o clk-pll.o clk-ref.o clk-div.o clk-frac.o clk-ssp.o
 
 obj-$(CONFIG_SOC_IMX23) += clk-imx23.o
 obj-$(CONFIG_SOC_IMX28) += clk-imx28.o
diff --git a/drivers/clk/mxs/clk-ssp.c b/drivers/clk/mxs/clk-ssp.c
new file mode 100644
index 000000000000..af7bdbf9ebd7
--- /dev/null
+++ b/drivers/clk/mxs/clk-ssp.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 DENX Software Engineering, GmbH
+ *
+ * Pulled from code:
+ * Portions copyright (C) 2003 Russell King, PXA MMCI Driver
+ * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC driver
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/spi/mxs-spi.h>
+
+void mxs_ssp_set_clk_rate(struct mxs_ssp *ssp, unsigned int rate)
+{
+	unsigned int ssp_clk, ssp_sck;
+	u32 clock_divide, clock_rate;
+	u32 val;
+
+	ssp_clk = clk_get_rate(ssp->clk);
+
+	for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
+		clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
+		clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0;
+		if (clock_rate <= 255)
+			break;
+	}
+
+	if (clock_divide > 254) {
+		dev_err(ssp->dev,
+			"%s: cannot set clock to %d\n", __func__, rate);
+		return;
+	}
+
+	ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
+
+	val = readl(ssp->base + HW_SSP_TIMING(ssp));
+	val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
+	val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
+	val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
+	writel(val, ssp->base + HW_SSP_TIMING(ssp));
+
+	ssp->clk_rate = ssp_sck;
+
+	dev_dbg(ssp->dev,
+		"%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
+		__func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate);
+}
+EXPORT_SYMBOL_GPL(mxs_ssp_set_clk_rate);
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index ad3fcea1269e..bb4c2bf04d09 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -41,91 +41,13 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/module.h>
-#include <linux/fsl/mxs-dma.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/stmp_device.h>
 #include <linux/mmc/mxs-mmc.h>
+#include <linux/spi/mxs-spi.h>
 
 #define DRIVER_NAME	"mxs-mmc"
 
-/* card detect polling timeout */
-#define MXS_MMC_DETECT_TIMEOUT			(HZ/2)
-
-#define ssp_is_old(host)	((host)->devid == IMX23_MMC)
-
-/* SSP registers */
-#define HW_SSP_CTRL0				0x000
-#define  BM_SSP_CTRL0_RUN			(1 << 29)
-#define  BM_SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
-#define  BM_SSP_CTRL0_IGNORE_CRC		(1 << 26)
-#define  BM_SSP_CTRL0_READ			(1 << 25)
-#define  BM_SSP_CTRL0_DATA_XFER			(1 << 24)
-#define  BP_SSP_CTRL0_BUS_WIDTH			(22)
-#define  BM_SSP_CTRL0_BUS_WIDTH			(0x3 << 22)
-#define  BM_SSP_CTRL0_WAIT_FOR_IRQ		(1 << 21)
-#define  BM_SSP_CTRL0_LONG_RESP			(1 << 19)
-#define  BM_SSP_CTRL0_GET_RESP			(1 << 17)
-#define  BM_SSP_CTRL0_ENABLE			(1 << 16)
-#define  BP_SSP_CTRL0_XFER_COUNT		(0)
-#define  BM_SSP_CTRL0_XFER_COUNT		(0xffff)
-#define HW_SSP_CMD0				0x010
-#define  BM_SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
-#define  BM_SSP_CMD0_SLOW_CLKING_EN		(1 << 22)
-#define  BM_SSP_CMD0_CONT_CLKING_EN		(1 << 21)
-#define  BM_SSP_CMD0_APPEND_8CYC		(1 << 20)
-#define  BP_SSP_CMD0_BLOCK_SIZE			(16)
-#define  BM_SSP_CMD0_BLOCK_SIZE			(0xf << 16)
-#define  BP_SSP_CMD0_BLOCK_COUNT		(8)
-#define  BM_SSP_CMD0_BLOCK_COUNT		(0xff << 8)
-#define  BP_SSP_CMD0_CMD			(0)
-#define  BM_SSP_CMD0_CMD			(0xff)
-#define HW_SSP_CMD1				0x020
-#define HW_SSP_XFER_SIZE			0x030
-#define HW_SSP_BLOCK_SIZE			0x040
-#define  BP_SSP_BLOCK_SIZE_BLOCK_COUNT		(4)
-#define  BM_SSP_BLOCK_SIZE_BLOCK_COUNT		(0xffffff << 4)
-#define  BP_SSP_BLOCK_SIZE_BLOCK_SIZE		(0)
-#define  BM_SSP_BLOCK_SIZE_BLOCK_SIZE		(0xf)
-#define HW_SSP_TIMING(h)			(ssp_is_old(h) ? 0x050 : 0x070)
-#define  BP_SSP_TIMING_TIMEOUT			(16)
-#define  BM_SSP_TIMING_TIMEOUT			(0xffff << 16)
-#define  BP_SSP_TIMING_CLOCK_DIVIDE		(8)
-#define  BM_SSP_TIMING_CLOCK_DIVIDE		(0xff << 8)
-#define  BP_SSP_TIMING_CLOCK_RATE		(0)
-#define  BM_SSP_TIMING_CLOCK_RATE		(0xff)
-#define HW_SSP_CTRL1(h)				(ssp_is_old(h) ? 0x060 : 0x080)
-#define  BM_SSP_CTRL1_SDIO_IRQ			(1 << 31)
-#define  BM_SSP_CTRL1_SDIO_IRQ_EN		(1 << 30)
-#define  BM_SSP_CTRL1_RESP_ERR_IRQ		(1 << 29)
-#define  BM_SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
-#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
-#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN	(1 << 26)
-#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
-#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN	(1 << 24)
-#define  BM_SSP_CTRL1_DATA_CRC_IRQ		(1 << 23)
-#define  BM_SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
-#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
-#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN	(1 << 20)
-#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
-#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN	(1 << 16)
-#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
-#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN	(1 << 14)
-#define  BM_SSP_CTRL1_DMA_ENABLE		(1 << 13)
-#define  BM_SSP_CTRL1_POLARITY			(1 << 9)
-#define  BP_SSP_CTRL1_WORD_LENGTH		(4)
-#define  BM_SSP_CTRL1_WORD_LENGTH		(0xf << 4)
-#define  BP_SSP_CTRL1_SSP_MODE			(0)
-#define  BM_SSP_CTRL1_SSP_MODE			(0xf)
-#define HW_SSP_SDRESP0(h)			(ssp_is_old(h) ? 0x080 : 0x0a0)
-#define HW_SSP_SDRESP1(h)			(ssp_is_old(h) ? 0x090 : 0x0b0)
-#define HW_SSP_SDRESP2(h)			(ssp_is_old(h) ? 0x0a0 : 0x0c0)
-#define HW_SSP_SDRESP3(h)			(ssp_is_old(h) ? 0x0b0 : 0x0d0)
-#define HW_SSP_STATUS(h)			(ssp_is_old(h) ? 0x0c0 : 0x100)
-#define  BM_SSP_STATUS_CARD_DETECT		(1 << 28)
-#define  BM_SSP_STATUS_SDIO_IRQ			(1 << 17)
-
-#define BF_SSP(value, field)	(((value) << BP_SSP_##field) & BM_SSP_##field)
-
 #define MXS_MMC_IRQ_BITS	(BM_SSP_CTRL1_SDIO_IRQ		| \
 				 BM_SSP_CTRL1_RESP_ERR_IRQ	| \
 				 BM_SSP_CTRL1_RESP_TIMEOUT_IRQ	| \
@@ -135,31 +57,17 @@
 				 BM_SSP_CTRL1_RECV_TIMEOUT_IRQ  | \
 				 BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)
 
-#define SSP_PIO_NUM	3
-
-enum mxs_mmc_id {
-	IMX23_MMC,
-	IMX28_MMC,
-};
+/* card detect polling timeout */
+#define MXS_MMC_DETECT_TIMEOUT			(HZ/2)
 
 struct mxs_mmc_host {
+	struct mxs_ssp			ssp;
+
 	struct mmc_host			*mmc;
 	struct mmc_request		*mrq;
 	struct mmc_command		*cmd;
 	struct mmc_data			*data;
 
-	void __iomem			*base;
-	int				dma_channel;
-	struct clk			*clk;
-	unsigned int			clk_rate;
-
-	struct dma_chan         	*dmach;
-	struct mxs_dma_data		dma_data;
-	unsigned int			dma_dir;
-	enum dma_transfer_direction	slave_dirn;
-	u32				ssp_pio_words[SSP_PIO_NUM];
-
-	enum mxs_mmc_id			devid;
 	unsigned char			bus_width;
 	spinlock_t			lock;
 	int				sdio_irq_en;
@@ -186,16 +94,18 @@ static int mxs_mmc_get_ro(struct mmc_host *mmc)
 static int mxs_mmc_get_cd(struct mmc_host *mmc)
 {
 	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct mxs_ssp *ssp = &host->ssp;
 
-	return !(readl(host->base + HW_SSP_STATUS(host)) &
+	return !(readl(ssp->base + HW_SSP_STATUS(ssp)) &
 		 BM_SSP_STATUS_CARD_DETECT);
 }
 
 static void mxs_mmc_reset(struct mxs_mmc_host *host)
 {
+	struct mxs_ssp *ssp = &host->ssp;
 	u32 ctrl0, ctrl1;
 
-	stmp_reset_block(host->base);
+	stmp_reset_block(ssp->base);
 
 	ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
 	ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
@@ -211,15 +121,15 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host)
 	writel(BF_SSP(0xffff, TIMING_TIMEOUT) |
 	       BF_SSP(2, TIMING_CLOCK_DIVIDE) |
 	       BF_SSP(0, TIMING_CLOCK_RATE),
-	       host->base + HW_SSP_TIMING(host));
+	       ssp->base + HW_SSP_TIMING(ssp));
 
 	if (host->sdio_irq_en) {
 		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
 		ctrl1 |= BM_SSP_CTRL1_SDIO_IRQ_EN;
 	}
 
-	writel(ctrl0, host->base + HW_SSP_CTRL0);
-	writel(ctrl1, host->base + HW_SSP_CTRL1(host));
+	writel(ctrl0, ssp->base + HW_SSP_CTRL0);
+	writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp));
 }
 
 static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
@@ -230,21 +140,22 @@ static void mxs_mmc_request_done(struct mxs_mmc_host *host)
 	struct mmc_command *cmd = host->cmd;
 	struct mmc_data *data = host->data;
 	struct mmc_request *mrq = host->mrq;
+	struct mxs_ssp *ssp = &host->ssp;
 
 	if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) {
 		if (mmc_resp_type(cmd) & MMC_RSP_136) {
-			cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0(host));
-			cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1(host));
-			cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2(host));
-			cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3(host));
+			cmd->resp[3] = readl(ssp->base + HW_SSP_SDRESP0(ssp));
+			cmd->resp[2] = readl(ssp->base + HW_SSP_SDRESP1(ssp));
+			cmd->resp[1] = readl(ssp->base + HW_SSP_SDRESP2(ssp));
+			cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP3(ssp));
 		} else {
-			cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0(host));
+			cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP0(ssp));
 		}
 	}
 
 	if (data) {
 		dma_unmap_sg(mmc_dev(host->mmc), data->sg,
-			     data->sg_len, host->dma_dir);
+			     data->sg_len, ssp->dma_dir);
 		/*
 		 * If there was an error on any block, we mark all
 		 * data blocks as being in error.
@@ -277,13 +188,14 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
 	struct mxs_mmc_host *host = dev_id;
 	struct mmc_command *cmd = host->cmd;
 	struct mmc_data *data = host->data;
+	struct mxs_ssp *ssp = &host->ssp;
 	u32 stat;
 
 	spin_lock(&host->lock);
 
-	stat = readl(host->base + HW_SSP_CTRL1(host));
+	stat = readl(ssp->base + HW_SSP_CTRL1(ssp));
 	writel(stat & MXS_MMC_IRQ_BITS,
-	       host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
+	       ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
 
 	spin_unlock(&host->lock);
 
@@ -312,6 +224,7 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
 static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
 	struct mxs_mmc_host *host, unsigned long flags)
 {
+	struct mxs_ssp *ssp = &host->ssp;
 	struct dma_async_tx_descriptor *desc;
 	struct mmc_data *data = host->data;
 	struct scatterlist * sgl;
@@ -320,24 +233,24 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
 	if (data) {
 		/* data */
 		dma_map_sg(mmc_dev(host->mmc), data->sg,
-			   data->sg_len, host->dma_dir);
+			   data->sg_len, ssp->dma_dir);
 		sgl = data->sg;
 		sg_len = data->sg_len;
 	} else {
 		/* pio */
-		sgl = (struct scatterlist *) host->ssp_pio_words;
+		sgl = (struct scatterlist *) ssp->ssp_pio_words;
 		sg_len = SSP_PIO_NUM;
 	}
 
-	desc = dmaengine_prep_slave_sg(host->dmach,
-				sgl, sg_len, host->slave_dirn, flags);
+	desc = dmaengine_prep_slave_sg(ssp->dmach,
+				sgl, sg_len, ssp->slave_dirn, flags);
 	if (desc) {
 		desc->callback = mxs_mmc_dma_irq_callback;
 		desc->callback_param = host;
 	} else {
 		if (data)
 			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
-				     data->sg_len, host->dma_dir);
+				     data->sg_len, ssp->dma_dir);
 	}
 
 	return desc;
@@ -345,6 +258,7 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
 
 static void mxs_mmc_bc(struct mxs_mmc_host *host)
 {
+	struct mxs_ssp *ssp = &host->ssp;
 	struct mmc_command *cmd = host->cmd;
 	struct dma_async_tx_descriptor *desc;
 	u32 ctrl0, cmd0, cmd1;
@@ -358,17 +272,17 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host)
 		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
 	}
 
-	host->ssp_pio_words[0] = ctrl0;
-	host->ssp_pio_words[1] = cmd0;
-	host->ssp_pio_words[2] = cmd1;
-	host->dma_dir = DMA_NONE;
-	host->slave_dirn = DMA_TRANS_NONE;
+	ssp->ssp_pio_words[0] = ctrl0;
+	ssp->ssp_pio_words[1] = cmd0;
+	ssp->ssp_pio_words[2] = cmd1;
+	ssp->dma_dir = DMA_NONE;
+	ssp->slave_dirn = DMA_TRANS_NONE;
 	desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
 	if (!desc)
 		goto out;
 
 	dmaengine_submit(desc);
-	dma_async_issue_pending(host->dmach);
+	dma_async_issue_pending(ssp->dmach);
 	return;
 
 out:
@@ -378,6 +292,7 @@ out:
 
 static void mxs_mmc_ac(struct mxs_mmc_host *host)
 {
+	struct mxs_ssp *ssp = &host->ssp;
 	struct mmc_command *cmd = host->cmd;
 	struct dma_async_tx_descriptor *desc;
 	u32 ignore_crc, get_resp, long_resp;
@@ -399,17 +314,17 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
 		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
 	}
 
-	host->ssp_pio_words[0] = ctrl0;
-	host->ssp_pio_words[1] = cmd0;
-	host->ssp_pio_words[2] = cmd1;
-	host->dma_dir = DMA_NONE;
-	host->slave_dirn = DMA_TRANS_NONE;
+	ssp->ssp_pio_words[0] = ctrl0;
+	ssp->ssp_pio_words[1] = cmd0;
+	ssp->ssp_pio_words[2] = cmd1;
+	ssp->dma_dir = DMA_NONE;
+	ssp->slave_dirn = DMA_TRANS_NONE;
 	desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
 	if (!desc)
 		goto out;
 
 	dmaengine_submit(desc);
-	dma_async_issue_pending(host->dmach);
+	dma_async_issue_pending(ssp->dmach);
 	return;
 
 out:
@@ -447,6 +362,8 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
 	unsigned int data_size = 0, log2_blksz;
 	unsigned int blocks = data->blocks;
 
+	struct mxs_ssp *ssp = &host->ssp;
+
 	u32 ignore_crc, get_resp, long_resp, read;
 	u32 ctrl0, cmd0, cmd1, val;
 
@@ -489,15 +406,15 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
 		blocks = 1;
 
 	/* xfer count, block size and count need to be set differently */
-	if (ssp_is_old(host)) {
+	if (ssp_is_old(ssp)) {
 		ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT);
 		cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) |
 			BF_SSP(blocks - 1, CMD0_BLOCK_COUNT);
 	} else {
-		writel(data_size, host->base + HW_SSP_XFER_SIZE);
+		writel(data_size, ssp->base + HW_SSP_XFER_SIZE);
 		writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) |
 		       BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT),
-		       host->base + HW_SSP_BLOCK_SIZE);
+		       ssp->base + HW_SSP_BLOCK_SIZE);
 	}
 
 	if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
@@ -512,18 +429,18 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
 	}
 
 	/* set the timeout count */
-	timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns);
-	val = readl(host->base + HW_SSP_TIMING(host));
+	timeout = mxs_ns_to_ssp_ticks(ssp->clk_rate, data->timeout_ns);
+	val = readl(ssp->base + HW_SSP_TIMING(ssp));
 	val &= ~(BM_SSP_TIMING_TIMEOUT);
 	val |= BF_SSP(timeout, TIMING_TIMEOUT);
-	writel(val, host->base + HW_SSP_TIMING(host));
+	writel(val, ssp->base + HW_SSP_TIMING(ssp));
 
 	/* pio */
-	host->ssp_pio_words[0] = ctrl0;
-	host->ssp_pio_words[1] = cmd0;
-	host->ssp_pio_words[2] = cmd1;
-	host->dma_dir = DMA_NONE;
-	host->slave_dirn = DMA_TRANS_NONE;
+	ssp->ssp_pio_words[0] = ctrl0;
+	ssp->ssp_pio_words[1] = cmd0;
+	ssp->ssp_pio_words[2] = cmd1;
+	ssp->dma_dir = DMA_NONE;
+	ssp->slave_dirn = DMA_TRANS_NONE;
 	desc = mxs_mmc_prep_dma(host, 0);
 	if (!desc)
 		goto out;
@@ -531,14 +448,14 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
 	/* append data sg */
 	WARN_ON(host->data != NULL);
 	host->data = data;
-	host->dma_dir = dma_data_dir;
-	host->slave_dirn = slave_dirn;
+	ssp->dma_dir = dma_data_dir;
+	ssp->slave_dirn = slave_dirn;
 	desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc)
 		goto out;
 
 	dmaengine_submit(desc);
-	dma_async_issue_pending(host->dmach);
+	dma_async_issue_pending(ssp->dmach);
 	return;
 out:
 	dev_warn(mmc_dev(host->mmc),
@@ -579,42 +496,6 @@ static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	mxs_mmc_start_cmd(host, mrq->cmd);
 }
 
-static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
-{
-	unsigned int ssp_clk, ssp_sck;
-	u32 clock_divide, clock_rate;
-	u32 val;
-
-	ssp_clk = clk_get_rate(host->clk);
-
-	for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
-		clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
-		clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0;
-		if (clock_rate <= 255)
-			break;
-	}
-
-	if (clock_divide > 254) {
-		dev_err(mmc_dev(host->mmc),
-			"%s: cannot set clock to %d\n", __func__, rate);
-		return;
-	}
-
-	ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
-
-	val = readl(host->base + HW_SSP_TIMING(host));
-	val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
-	val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
-	val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
-	writel(val, host->base + HW_SSP_TIMING(host));
-
-	host->clk_rate = ssp_sck;
-
-	dev_dbg(mmc_dev(host->mmc),
-		"%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
-		__func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate);
-}
-
 static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mxs_mmc_host *host = mmc_priv(mmc);
@@ -627,12 +508,13 @@ static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		host->bus_width = 0;
 
 	if (ios->clock)
-		mxs_mmc_set_clk_rate(host, ios->clock);
+		mxs_ssp_set_clk_rate(&host->ssp, ios->clock);
 }
 
 static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
 {
 	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct mxs_ssp *ssp = &host->ssp;
 	unsigned long flags;
 
 	spin_lock_irqsave(&host->lock, flags);
@@ -641,19 +523,19 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
 
 	if (enable) {
 		writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
-		       host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+		       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
 		writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
 		       host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET);
 	} else {
 		writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
-		       host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+		       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
 		writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
-		       host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
+		       ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
 	}
 
 	spin_unlock_irqrestore(&host->lock, flags);
 
-	if (enable && readl(host->base + HW_SSP_STATUS(host)) &
+	if (enable && readl(ssp->base + HW_SSP_STATUS(ssp)) &
 			BM_SSP_STATUS_SDIO_IRQ)
 		mmc_signal_sdio_irq(host->mmc);
 
@@ -670,34 +552,35 @@ static const struct mmc_host_ops mxs_mmc_ops = {
 static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param)
 {
 	struct mxs_mmc_host *host = param;
+	struct mxs_ssp *ssp = &host->ssp;
 
 	if (!mxs_dma_is_apbh(chan))
 		return false;
 
-	if (chan->chan_id != host->dma_channel)
+	if (chan->chan_id != ssp->dma_channel)
 		return false;
 
-	chan->private = &host->dma_data;
+	chan->private = &ssp->dma_data;
 
 	return true;
 }
 
-static struct platform_device_id mxs_mmc_ids[] = {
+static struct platform_device_id mxs_ssp_ids[] = {
 	{
 		.name = "imx23-mmc",
-		.driver_data = IMX23_MMC,
+		.driver_data = IMX23_SSP,
 	}, {
 		.name = "imx28-mmc",
-		.driver_data = IMX28_MMC,
+		.driver_data = IMX28_SSP,
 	}, {
 		/* sentinel */
 	}
 };
-MODULE_DEVICE_TABLE(platform, mxs_mmc_ids);
+MODULE_DEVICE_TABLE(platform, mxs_ssp_ids);
 
 static const struct of_device_id mxs_mmc_dt_ids[] = {
-	{ .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_MMC, },
-	{ .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_MMC, },
+	{ .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_SSP, },
+	{ .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_SSP, },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids);
@@ -716,6 +599,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 	dma_cap_mask_t mask;
 	struct regulator *reg_vmmc;
 	enum of_gpio_flags flags;
+	struct mxs_ssp *ssp;
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -729,28 +613,30 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	host = mmc_priv(mmc);
-	host->base = devm_request_and_ioremap(&pdev->dev, iores);
-	if (!host->base) {
+	ssp = &host->ssp;
+	ssp->dev = &pdev->dev;
+	ssp->base = devm_request_and_ioremap(&pdev->dev, iores);
+	if (!ssp->base) {
 		ret = -EADDRNOTAVAIL;
 		goto out_mmc_free;
 	}
 
 	if (np) {
-		host->devid = (enum mxs_mmc_id) of_id->data;
+		ssp->devid = (enum mxs_ssp_id) of_id->data;
 		/*
 		 * TODO: This is a temporary solution and should be changed
 		 * to use generic DMA binding later when the helpers get in.
 		 */
 		ret = of_property_read_u32(np, "fsl,ssp-dma-channel",
-					   &host->dma_channel);
+					   &ssp->dma_channel);
 		if (ret) {
 			dev_err(mmc_dev(host->mmc),
 				"failed to get dma channel\n");
 			goto out_mmc_free;
 		}
 	} else {
-		host->devid = pdev->id_entry->driver_data;
-		host->dma_channel = dmares->start;
+		ssp->devid = pdev->id_entry->driver_data;
+		ssp->dma_channel = dmares->start;
 	}
 
 	host->mmc = mmc;
@@ -772,20 +658,20 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 		goto out_mmc_free;
 	}
 
-	host->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(host->clk)) {
-		ret = PTR_ERR(host->clk);
+	ssp->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ssp->clk)) {
+		ret = PTR_ERR(ssp->clk);
 		goto out_mmc_free;
 	}
-	clk_prepare_enable(host->clk);
+	clk_prepare_enable(ssp->clk);
 
 	mxs_mmc_reset(host);
 
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
-	host->dma_data.chan_irq = irq_dma;
-	host->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
-	if (!host->dmach) {
+	ssp->dma_data.chan_irq = irq_dma;
+	ssp->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
+	if (!ssp->dmach) {
 		dev_err(mmc_dev(host->mmc),
 			"%s: failed to request dma\n", __func__);
 		goto out_clk_put;
@@ -822,9 +708,9 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 
 	mmc->max_segs = 52;
 	mmc->max_blk_size = 1 << 0xf;
-	mmc->max_blk_count = (ssp_is_old(host)) ? 0xff : 0xffffff;
-	mmc->max_req_size = (ssp_is_old(host)) ? 0xffff : 0xffffffff;
-	mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev);
+	mmc->max_blk_count = (ssp_is_old(ssp)) ? 0xff : 0xffffff;
+	mmc->max_req_size = (ssp_is_old(ssp)) ? 0xffff : 0xffffffff;
+	mmc->max_seg_size = dma_get_max_seg_size(ssp->dmach->device->dev);
 
 	platform_set_drvdata(pdev, mmc);
 
@@ -844,11 +730,11 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 	return 0;
 
 out_free_dma:
-	if (host->dmach)
-		dma_release_channel(host->dmach);
+	if (ssp->dmach)
+		dma_release_channel(ssp->dmach);
 out_clk_put:
-	clk_disable_unprepare(host->clk);
-	clk_put(host->clk);
+	clk_disable_unprepare(ssp->clk);
+	clk_put(ssp->clk);
 out_mmc_free:
 	mmc_free_host(mmc);
 	return ret;
@@ -858,16 +744,17 @@ static int mxs_mmc_remove(struct platform_device *pdev)
 {
 	struct mmc_host *mmc = platform_get_drvdata(pdev);
 	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct mxs_ssp *ssp = &host->ssp;
 
 	mmc_remove_host(mmc);
 
 	platform_set_drvdata(pdev, NULL);
 
-	if (host->dmach)
-		dma_release_channel(host->dmach);
+	if (ssp->dmach)
+		dma_release_channel(ssp->dmach);
 
-	clk_disable_unprepare(host->clk);
-	clk_put(host->clk);
+	clk_disable_unprepare(ssp->clk);
+	clk_put(ssp->clk);
 
 	mmc_free_host(mmc);
 
@@ -879,11 +766,12 @@ static int mxs_mmc_suspend(struct device *dev)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
 	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct mxs_ssp *ssp = &host->ssp;
 	int ret = 0;
 
 	ret = mmc_suspend_host(mmc);
 
-	clk_disable_unprepare(host->clk);
+	clk_disable_unprepare(ssp->clk);
 
 	return ret;
 }
@@ -892,9 +780,10 @@ static int mxs_mmc_resume(struct device *dev)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
 	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct mxs_ssp *ssp = &host->ssp;
 	int ret = 0;
 
-	clk_prepare_enable(host->clk);
+	clk_prepare_enable(ssp->clk);
 
 	ret = mmc_resume_host(mmc);
 
@@ -910,7 +799,7 @@ static const struct dev_pm_ops mxs_mmc_pm_ops = {
 static struct platform_driver mxs_mmc_driver = {
 	.probe		= mxs_mmc_probe,
 	.remove		= mxs_mmc_remove,
-	.id_table	= mxs_mmc_ids,
+	.id_table	= mxs_ssp_ids,
 	.driver		= {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2d198a01a410..ecc31a1f73fc 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -325,6 +325,12 @@ config SPI_S3C64XX
 	help
 	  SPI driver for Samsung S3C64XX and newer SoCs.
 
+config SPI_SC18IS602
+	tristate "NXP SC18IS602/602B/603 I2C to SPI bridge"
+	depends on I2C
+	help
+	  SPI driver for NXP SC18IS602/602B/603 I2C to SPI bridge.
+
 config SPI_SH_MSIOF
 	tristate "SuperH MSIOF SPI controller"
 	depends on SUPERH && HAVE_CLK
@@ -364,11 +370,12 @@ config SPI_STMP3XXX
 	help
 	  SPI driver for Freescale STMP37xx/378x SoC SSP interface
 
-config SPI_TEGRA
-	tristate "Nvidia Tegra SPI controller"
-	depends on ARCH_TEGRA && TEGRA20_APB_DMA
+config SPI_MXS
+	tristate "Freescale MXS SPI controller"
+	depends on ARCH_MXS
+	select STMP_DEVICE
 	help
-	  SPI driver for NVidia Tegra SoCs
+	  SPI driver for Freescale MXS devices.
 
 config SPI_TI_SSP
 	tristate "TI Sequencer Serial Port - SPI Support"
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3920dcf4c740..22fd3a7251bc 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o
 obj-$(CONFIG_SPI_MPC512x_PSC)		+= spi-mpc512x-psc.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= spi-mpc52xx-psc.o
 obj-$(CONFIG_SPI_MPC52xx)		+= spi-mpc52xx.o
+obj-$(CONFIG_SPI_MXS)			+= spi-mxs.o
 obj-$(CONFIG_SPI_NUC900)		+= spi-nuc900.o
 obj-$(CONFIG_SPI_OC_TINY)		+= spi-oc-tiny.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= spi-omap-uwire.o
@@ -51,13 +52,13 @@ obj-$(CONFIG_SPI_S3C24XX)		+= spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y			:= spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
 obj-$(CONFIG_SPI_S3C64XX)		+= spi-s3c64xx.o
+obj-$(CONFIG_SPI_SC18IS602)		+= spi-sc18is602.o
 obj-$(CONFIG_SPI_SH)			+= spi-sh.o
 obj-$(CONFIG_SPI_SH_HSPI)		+= spi-sh-hspi.o
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi-sh-msiof.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi-sh-sci.o
 obj-$(CONFIG_SPI_SIRF)		+= spi-sirf.o
 obj-$(CONFIG_SPI_STMP3XXX)		+= spi-stmp.o
-obj-$(CONFIG_SPI_TEGRA)			+= spi-tegra.o
 obj-$(CONFIG_SPI_TI_SSP)		+= spi-ti-ssp.o
 obj-$(CONFIG_SPI_TLE62X0)		+= spi-tle62x0.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi-topcliff-pch.o
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c
index c00d00e96ee4..f1fec2a19d10 100644
--- a/drivers/spi/spi-altera.c
+++ b/drivers/spi/spi-altera.c
@@ -307,8 +307,6 @@ static const struct of_device_id altera_spi_match[] = {
 	{},
 };
 MODULE_DEVICE_TABLE(of, altera_spi_match);
-#else /* CONFIG_OF */
-#define altera_spi_match NULL
 #endif /* CONFIG_OF */
 
 static struct platform_driver altera_spi_driver = {
@@ -318,7 +316,7 @@ static struct platform_driver altera_spi_driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
 		.pm = NULL,
-		.of_match_table = altera_spi_match,
+		.of_match_table = of_match_ptr(altera_spi_match),
 	},
 };
 module_platform_driver(altera_spi_driver);
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 0b56cfc71fab..a2b50c516b31 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -22,6 +22,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
@@ -46,6 +48,7 @@ struct spi_gpio {
 	struct spi_bitbang		bitbang;
 	struct spi_gpio_platform_data	pdata;
 	struct platform_device		*pdev;
+	int				cs_gpios[0];
 };
 
 /*----------------------------------------------------------------------*/
@@ -89,15 +92,21 @@ struct spi_gpio {
 
 /*----------------------------------------------------------------------*/
 
-static inline const struct spi_gpio_platform_data * __pure
-spi_to_pdata(const struct spi_device *spi)
+static inline struct spi_gpio * __pure
+spi_to_spi_gpio(const struct spi_device *spi)
 {
 	const struct spi_bitbang	*bang;
-	const struct spi_gpio		*spi_gpio;
+	struct spi_gpio			*spi_gpio;
 
 	bang = spi_master_get_devdata(spi->master);
 	spi_gpio = container_of(bang, struct spi_gpio, bitbang);
-	return &spi_gpio->pdata;
+	return spi_gpio;
+}
+
+static inline struct spi_gpio_platform_data * __pure
+spi_to_pdata(const struct spi_device *spi)
+{
+	return &spi_to_spi_gpio(spi)->pdata;
 }
 
 /* this is #defined to avoid unused-variable warnings when inlining */
@@ -210,7 +219,8 @@ static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
 
 static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
 {
-	unsigned long cs = (unsigned long) spi->controller_data;
+	struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
+	unsigned int cs = spi_gpio->cs_gpios[spi->chip_select];
 
 	/* set initial clock polarity */
 	if (is_active)
@@ -224,12 +234,27 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
 
 static int spi_gpio_setup(struct spi_device *spi)
 {
-	unsigned long	cs = (unsigned long) spi->controller_data;
-	int		status = 0;
+	unsigned int		cs;
+	int			status = 0;
+	struct spi_gpio		*spi_gpio = spi_to_spi_gpio(spi);
+	struct device_node	*np = spi->master->dev.of_node;
 
 	if (spi->bits_per_word > 32)
 		return -EINVAL;
 
+	if (np) {
+		/*
+		 * In DT environments, the CS GPIOs have already been
+		 * initialized from the "cs-gpios" property of the node.
+		 */
+		cs = spi_gpio->cs_gpios[spi->chip_select];
+	} else {
+		/*
+		 * ... otherwise, take it from spi->controller_data
+		 */
+		cs = (unsigned int) spi->controller_data;
+	}
+
 	if (!spi->controller_state) {
 		if (cs != SPI_GPIO_NO_CHIPSELECT) {
 			status = gpio_request(cs, dev_name(&spi->dev));
@@ -239,8 +264,12 @@ static int spi_gpio_setup(struct spi_device *spi)
 					!(spi->mode & SPI_CS_HIGH));
 		}
 	}
-	if (!status)
+	if (!status) {
 		status = spi_bitbang_setup(spi);
+		/* in case it was initialized from static board data */
+		spi_gpio->cs_gpios[spi->chip_select] = cs;
+	}
+
 	if (status) {
 		if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT)
 			gpio_free(cs);
@@ -250,7 +279,8 @@ static int spi_gpio_setup(struct spi_device *spi)
 
 static void spi_gpio_cleanup(struct spi_device *spi)
 {
-	unsigned long	cs = (unsigned long) spi->controller_data;
+	struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
+	unsigned int cs = spi_gpio->cs_gpios[spi->chip_select];
 
 	if (cs != SPI_GPIO_NO_CHIPSELECT)
 		gpio_free(cs);
@@ -313,6 +343,55 @@ done:
 	return value;
 }
 
+#ifdef CONFIG_OF
+static struct of_device_id spi_gpio_dt_ids[] = {
+	{ .compatible = "spi-gpio" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids);
+
+static int spi_gpio_probe_dt(struct platform_device *pdev)
+{
+	int ret;
+	u32 tmp;
+	struct spi_gpio_platform_data	*pdata;
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *of_id =
+			of_match_device(spi_gpio_dt_ids, &pdev->dev);
+
+	if (!of_id)
+		return 0;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->sck = of_get_named_gpio(np, "gpio-sck", 0);
+	pdata->miso = of_get_named_gpio(np, "gpio-miso", 0);
+	pdata->mosi = of_get_named_gpio(np, "gpio-mosi", 0);
+
+	ret = of_property_read_u32(np, "num-chipselects", &tmp);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "num-chipselects property not found\n");
+		goto error_free;
+	}
+
+	pdata->num_chipselect = tmp;
+	pdev->dev.platform_data = pdata;
+
+	return 1;
+
+error_free:
+	devm_kfree(&pdev->dev, pdata);
+	return ret;
+}
+#else
+static inline int spi_gpio_probe_dt(struct platform_device *pdev)
+{
+	return 0;
+}
+#endif
+
 static int __devinit spi_gpio_probe(struct platform_device *pdev)
 {
 	int				status;
@@ -320,6 +399,13 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev)
 	struct spi_gpio			*spi_gpio;
 	struct spi_gpio_platform_data	*pdata;
 	u16 master_flags = 0;
+	bool use_of = 0;
+
+	status = spi_gpio_probe_dt(pdev);
+	if (status < 0)
+		return status;
+	if (status > 0)
+		use_of = 1;
 
 	pdata = pdev->dev.platform_data;
 #ifdef GENERIC_BITBANG
@@ -331,7 +417,8 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev)
 	if (status < 0)
 		return status;
 
-	master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);
+	master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) +
+					(sizeof(int) * SPI_N_CHIPSEL));
 	if (!master) {
 		status = -ENOMEM;
 		goto gpio_free;
@@ -348,6 +435,23 @@ static int __devinit spi_gpio_probe(struct platform_device *pdev)
 	master->num_chipselect = SPI_N_CHIPSEL;
 	master->setup = spi_gpio_setup;
 	master->cleanup = spi_gpio_cleanup;
+#ifdef CONFIG_OF
+	master->dev.of_node = pdev->dev.of_node;
+
+	if (use_of) {
+		int i;
+		struct device_node *np = pdev->dev.of_node;
+
+		/*
+		 * In DT environments, take the CS GPIO from the "cs-gpios"
+		 * property of the node.
+		 */
+
+		for (i = 0; i < SPI_N_CHIPSEL; i++)
+			spi_gpio->cs_gpios[i] =
+				of_get_named_gpio(np, "cs-gpios", i);
+	}
+#endif
 
 	spi_gpio->bitbang.master = spi_master_get(master);
 	spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
@@ -408,8 +512,11 @@ static int __devexit spi_gpio_remove(struct platform_device *pdev)
 MODULE_ALIAS("platform:" DRIVER_NAME);
 
 static struct platform_driver spi_gpio_driver = {
-	.driver.name	= DRIVER_NAME,
-	.driver.owner	= THIS_MODULE,
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(spi_gpio_dt_ids),
+	},
 	.probe		= spi_gpio_probe,
 	.remove		= __devexit_p(spi_gpio_remove),
 };
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index de7ebb65e535..c9a0d8467de6 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -197,6 +197,7 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
 #define MX51_ECSPI_CONFIG_SCLKPOL(cs)	(1 << ((cs) +  4))
 #define MX51_ECSPI_CONFIG_SBBCTRL(cs)	(1 << ((cs) +  8))
 #define MX51_ECSPI_CONFIG_SSBPOL(cs)	(1 << ((cs) + 12))
+#define MX51_ECSPI_CONFIG_SCLKCTL(cs)	(1 << ((cs) + 20))
 
 #define MX51_ECSPI_INT		0x10
 #define MX51_ECSPI_INT_TEEN		(1 <<  0)
@@ -287,9 +288,10 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
 	if (config->mode & SPI_CPHA)
 		cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
 
-	if (config->mode & SPI_CPOL)
+	if (config->mode & SPI_CPOL) {
 		cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
-
+		cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
+	}
 	if (config->mode & SPI_CS_HIGH)
 		cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
 
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 4c63f772780a..0a1e39e94d06 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -494,7 +494,7 @@ free_master:
 
 static int __devexit mpc512x_psc_spi_do_remove(struct device *dev)
 {
-	struct spi_master *master = dev_get_drvdata(dev);
+	struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
 	flush_workqueue(mps->workqueue);
@@ -503,6 +503,7 @@ static int __devexit mpc512x_psc_spi_do_remove(struct device *dev)
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
+	spi_master_put(master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c
index 66047156d90d..bd47d262d53f 100644
--- a/drivers/spi/spi-mpc52xx-psc.c
+++ b/drivers/spi/spi-mpc52xx-psc.c
@@ -481,7 +481,7 @@ static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op)
 
 static int __devexit mpc52xx_psc_spi_of_remove(struct platform_device *op)
 {
-	struct spi_master *master = dev_get_drvdata(&op->dev);
+	struct spi_master *master = spi_master_get(dev_get_drvdata(&op->dev));
 	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
 
 	flush_workqueue(mps->workqueue);
@@ -490,6 +490,7 @@ static int __devexit mpc52xx_psc_spi_of_remove(struct platform_device *op)
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
+	spi_master_put(master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c
index cb3a3830b0a5..045410650212 100644
--- a/drivers/spi/spi-mpc52xx.c
+++ b/drivers/spi/spi-mpc52xx.c
@@ -454,7 +454,7 @@ static int __devinit mpc52xx_spi_probe(struct platform_device *op)
 				GFP_KERNEL);
 		if (!ms->gpio_cs) {
 			rc = -ENOMEM;
-			goto err_alloc;
+			goto err_alloc_gpio;
 		}
 
 		for (i = 0; i < ms->gpio_cs_count; i++) {
@@ -514,12 +514,13 @@ static int __devinit mpc52xx_spi_probe(struct platform_device *op)
 
  err_register:
 	dev_err(&ms->master->dev, "initialization failed\n");
-	spi_master_put(master);
  err_gpio:
 	while (i-- > 0)
 		gpio_free(ms->gpio_cs[i]);
 
 	kfree(ms->gpio_cs);
+ err_alloc_gpio:
+	spi_master_put(master);
  err_alloc:
  err_init:
 	iounmap(regs);
@@ -528,7 +529,7 @@ static int __devinit mpc52xx_spi_probe(struct platform_device *op)
 
 static int __devexit mpc52xx_spi_remove(struct platform_device *op)
 {
-	struct spi_master *master = dev_get_drvdata(&op->dev);
+	struct spi_master *master = spi_master_get(dev_get_drvdata(&op->dev));
 	struct mpc52xx_spi *ms = spi_master_get_devdata(master);
 	int i;
 
@@ -540,8 +541,8 @@ static int __devexit mpc52xx_spi_remove(struct platform_device *op)
 
 	kfree(ms->gpio_cs);
 	spi_unregister_master(master);
-	spi_master_put(master);
 	iounmap(ms->regs);
+	spi_master_put(master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
new file mode 100644
index 000000000000..edf1360ab09e
--- /dev/null
+++ b/drivers/spi/spi-mxs.c
@@ -0,0 +1,674 @@
+/*
+ * Freescale MXS SPI master driver
+ *
+ * Copyright 2012 DENX Software Engineering, GmbH.
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * Rework and transition to new API by:
+ * Marek Vasut <marex@denx.de>
+ *
+ * Based on previous attempt by:
+ * Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * Based on code from U-Boot bootloader by:
+ * Marek Vasut <marex@denx.de>
+ *
+ * Based on spi-stmp.c, which is:
+ * Author: Dmitry Pervushin <dimka@embeddedalley.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/highmem.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/stmp_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mxs-spi.h>
+
+#define DRIVER_NAME		"mxs-spi"
+
+/* Use 10S timeout for very long transfers, it should suffice. */
+#define SSP_TIMEOUT		10000
+
+#define SG_MAXLEN		0xff00
+
+struct mxs_spi {
+	struct mxs_ssp		ssp;
+	struct completion	c;
+};
+
+static int mxs_spi_setup_transfer(struct spi_device *dev,
+				struct spi_transfer *t)
+{
+	struct mxs_spi *spi = spi_master_get_devdata(dev->master);
+	struct mxs_ssp *ssp = &spi->ssp;
+	uint8_t bits_per_word;
+	uint32_t hz = 0;
+
+	bits_per_word = dev->bits_per_word;
+	if (t && t->bits_per_word)
+		bits_per_word = t->bits_per_word;
+
+	if (bits_per_word != 8) {
+		dev_err(&dev->dev, "%s, unsupported bits_per_word=%d\n",
+					__func__, bits_per_word);
+		return -EINVAL;
+	}
+
+	hz = dev->max_speed_hz;
+	if (t && t->speed_hz)
+		hz = min(hz, t->speed_hz);
+	if (hz == 0) {
+		dev_err(&dev->dev, "Cannot continue with zero clock\n");
+		return -EINVAL;
+	}
+
+	mxs_ssp_set_clk_rate(ssp, hz);
+
+	writel(BF_SSP_CTRL1_SSP_MODE(BV_SSP_CTRL1_SSP_MODE__SPI) |
+		     BF_SSP_CTRL1_WORD_LENGTH
+		     (BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) |
+		     ((dev->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
+		     ((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0),
+		     ssp->base + HW_SSP_CTRL1(ssp));
+
+	writel(0x0, ssp->base + HW_SSP_CMD0);
+	writel(0x0, ssp->base + HW_SSP_CMD1);
+
+	return 0;
+}
+
+static int mxs_spi_setup(struct spi_device *dev)
+{
+	int err = 0;
+
+	if (!dev->bits_per_word)
+		dev->bits_per_word = 8;
+
+	if (dev->mode & ~(SPI_CPOL | SPI_CPHA))
+		return -EINVAL;
+
+	err = mxs_spi_setup_transfer(dev, NULL);
+	if (err) {
+		dev_err(&dev->dev,
+			"Failed to setup transfer, error = %d\n", err);
+	}
+
+	return err;
+}
+
+static uint32_t mxs_spi_cs_to_reg(unsigned cs)
+{
+	uint32_t select = 0;
+
+	/*
+	 * i.MX28 Datasheet: 17.10.1: HW_SSP_CTRL0
+	 *
+	 * The bits BM_SSP_CTRL0_WAIT_FOR_CMD and BM_SSP_CTRL0_WAIT_FOR_IRQ
+	 * in HW_SSP_CTRL0 register do have multiple usage, please refer to
+	 * the datasheet for further details. In SPI mode, they are used to
+	 * toggle the chip-select lines (nCS pins).
+	 */
+	if (cs & 1)
+		select |= BM_SSP_CTRL0_WAIT_FOR_CMD;
+	if (cs & 2)
+		select |= BM_SSP_CTRL0_WAIT_FOR_IRQ;
+
+	return select;
+}
+
+static void mxs_spi_set_cs(struct mxs_spi *spi, unsigned cs)
+{
+	const uint32_t mask =
+		BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ;
+	uint32_t select;
+	struct mxs_ssp *ssp = &spi->ssp;
+
+	writel(mask, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+	select = mxs_spi_cs_to_reg(cs);
+	writel(select, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+}
+
+static inline void mxs_spi_enable(struct mxs_spi *spi)
+{
+	struct mxs_ssp *ssp = &spi->ssp;
+
+	writel(BM_SSP_CTRL0_LOCK_CS,
+		ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+	writel(BM_SSP_CTRL0_IGNORE_CRC,
+		ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+}
+
+static inline void mxs_spi_disable(struct mxs_spi *spi)
+{
+	struct mxs_ssp *ssp = &spi->ssp;
+
+	writel(BM_SSP_CTRL0_LOCK_CS,
+		ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+	writel(BM_SSP_CTRL0_IGNORE_CRC,
+		ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+}
+
+static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set)
+{
+	const unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT);
+	struct mxs_ssp *ssp = &spi->ssp;
+	uint32_t reg;
+
+	do {
+		reg = readl_relaxed(ssp->base + offset);
+
+		if (!set)
+			reg = ~reg;
+
+		reg &= mask;
+
+		if (reg == mask)
+			return 0;
+	} while (time_before(jiffies, timeout));
+
+	return -ETIMEDOUT;
+}
+
+static void mxs_ssp_dma_irq_callback(void *param)
+{
+	struct mxs_spi *spi = param;
+	complete(&spi->c);
+}
+
+static irqreturn_t mxs_ssp_irq_handler(int irq, void *dev_id)
+{
+	struct mxs_ssp *ssp = dev_id;
+	dev_err(ssp->dev, "%s[%i] CTRL1=%08x STATUS=%08x\n",
+		__func__, __LINE__,
+		readl(ssp->base + HW_SSP_CTRL1(ssp)),
+		readl(ssp->base + HW_SSP_STATUS(ssp)));
+	return IRQ_HANDLED;
+}
+
+static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
+			    unsigned char *buf, int len,
+			    int *first, int *last, int write)
+{
+	struct mxs_ssp *ssp = &spi->ssp;
+	struct dma_async_tx_descriptor *desc = NULL;
+	const bool vmalloced_buf = is_vmalloc_addr(buf);
+	const int desc_len = vmalloced_buf ? PAGE_SIZE : SG_MAXLEN;
+	const int sgs = DIV_ROUND_UP(len, desc_len);
+	int sg_count;
+	int min, ret;
+	uint32_t ctrl0;
+	struct page *vm_page;
+	void *sg_buf;
+	struct {
+		uint32_t		pio[4];
+		struct scatterlist	sg;
+	} *dma_xfer;
+
+	if (!len)
+		return -EINVAL;
+
+	dma_xfer = kzalloc(sizeof(*dma_xfer) * sgs, GFP_KERNEL);
+	if (!dma_xfer)
+		return -ENOMEM;
+
+	INIT_COMPLETION(spi->c);
+
+	ctrl0 = readl(ssp->base + HW_SSP_CTRL0);
+	ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs);
+
+	if (*first)
+		ctrl0 |= BM_SSP_CTRL0_LOCK_CS;
+	if (!write)
+		ctrl0 |= BM_SSP_CTRL0_READ;
+
+	/* Queue the DMA data transfer. */
+	for (sg_count = 0; sg_count < sgs; sg_count++) {
+		min = min(len, desc_len);
+
+		/* Prepare the transfer descriptor. */
+		if ((sg_count + 1 == sgs) && *last)
+			ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC;
+
+		if (ssp->devid == IMX23_SSP)
+			ctrl0 |= min;
+
+		dma_xfer[sg_count].pio[0] = ctrl0;
+		dma_xfer[sg_count].pio[3] = min;
+
+		if (vmalloced_buf) {
+			vm_page = vmalloc_to_page(buf);
+			if (!vm_page) {
+				ret = -ENOMEM;
+				goto err_vmalloc;
+			}
+			sg_buf = page_address(vm_page) +
+				((size_t)buf & ~PAGE_MASK);
+		} else {
+			sg_buf = buf;
+		}
+
+		sg_init_one(&dma_xfer[sg_count].sg, sg_buf, min);
+		ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
+			write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+		len -= min;
+		buf += min;
+
+		/* Queue the PIO register write transfer. */
+		desc = dmaengine_prep_slave_sg(ssp->dmach,
+				(struct scatterlist *)dma_xfer[sg_count].pio,
+				(ssp->devid == IMX23_SSP) ? 1 : 4,
+				DMA_TRANS_NONE,
+				sg_count ? DMA_PREP_INTERRUPT : 0);
+		if (!desc) {
+			dev_err(ssp->dev,
+				"Failed to get PIO reg. write descriptor.\n");
+			ret = -EINVAL;
+			goto err_mapped;
+		}
+
+		desc = dmaengine_prep_slave_sg(ssp->dmach,
+				&dma_xfer[sg_count].sg, 1,
+				write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
+				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+		if (!desc) {
+			dev_err(ssp->dev,
+				"Failed to get DMA data write descriptor.\n");
+			ret = -EINVAL;
+			goto err_mapped;
+		}
+	}
+
+	/*
+	 * The last descriptor must have this callback,
+	 * to finish the DMA transaction.
+	 */
+	desc->callback = mxs_ssp_dma_irq_callback;
+	desc->callback_param = spi;
+
+	/* Start the transfer. */
+	dmaengine_submit(desc);
+	dma_async_issue_pending(ssp->dmach);
+
+	ret = wait_for_completion_timeout(&spi->c,
+				msecs_to_jiffies(SSP_TIMEOUT));
+	if (!ret) {
+		dev_err(ssp->dev, "DMA transfer timeout\n");
+		ret = -ETIMEDOUT;
+		goto err_vmalloc;
+	}
+
+	ret = 0;
+
+err_vmalloc:
+	while (--sg_count >= 0) {
+err_mapped:
+		dma_unmap_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
+			write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	}
+
+	kfree(dma_xfer);
+
+	return ret;
+}
+
+static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
+			    unsigned char *buf, int len,
+			    int *first, int *last, int write)
+{
+	struct mxs_ssp *ssp = &spi->ssp;
+
+	if (*first)
+		mxs_spi_enable(spi);
+
+	mxs_spi_set_cs(spi, cs);
+
+	while (len--) {
+		if (*last && len == 0)
+			mxs_spi_disable(spi);
+
+		if (ssp->devid == IMX23_SSP) {
+			writel(BM_SSP_CTRL0_XFER_COUNT,
+				ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+			writel(1,
+				ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+		} else {
+			writel(1, ssp->base + HW_SSP_XFER_SIZE);
+		}
+
+		if (write)
+			writel(BM_SSP_CTRL0_READ,
+				ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+		else
+			writel(BM_SSP_CTRL0_READ,
+				ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+
+		writel(BM_SSP_CTRL0_RUN,
+				ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+
+		if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 1))
+			return -ETIMEDOUT;
+
+		if (write)
+			writel(*buf, ssp->base + HW_SSP_DATA(ssp));
+
+		writel(BM_SSP_CTRL0_DATA_XFER,
+			     ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+
+		if (!write) {
+			if (mxs_ssp_wait(spi, HW_SSP_STATUS(ssp),
+						BM_SSP_STATUS_FIFO_EMPTY, 0))
+				return -ETIMEDOUT;
+
+			*buf = (readl(ssp->base + HW_SSP_DATA(ssp)) & 0xff);
+		}
+
+		if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 0))
+			return -ETIMEDOUT;
+
+		buf++;
+	}
+
+	if (len <= 0)
+		return 0;
+
+	return -ETIMEDOUT;
+}
+
+static int mxs_spi_transfer_one(struct spi_master *master,
+				struct spi_message *m)
+{
+	struct mxs_spi *spi = spi_master_get_devdata(master);
+	struct mxs_ssp *ssp = &spi->ssp;
+	int first, last;
+	struct spi_transfer *t, *tmp_t;
+	int status = 0;
+	int cs;
+
+	first = last = 0;
+
+	cs = m->spi->chip_select;
+
+	list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
+
+		status = mxs_spi_setup_transfer(m->spi, t);
+		if (status)
+			break;
+
+		if (&t->transfer_list == m->transfers.next)
+			first = 1;
+		if (&t->transfer_list == m->transfers.prev)
+			last = 1;
+		if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) {
+			dev_err(ssp->dev,
+				"Cannot send and receive simultaneously\n");
+			status = -EINVAL;
+			break;
+		}
+
+		/*
+		 * Small blocks can be transfered via PIO.
+		 * Measured by empiric means:
+		 *
+		 * dd if=/dev/mtdblock0 of=/dev/null bs=1024k count=1
+		 *
+		 * DMA only: 2.164808 seconds, 473.0KB/s
+		 * Combined: 1.676276 seconds, 610.9KB/s
+		 */
+		if (t->len < 32) {
+			writel(BM_SSP_CTRL1_DMA_ENABLE,
+				ssp->base + HW_SSP_CTRL1(ssp) +
+				STMP_OFFSET_REG_CLR);
+
+			if (t->tx_buf)
+				status = mxs_spi_txrx_pio(spi, cs,
+						(void *)t->tx_buf,
+						t->len, &first, &last, 1);
+			if (t->rx_buf)
+				status = mxs_spi_txrx_pio(spi, cs,
+						t->rx_buf, t->len,
+						&first, &last, 0);
+		} else {
+			writel(BM_SSP_CTRL1_DMA_ENABLE,
+				ssp->base + HW_SSP_CTRL1(ssp) +
+				STMP_OFFSET_REG_SET);
+
+			if (t->tx_buf)
+				status = mxs_spi_txrx_dma(spi, cs,
+						(void *)t->tx_buf, t->len,
+						&first, &last, 1);
+			if (t->rx_buf)
+				status = mxs_spi_txrx_dma(spi, cs,
+						t->rx_buf, t->len,
+						&first, &last, 0);
+		}
+
+		if (status) {
+			stmp_reset_block(ssp->base);
+			break;
+		}
+
+		m->actual_length += t->len;
+		first = last = 0;
+	}
+
+	m->status = 0;
+	spi_finalize_current_message(master);
+
+	return status;
+}
+
+static bool mxs_ssp_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct mxs_ssp *ssp = param;
+
+	if (!mxs_dma_is_apbh(chan))
+		return false;
+
+	if (chan->chan_id != ssp->dma_channel)
+		return false;
+
+	chan->private = &ssp->dma_data;
+
+	return true;
+}
+
+static const struct of_device_id mxs_spi_dt_ids[] = {
+	{ .compatible = "fsl,imx23-spi", .data = (void *) IMX23_SSP, },
+	{ .compatible = "fsl,imx28-spi", .data = (void *) IMX28_SSP, },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_spi_dt_ids);
+
+static int __devinit mxs_spi_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+			of_match_device(mxs_spi_dt_ids, &pdev->dev);
+	struct device_node *np = pdev->dev.of_node;
+	struct spi_master *master;
+	struct mxs_spi *spi;
+	struct mxs_ssp *ssp;
+	struct resource *iores, *dmares;
+	struct pinctrl *pinctrl;
+	struct clk *clk;
+	void __iomem *base;
+	int devid, dma_channel, clk_freq;
+	int ret = 0, irq_err, irq_dma;
+	dma_cap_mask_t mask;
+
+	/*
+	 * Default clock speed for the SPI core. 160MHz seems to
+	 * work reasonably well with most SPI flashes, so use this
+	 * as a default. Override with "clock-frequency" DT prop.
+	 */
+	const int clk_freq_default = 160000000;
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq_err = platform_get_irq(pdev, 0);
+	irq_dma = platform_get_irq(pdev, 1);
+	if (!iores || irq_err < 0 || irq_dma < 0)
+		return -EINVAL;
+
+	base = devm_request_and_ioremap(&pdev->dev, iores);
+	if (!base)
+		return -EADDRNOTAVAIL;
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		return PTR_ERR(pinctrl);
+
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	if (np) {
+		devid = (enum mxs_ssp_id) of_id->data;
+		/*
+		 * TODO: This is a temporary solution and should be changed
+		 * to use generic DMA binding later when the helpers get in.
+		 */
+		ret = of_property_read_u32(np, "fsl,ssp-dma-channel",
+					   &dma_channel);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to get DMA channel\n");
+			return -EINVAL;
+		}
+
+		ret = of_property_read_u32(np, "clock-frequency",
+					   &clk_freq);
+		if (ret)
+			clk_freq = clk_freq_default;
+	} else {
+		dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (!dmares)
+			return -EINVAL;
+		devid = pdev->id_entry->driver_data;
+		dma_channel = dmares->start;
+		clk_freq = clk_freq_default;
+	}
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*spi));
+	if (!master)
+		return -ENOMEM;
+
+	master->transfer_one_message = mxs_spi_transfer_one;
+	master->setup = mxs_spi_setup;
+	master->mode_bits = SPI_CPOL | SPI_CPHA;
+	master->num_chipselect = 3;
+	master->dev.of_node = np;
+	master->flags = SPI_MASTER_HALF_DUPLEX;
+
+	spi = spi_master_get_devdata(master);
+	ssp = &spi->ssp;
+	ssp->dev = &pdev->dev;
+	ssp->clk = clk;
+	ssp->base = base;
+	ssp->devid = devid;
+	ssp->dma_channel = dma_channel;
+
+	init_completion(&spi->c);
+
+	ret = devm_request_irq(&pdev->dev, irq_err, mxs_ssp_irq_handler, 0,
+			       DRIVER_NAME, ssp);
+	if (ret)
+		goto out_master_free;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	ssp->dma_data.chan_irq = irq_dma;
+	ssp->dmach = dma_request_channel(mask, mxs_ssp_dma_filter, ssp);
+	if (!ssp->dmach) {
+		dev_err(ssp->dev, "Failed to request DMA\n");
+		goto out_master_free;
+	}
+
+	clk_prepare_enable(ssp->clk);
+	clk_set_rate(ssp->clk, clk_freq);
+	ssp->clk_rate = clk_get_rate(ssp->clk) / 1000;
+
+	stmp_reset_block(ssp->base);
+
+	platform_set_drvdata(pdev, master);
+
+	ret = spi_register_master(master);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
+		goto out_free_dma;
+	}
+
+	return 0;
+
+out_free_dma:
+	dma_release_channel(ssp->dmach);
+	clk_disable_unprepare(ssp->clk);
+out_master_free:
+	spi_master_put(master);
+	return ret;
+}
+
+static int __devexit mxs_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct mxs_spi *spi;
+	struct mxs_ssp *ssp;
+
+	master = spi_master_get(platform_get_drvdata(pdev));
+	spi = spi_master_get_devdata(master);
+	ssp = &spi->ssp;
+
+	spi_unregister_master(master);
+
+	dma_release_channel(ssp->dmach);
+
+	clk_disable_unprepare(ssp->clk);
+
+	spi_master_put(master);
+
+	return 0;
+}
+
+static struct platform_driver mxs_spi_driver = {
+	.probe	= mxs_spi_probe,
+	.remove	= __devexit_p(mxs_spi_remove),
+	.driver	= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = mxs_spi_dt_ids,
+	},
+};
+
+module_platform_driver(mxs_spi_driver);
+
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_DESCRIPTION("MXS SPI master driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-spi");
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 5d59a69a9064..474e2174e08a 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -38,6 +38,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
 
 #include <linux/spi/spi.h>
 
@@ -140,13 +142,6 @@ struct omap2_mcspi_cs {
 	u32			chconf0;
 };
 
-#define MOD_REG_BIT(val, mask, set) do { \
-	if (set) \
-		val |= mask; \
-	else \
-		val &= ~mask; \
-} while (0)
-
 static inline void mcspi_write_reg(struct spi_master *master,
 		int idx, u32 val)
 {
@@ -205,7 +200,11 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
 	else
 		rw = OMAP2_MCSPI_CHCONF_DMAW;
 
-	MOD_REG_BIT(l, rw, enable);
+	if (enable)
+		l |= rw;
+	else
+		l &= ~rw;
+
 	mcspi_write_chconf0(spi, l);
 }
 
@@ -224,7 +223,11 @@ static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
 	u32 l;
 
 	l = mcspi_cached_chconf0(spi);
-	MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
+	if (cs_active)
+		l |= OMAP2_MCSPI_CHCONF_FORCE;
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_FORCE;
+
 	mcspi_write_chconf0(spi, l);
 }
 
@@ -239,9 +242,8 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master)
 	 * to single-channel master mode
 	 */
 	l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
-	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
-	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
-	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+	l &= ~(OMAP2_MCSPI_MODULCTRL_STEST | OMAP2_MCSPI_MODULCTRL_MS);
+	l |= OMAP2_MCSPI_MODULCTRL_SINGLE;
 	mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
 
 	ctx->modulctrl = l;
@@ -260,16 +262,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
 	list_for_each_entry(cs, &ctx->cs, node)
 		__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
 }
-static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
-{
-	pm_runtime_mark_last_busy(mcspi->dev);
-	pm_runtime_put_autosuspend(mcspi->dev);
-}
-
-static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
-{
-	return pm_runtime_get_sync(mcspi->dev);
-}
 
 static int omap2_prepare_transfer(struct spi_master *master)
 {
@@ -325,49 +317,27 @@ static void omap2_mcspi_tx_callback(void *data)
 	omap2_mcspi_set_dma_req(spi, 0, 0);
 }
 
-static unsigned
-omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
+static void omap2_mcspi_tx_dma(struct spi_device *spi,
+				struct spi_transfer *xfer,
+				struct dma_slave_config cfg)
 {
 	struct omap2_mcspi	*mcspi;
-	struct omap2_mcspi_cs	*cs = spi->controller_state;
 	struct omap2_mcspi_dma  *mcspi_dma;
 	unsigned int		count;
-	int			word_len, element_count;
-	int			elements = 0;
-	u32			l;
 	u8			* rx;
 	const u8		* tx;
 	void __iomem		*chstat_reg;
-	struct dma_slave_config	cfg;
-	enum dma_slave_buswidth width;
-	unsigned es;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
 
 	mcspi = spi_master_get_devdata(spi->master);
 	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-	l = mcspi_cached_chconf0(spi);
+	count = xfer->len;
 
+	rx = xfer->rx_buf;
+	tx = xfer->tx_buf;
 	chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
 
-	if (cs->word_len <= 8) {
-		width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-		es = 1;
-	} else if (cs->word_len <= 16) {
-		width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-		es = 2;
-	} else {
-		width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-		es = 4;
-	}
-
-	memset(&cfg, 0, sizeof(cfg));
-	cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0;
-	cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0;
-	cfg.src_addr_width = width;
-	cfg.dst_addr_width = width;
-	cfg.src_maxburst = 1;
-	cfg.dst_maxburst = 1;
-
-	if (xfer->tx_buf && mcspi_dma->dma_tx) {
+	if (mcspi_dma->dma_tx) {
 		struct dma_async_tx_descriptor *tx;
 		struct scatterlist sg;
 
@@ -378,7 +348,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 		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);
+		DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 		if (tx) {
 			tx->callback = omap2_mcspi_tx_callback;
 			tx->callback_param = spi;
@@ -387,8 +357,50 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 			/* FIXME: fall back to PIO? */
 		}
 	}
+	dma_async_issue_pending(mcspi_dma->dma_tx);
+	omap2_mcspi_set_dma_req(spi, 0, 1);
+
+	wait_for_completion(&mcspi_dma->dma_tx_completion);
+	dma_unmap_single(mcspi->dev, xfer->tx_dma, count,
+			 DMA_TO_DEVICE);
+
+	/* for TX_ONLY mode, be sure all words have shifted out */
+	if (rx == NULL) {
+		if (mcspi_wait_for_reg_bit(chstat_reg,
+					OMAP2_MCSPI_CHSTAT_TXS) < 0)
+			dev_err(&spi->dev, "TXS timed out\n");
+		else if (mcspi_wait_for_reg_bit(chstat_reg,
+					OMAP2_MCSPI_CHSTAT_EOT) < 0)
+			dev_err(&spi->dev, "EOT timed out\n");
+	}
+}
+
+static unsigned
+omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
+				struct dma_slave_config cfg,
+				unsigned es)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma  *mcspi_dma;
+	unsigned int		count;
+	u32			l;
+	int			elements = 0;
+	int			word_len, element_count;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+	count = xfer->len;
+	word_len = cs->word_len;
+	l = mcspi_cached_chconf0(spi);
 
-	if (xfer->rx_buf && mcspi_dma->dma_rx) {
+	if (word_len <= 8)
+		element_count = count;
+	else if (word_len <= 16)
+		element_count = count >> 1;
+	else /* word_len <= 32 */
+		element_count = count >> 2;
+
+	if (mcspi_dma->dma_rx) {
 		struct dma_async_tx_descriptor *tx;
 		struct scatterlist sg;
 		size_t len = xfer->len - es;
@@ -403,108 +415,120 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 		sg_dma_len(&sg) = len;
 
 		tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1,
-			DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+				DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT |
+				DMA_CTRL_ACK);
 		if (tx) {
 			tx->callback = omap2_mcspi_rx_callback;
 			tx->callback_param = spi;
 			dmaengine_submit(tx);
 		} else {
-			/* FIXME: fall back to PIO? */
-		}
-	}
-
-	count = xfer->len;
-	word_len = cs->word_len;
-
-	rx = xfer->rx_buf;
-	tx = xfer->tx_buf;
-
-	if (word_len <= 8) {
-		element_count = count;
-	} else if (word_len <= 16) {
-		element_count = count >> 1;
-	} else /* word_len <= 32 */ {
-		element_count = count >> 2;
-	}
-
-	if (tx != NULL) {
-		dma_async_issue_pending(mcspi_dma->dma_tx);
-		omap2_mcspi_set_dma_req(spi, 0, 1);
-	}
-
-	if (rx != NULL) {
-		dma_async_issue_pending(mcspi_dma->dma_rx);
-		omap2_mcspi_set_dma_req(spi, 1, 1);
-	}
-
-	if (tx != NULL) {
-		wait_for_completion(&mcspi_dma->dma_tx_completion);
-		dma_unmap_single(mcspi->dev, xfer->tx_dma, count,
-				 DMA_TO_DEVICE);
-
-		/* for TX_ONLY mode, be sure all words have shifted out */
-		if (rx == NULL) {
-			if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_TXS) < 0)
-				dev_err(&spi->dev, "TXS timed out\n");
-			else if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_EOT) < 0)
-				dev_err(&spi->dev, "EOT timed out\n");
+				/* FIXME: fall back to PIO? */
 		}
 	}
 
-	if (rx != NULL) {
-		wait_for_completion(&mcspi_dma->dma_rx_completion);
-		dma_unmap_single(mcspi->dev, xfer->rx_dma, count,
-				 DMA_FROM_DEVICE);
-		omap2_mcspi_set_enable(spi, 0);
+	dma_async_issue_pending(mcspi_dma->dma_rx);
+	omap2_mcspi_set_dma_req(spi, 1, 1);
 
-		elements = element_count - 1;
+	wait_for_completion(&mcspi_dma->dma_rx_completion);
+	dma_unmap_single(mcspi->dev, xfer->rx_dma, count,
+			 DMA_FROM_DEVICE);
+	omap2_mcspi_set_enable(spi, 0);
 
-		if (l & OMAP2_MCSPI_CHCONF_TURBO) {
-			elements--;
+	elements = element_count - 1;
 
-			if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
-				   & OMAP2_MCSPI_CHSTAT_RXS)) {
-				u32 w;
-
-				w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
-				if (word_len <= 8)
-					((u8 *)xfer->rx_buf)[elements++] = w;
-				else if (word_len <= 16)
-					((u16 *)xfer->rx_buf)[elements++] = w;
-				else /* word_len <= 32 */
-					((u32 *)xfer->rx_buf)[elements++] = w;
-			} else {
-				dev_err(&spi->dev,
-					"DMA RX penultimate word empty");
-				count -= (word_len <= 8)  ? 2 :
-					(word_len <= 16) ? 4 :
-					/* word_len <= 32 */ 8;
-				omap2_mcspi_set_enable(spi, 1);
-				return count;
-			}
-		}
+	if (l & OMAP2_MCSPI_CHCONF_TURBO) {
+		elements--;
 
 		if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
-				& OMAP2_MCSPI_CHSTAT_RXS)) {
+				   & OMAP2_MCSPI_CHSTAT_RXS)) {
 			u32 w;
 
 			w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
 			if (word_len <= 8)
-				((u8 *)xfer->rx_buf)[elements] = w;
+				((u8 *)xfer->rx_buf)[elements++] = w;
 			else if (word_len <= 16)
-				((u16 *)xfer->rx_buf)[elements] = w;
+				((u16 *)xfer->rx_buf)[elements++] = w;
 			else /* word_len <= 32 */
-				((u32 *)xfer->rx_buf)[elements] = w;
+				((u32 *)xfer->rx_buf)[elements++] = w;
 		} else {
-			dev_err(&spi->dev, "DMA RX last word empty");
-			count -= (word_len <= 8)  ? 1 :
-				 (word_len <= 16) ? 2 :
-			       /* word_len <= 32 */ 4;
+			dev_err(&spi->dev, "DMA RX penultimate word empty");
+			count -= (word_len <= 8)  ? 2 :
+				(word_len <= 16) ? 4 :
+				/* word_len <= 32 */ 8;
+			omap2_mcspi_set_enable(spi, 1);
+			return count;
 		}
-		omap2_mcspi_set_enable(spi, 1);
 	}
+	if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
+				& OMAP2_MCSPI_CHSTAT_RXS)) {
+		u32 w;
+
+		w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
+		if (word_len <= 8)
+			((u8 *)xfer->rx_buf)[elements] = w;
+		else if (word_len <= 16)
+			((u16 *)xfer->rx_buf)[elements] = w;
+		else /* word_len <= 32 */
+			((u32 *)xfer->rx_buf)[elements] = w;
+	} else {
+		dev_err(&spi->dev, "DMA RX last word empty");
+		count -= (word_len <= 8)  ? 1 :
+			 (word_len <= 16) ? 2 :
+		       /* word_len <= 32 */ 4;
+	}
+	omap2_mcspi_set_enable(spi, 1);
+	return count;
+}
+
+static unsigned
+omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+	struct omap2_mcspi_dma  *mcspi_dma;
+	unsigned int		count;
+	u32			l;
+	u8			*rx;
+	const u8		*tx;
+	struct dma_slave_config	cfg;
+	enum dma_slave_buswidth width;
+	unsigned es;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+	l = mcspi_cached_chconf0(spi);
+
+
+	if (cs->word_len <= 8) {
+		width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+		es = 1;
+	} else if (cs->word_len <= 16) {
+		width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		es = 2;
+	} else {
+		width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		es = 4;
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0;
+	cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0;
+	cfg.src_addr_width = width;
+	cfg.dst_addr_width = width;
+	cfg.src_maxburst = 1;
+	cfg.dst_maxburst = 1;
+
+	rx = xfer->rx_buf;
+	tx = xfer->tx_buf;
+
+	count = xfer->len;
+
+	if (tx != NULL)
+		omap2_mcspi_tx_dma(spi, xfer, cfg);
+
+	if (rx != NULL)
+		return omap2_mcspi_rx_dma(spi, xfer, cfg, es);
+
 	return count;
 }
 
@@ -848,12 +872,13 @@ static int omap2_mcspi_setup(struct spi_device *spi)
 			return ret;
 	}
 
-	ret = omap2_mcspi_enable_clocks(mcspi);
+	ret = pm_runtime_get_sync(mcspi->dev);
 	if (ret < 0)
 		return ret;
 
 	ret = omap2_mcspi_setup_transfer(spi, NULL);
-	omap2_mcspi_disable_clocks(mcspi);
+	pm_runtime_mark_last_busy(mcspi->dev);
+	pm_runtime_put_autosuspend(mcspi->dev);
 
 	return ret;
 }
@@ -1067,7 +1092,7 @@ static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
 	struct omap2_mcspi_regs	*ctx = &mcspi->ctx;
 	int			ret = 0;
 
-	ret = omap2_mcspi_enable_clocks(mcspi);
+	ret = pm_runtime_get_sync(mcspi->dev);
 	if (ret < 0)
 		return ret;
 
@@ -1076,7 +1101,8 @@ static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
 	ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
 
 	omap2_mcspi_set_master_mode(master);
-	omap2_mcspi_disable_clocks(mcspi);
+	pm_runtime_mark_last_busy(mcspi->dev);
+	pm_runtime_put_autosuspend(mcspi->dev);
 	return 0;
 }
 
@@ -1124,6 +1150,7 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
 	static int		bus_num = 1;
 	struct device_node	*node = pdev->dev.of_node;
 	const struct of_device_id *match;
+	struct pinctrl *pinctrl;
 
 	master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
 	if (master == NULL) {
@@ -1219,6 +1246,11 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
 	if (status < 0)
 		goto dma_chnl_free;
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
 	pm_runtime_enable(&pdev->dev);
@@ -1238,7 +1270,6 @@ dma_chnl_free:
 	kfree(mcspi->dma_channels);
 free_master:
 	spi_master_put(master);
-	platform_set_drvdata(pdev, NULL);
 	return status;
 }
 
@@ -1252,12 +1283,11 @@ static int __devexit omap2_mcspi_remove(struct platform_device *pdev)
 	mcspi = spi_master_get_devdata(master);
 	dma_channels = mcspi->dma_channels;
 
-	omap2_mcspi_disable_clocks(mcspi);
+	pm_runtime_put_sync(mcspi->dev);
 	pm_runtime_disable(&pdev->dev);
 
 	spi_unregister_master(master);
 	kfree(dma_channels);
-	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
@@ -1278,20 +1308,21 @@ static int omap2_mcspi_resume(struct device *dev)
 	struct omap2_mcspi_regs	*ctx = &mcspi->ctx;
 	struct omap2_mcspi_cs	*cs;
 
-	omap2_mcspi_enable_clocks(mcspi);
+	pm_runtime_get_sync(mcspi->dev);
 	list_for_each_entry(cs, &ctx->cs, node) {
 		if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) {
 			/*
 			 * We need to toggle CS state for OMAP take this
 			 * change in account.
 			 */
-			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1);
+			cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE;
 			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
-			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0);
+			cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE;
 			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
 		}
 	}
-	omap2_mcspi_disable_clocks(mcspi);
+	pm_runtime_mark_last_busy(mcspi->dev);
+	pm_runtime_put_autosuspend(mcspi->dev);
 	return 0;
 }
 #else
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 9b0caddce503..b17c09cf0a05 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -36,12 +36,6 @@
 #define ORION_SPI_CLK_PRESCALE_MASK	0x1F
 
 struct orion_spi {
-	struct work_struct	work;
-
-	/* Lock access to transfer list.	*/
-	spinlock_t		lock;
-
-	struct list_head	msg_queue;
 	struct spi_master	*master;
 	void __iomem		*base;
 	unsigned int		max_speed;
@@ -49,8 +43,6 @@ struct orion_spi {
 	struct clk              *clk;
 };
 
-static struct workqueue_struct *orion_spi_wq;
-
 static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
 {
 	return orion_spi->base + reg;
@@ -277,73 +269,78 @@ out:
 }
 
 
-static void orion_spi_work(struct work_struct *work)
+static int orion_spi_transfer_one_message(struct spi_master *master,
+					   struct spi_message *m)
 {
-	struct orion_spi *orion_spi =
-		container_of(work, struct orion_spi, work);
-
-	spin_lock_irq(&orion_spi->lock);
-	while (!list_empty(&orion_spi->msg_queue)) {
-		struct spi_message *m;
-		struct spi_device *spi;
-		struct spi_transfer *t = NULL;
-		int par_override = 0;
-		int status = 0;
-		int cs_active = 0;
-
-		m = container_of(orion_spi->msg_queue.next, struct spi_message,
-				 queue);
+	struct orion_spi *orion_spi = spi_master_get_devdata(master);
+	struct spi_device *spi = m->spi;
+	struct spi_transfer *t = NULL;
+	int par_override = 0;
+	int status = 0;
+	int cs_active = 0;
 
-		list_del_init(&m->queue);
-		spin_unlock_irq(&orion_spi->lock);
+	/* Load defaults */
+	status = orion_spi_setup_transfer(spi, NULL);
 
-		spi = m->spi;
+	if (status < 0)
+		goto msg_done;
 
-		/* Load defaults */
-		status = orion_spi_setup_transfer(spi, NULL);
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		/* make sure buffer length is even when working in 16
+		 * bit mode*/
+		if ((t->bits_per_word == 16) && (t->len & 1)) {
+			dev_err(&spi->dev,
+				"message rejected : "
+				"odd data length %d while in 16 bit mode\n",
+				t->len);
+			status = -EIO;
+			goto msg_done;
+		}
 
-		if (status < 0)
+		if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
+			dev_err(&spi->dev,
+				"message rejected : "
+				"device min speed (%d Hz) exceeds "
+				"required transfer speed (%d Hz)\n",
+				orion_spi->min_speed, t->speed_hz);
+			status = -EIO;
 			goto msg_done;
+		}
 
-		list_for_each_entry(t, &m->transfers, transfer_list) {
-			if (par_override || t->speed_hz || t->bits_per_word) {
-				par_override = 1;
-				status = orion_spi_setup_transfer(spi, t);
-				if (status < 0)
-					break;
-				if (!t->speed_hz && !t->bits_per_word)
-					par_override = 0;
-			}
-
-			if (!cs_active) {
-				orion_spi_set_cs(orion_spi, 1);
-				cs_active = 1;
-			}
-
-			if (t->len)
-				m->actual_length +=
-					orion_spi_write_read(spi, t);
-
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
-
-			if (t->cs_change) {
-				orion_spi_set_cs(orion_spi, 0);
-				cs_active = 0;
-			}
+		if (par_override || t->speed_hz || t->bits_per_word) {
+			par_override = 1;
+			status = orion_spi_setup_transfer(spi, t);
+			if (status < 0)
+				break;
+			if (!t->speed_hz && !t->bits_per_word)
+				par_override = 0;
 		}
 
-msg_done:
-		if (cs_active)
-			orion_spi_set_cs(orion_spi, 0);
+		if (!cs_active) {
+			orion_spi_set_cs(orion_spi, 1);
+			cs_active = 1;
+		}
 
-		m->status = status;
-		m->complete(m->context);
+		if (t->len)
+			m->actual_length += orion_spi_write_read(spi, t);
 
-		spin_lock_irq(&orion_spi->lock);
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+
+		if (t->cs_change) {
+			orion_spi_set_cs(orion_spi, 0);
+			cs_active = 0;
+		}
 	}
 
-	spin_unlock_irq(&orion_spi->lock);
+msg_done:
+	if (cs_active)
+		orion_spi_set_cs(orion_spi, 0);
+
+	m->status = status;
+	spi_finalize_current_message(master);
+
+	return 0;
 }
 
 static int __init orion_spi_reset(struct orion_spi *orion_spi)
@@ -376,75 +373,6 @@ static int orion_spi_setup(struct spi_device *spi)
 	return 0;
 }
 
-static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct orion_spi *orion_spi;
-	struct spi_transfer *t = NULL;
-	unsigned long flags;
-
-	m->actual_length = 0;
-	m->status = 0;
-
-	/* reject invalid messages and transfers */
-	if (list_empty(&m->transfers) || !m->complete)
-		return -EINVAL;
-
-	orion_spi = spi_master_get_devdata(spi->master);
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		unsigned int bits_per_word = spi->bits_per_word;
-
-		if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"invalid transfer data buffers\n");
-			goto msg_rejected;
-		}
-
-		if (t->bits_per_word)
-			bits_per_word = t->bits_per_word;
-
-		if ((bits_per_word != 8) && (bits_per_word != 16)) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"invalid transfer bits_per_word (%d bits)\n",
-				bits_per_word);
-			goto msg_rejected;
-		}
-		/*make sure buffer length is even when working in 16 bit mode*/
-		if ((t->bits_per_word == 16) && (t->len & 1)) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"odd data length (%d) while in 16 bit mode\n",
-				t->len);
-			goto msg_rejected;
-		}
-
-		if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"device min speed (%d Hz) exceeds "
-				"required transfer speed (%d Hz)\n",
-				orion_spi->min_speed, t->speed_hz);
-			goto msg_rejected;
-		}
-	}
-
-
-	spin_lock_irqsave(&orion_spi->lock, flags);
-	list_add_tail(&m->queue, &orion_spi->msg_queue);
-	queue_work(orion_spi_wq, &orion_spi->work);
-	spin_unlock_irqrestore(&orion_spi->lock, flags);
-
-	return 0;
-msg_rejected:
-	/* Message rejected and not queued */
-	m->status = -EINVAL;
-	if (m->complete)
-		m->complete(m->context);
-	return -EINVAL;
-}
-
 static int __init orion_spi_probe(struct platform_device *pdev)
 {
 	struct spi_master *master;
@@ -474,7 +402,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)
 	master->mode_bits = 0;
 
 	master->setup = orion_spi_setup;
-	master->transfer = orion_spi_transfer;
+	master->transfer_one_message = orion_spi_transfer_one_message;
 	master->num_chipselect = ORION_NUM_CHIPSELECTS;
 
 	dev_set_drvdata(&pdev->dev, master);
@@ -507,11 +435,6 @@ static int __init orion_spi_probe(struct platform_device *pdev)
 	}
 	spi->base = ioremap(r->start, SZ_1K);
 
-	INIT_WORK(&spi->work, orion_spi_work);
-
-	spin_lock_init(&spi->lock);
-	INIT_LIST_HEAD(&spi->msg_queue);
-
 	if (orion_spi_reset(spi) < 0)
 		goto out_rel_mem;
 
@@ -536,14 +459,12 @@ out:
 static int __exit orion_spi_remove(struct platform_device *pdev)
 {
 	struct spi_master *master;
-	struct orion_spi *spi;
 	struct resource *r;
+	struct orion_spi *spi;
 
 	master = dev_get_drvdata(&pdev->dev);
 	spi = spi_master_get_devdata(master);
 
-	cancel_work_sync(&spi->work);
-
 	clk_disable_unprepare(spi->clk);
 	clk_put(spi->clk);
 
@@ -574,21 +495,13 @@ static struct platform_driver orion_spi_driver = {
 
 static int __init orion_spi_init(void)
 {
-	orion_spi_wq = create_singlethread_workqueue(
-				orion_spi_driver.driver.name);
-	if (orion_spi_wq == NULL)
-		return -ENOMEM;
-
 	return platform_driver_probe(&orion_spi_driver, orion_spi_probe);
 }
 module_init(orion_spi_init);
 
 static void __exit orion_spi_exit(void)
 {
-	flush_workqueue(orion_spi_wq);
 	platform_driver_unregister(&orion_spi_driver);
-
-	destroy_workqueue(orion_spi_wq);
 }
 module_exit(orion_spi_exit);
 
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 6abbe23c39b4..919464102d33 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1,7 +1,7 @@
 /*
  * A driver for the ARM PL022 PrimeCell SSP/SPI bus master.
  *
- * Copyright (C) 2008-2009 ST-Ericsson AB
+ * Copyright (C) 2008-2012 ST-Ericsson AB
  * Copyright (C) 2006 STMicroelectronics Pvt. Ltd.
  *
  * Author: Linus Walleij <linus.walleij@stericsson.com>
@@ -40,6 +40,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 #include <linux/pm_runtime.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
 
 /*
  * This macro is used to define some register default values.
@@ -356,6 +359,8 @@ struct vendor_data {
  * @sgt_rx: scattertable for the RX transfer
  * @sgt_tx: scattertable for the TX transfer
  * @dummypage: a dummy page used for driving data on the bus with DMA
+ * @cur_cs: current chip select (gpio)
+ * @chipselects: list of chipselects (gpios)
  */
 struct pl022 {
 	struct amba_device		*adev;
@@ -363,6 +368,10 @@ struct pl022 {
 	resource_size_t			phybase;
 	void __iomem			*virtbase;
 	struct clk			*clk;
+	/* Two optional pin states - default & sleep */
+	struct pinctrl			*pinctrl;
+	struct pinctrl_state		*pins_default;
+	struct pinctrl_state		*pins_sleep;
 	struct spi_master		*master;
 	struct pl022_ssp_controller	*master_info;
 	/* Message per-transfer pump */
@@ -389,6 +398,8 @@ struct pl022 {
 	char				*dummypage;
 	bool				dma_running;
 #endif
+	int cur_cs;
+	int *chipselects;
 };
 
 /**
@@ -433,6 +444,14 @@ static void null_cs_control(u32 command)
 	pr_debug("pl022: dummy chip select control, CS=0x%x\n", command);
 }
 
+static void pl022_cs_control(struct pl022 *pl022, u32 command)
+{
+	if (gpio_is_valid(pl022->cur_cs))
+		gpio_set_value(pl022->cur_cs, command);
+	else
+		pl022->cur_chip->cs_control(command);
+}
+
 /**
  * giveback - current spi_message is over, schedule next message and call
  * callback of this message. Assumes that caller already
@@ -479,7 +498,7 @@ static void giveback(struct pl022 *pl022)
 		if (next_msg && next_msg->spi != pl022->cur_msg->spi)
 			next_msg = NULL;
 		if (!next_msg || pl022->cur_msg->state == STATE_ERROR)
-			pl022->cur_chip->cs_control(SSP_CHIP_DESELECT);
+			pl022_cs_control(pl022, SSP_CHIP_DESELECT);
 		else
 			pl022->next_msg_cs_active = true;
 
@@ -818,8 +837,7 @@ static void dma_callback(void *data)
 	/* Update total bytes transferred */
 	msg->actual_length += pl022->cur_transfer->len;
 	if (pl022->cur_transfer->cs_change)
-		pl022->cur_chip->
-			cs_control(SSP_CHIP_DESELECT);
+		pl022_cs_control(pl022, SSP_CHIP_DESELECT);
 
 	/* Move to next transfer */
 	msg->state = next_transfer(pl022);
@@ -1252,8 +1270,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
 		/* Update total bytes transferred */
 		msg->actual_length += pl022->cur_transfer->len;
 		if (pl022->cur_transfer->cs_change)
-			pl022->cur_chip->
-				cs_control(SSP_CHIP_DESELECT);
+			pl022_cs_control(pl022, SSP_CHIP_DESELECT);
 		/* Move to next transfer */
 		msg->state = next_transfer(pl022);
 		tasklet_schedule(&pl022->pump_transfers);
@@ -1338,7 +1355,7 @@ static void pump_transfers(unsigned long data)
 
 		/* Reselect chip select only if cs_change was requested */
 		if (previous->cs_change)
-			pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
+			pl022_cs_control(pl022, SSP_CHIP_SELECT);
 	} else {
 		/* STATE_START */
 		message->state = STATE_RUNNING;
@@ -1377,7 +1394,7 @@ static void do_interrupt_dma_transfer(struct pl022 *pl022)
 
 	/* Enable target chip, if not already active */
 	if (!pl022->next_msg_cs_active)
-		pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
+		pl022_cs_control(pl022, SSP_CHIP_SELECT);
 
 	if (set_up_next_transfer(pl022, pl022->cur_transfer)) {
 		/* Error path */
@@ -1429,12 +1446,12 @@ static void do_polling_transfer(struct pl022 *pl022)
 			if (previous->delay_usecs)
 				udelay(previous->delay_usecs);
 			if (previous->cs_change)
-				pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
+				pl022_cs_control(pl022, SSP_CHIP_SELECT);
 		} else {
 			/* STATE_START */
 			message->state = STATE_RUNNING;
 			if (!pl022->next_msg_cs_active)
-				pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
+				pl022_cs_control(pl022, SSP_CHIP_SELECT);
 		}
 
 		/* Configuration Changing Per Transfer */
@@ -1466,7 +1483,7 @@ static void do_polling_transfer(struct pl022 *pl022)
 		/* Update total byte transferred */
 		message->actual_length += pl022->cur_transfer->len;
 		if (pl022->cur_transfer->cs_change)
-			pl022->cur_chip->cs_control(SSP_CHIP_DESELECT);
+			pl022_cs_control(pl022, SSP_CHIP_DESELECT);
 		/* Move to next transfer */
 		message->state = next_transfer(pl022);
 	}
@@ -1495,6 +1512,7 @@ static int pl022_transfer_one_message(struct spi_master *master,
 
 	/* Setup the SPI using the per chip configuration */
 	pl022->cur_chip = spi_get_ctldata(msg->spi);
+	pl022->cur_cs = pl022->chipselects[msg->spi->chip_select];
 
 	restore_state(pl022);
 	flush(pl022);
@@ -1766,12 +1784,14 @@ static const struct pl022_config_chip pl022_default_chip_info = {
 static int pl022_setup(struct spi_device *spi)
 {
 	struct pl022_config_chip const *chip_info;
+	struct pl022_config_chip chip_info_dt;
 	struct chip_data *chip;
 	struct ssp_clock_params clk_freq = { .cpsdvsr = 0, .scr = 0};
 	int status = 0;
 	struct pl022 *pl022 = spi_master_get_devdata(spi->master);
 	unsigned int bits = spi->bits_per_word;
 	u32 tmp;
+	struct device_node *np = spi->dev.of_node;
 
 	if (!spi->max_speed_hz)
 		return -EINVAL;
@@ -1794,10 +1814,32 @@ static int pl022_setup(struct spi_device *spi)
 	chip_info = spi->controller_data;
 
 	if (chip_info == NULL) {
-		chip_info = &pl022_default_chip_info;
-		/* spi_board_info.controller_data not is supplied */
-		dev_dbg(&spi->dev,
-			"using default controller_data settings\n");
+		if (np) {
+			chip_info_dt = pl022_default_chip_info;
+
+			chip_info_dt.hierarchy = SSP_MASTER;
+			of_property_read_u32(np, "pl022,interface",
+				&chip_info_dt.iface);
+			of_property_read_u32(np, "pl022,com-mode",
+				&chip_info_dt.com_mode);
+			of_property_read_u32(np, "pl022,rx-level-trig",
+				&chip_info_dt.rx_lev_trig);
+			of_property_read_u32(np, "pl022,tx-level-trig",
+				&chip_info_dt.tx_lev_trig);
+			of_property_read_u32(np, "pl022,ctrl-len",
+				&chip_info_dt.ctrl_len);
+			of_property_read_u32(np, "pl022,wait-state",
+				&chip_info_dt.wait_state);
+			of_property_read_u32(np, "pl022,duplex",
+				&chip_info_dt.duplex);
+
+			chip_info = &chip_info_dt;
+		} else {
+			chip_info = &pl022_default_chip_info;
+			/* spi_board_info.controller_data not is supplied */
+			dev_dbg(&spi->dev,
+				"using default controller_data settings\n");
+		}
 	} else
 		dev_dbg(&spi->dev,
 			"using user supplied controller_data settings\n");
@@ -1840,8 +1882,9 @@ static int pl022_setup(struct spi_device *spi)
 	chip->xfer_type = chip_info->com_mode;
 	if (!chip_info->cs_control) {
 		chip->cs_control = null_cs_control;
-		dev_warn(&spi->dev,
-			 "chip select function is NULL for this chip\n");
+		if (!gpio_is_valid(pl022->chipselects[spi->chip_select]))
+			dev_warn(&spi->dev,
+				 "invalid chip select\n");
 	} else
 		chip->cs_control = chip_info->cs_control;
 
@@ -1986,6 +2029,34 @@ static void pl022_cleanup(struct spi_device *spi)
 	kfree(chip);
 }
 
+static struct pl022_ssp_controller *
+pl022_platform_data_dt_get(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct pl022_ssp_controller *pd;
+	u32 tmp;
+
+	if (!np) {
+		dev_err(dev, "no dt node defined\n");
+		return NULL;
+	}
+
+	pd = devm_kzalloc(dev, sizeof(struct pl022_ssp_controller), GFP_KERNEL);
+	if (!pd) {
+		dev_err(dev, "cannot allocate platform data memory\n");
+		return NULL;
+	}
+
+	pd->bus_id = -1;
+	of_property_read_u32(np, "num-cs", &tmp);
+	pd->num_chipselect = tmp;
+	of_property_read_u32(np, "pl022,autosuspend-delay",
+			     &pd->autosuspend_delay);
+	pd->rt = of_property_read_bool(np, "pl022,rt");
+
+	return pd;
+}
+
 static int __devinit
 pl022_probe(struct amba_device *adev, const struct amba_id *id)
 {
@@ -1993,22 +2064,31 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
 	struct spi_master *master;
 	struct pl022 *pl022 = NULL;	/*Data for this driver */
-	int status = 0;
+	struct device_node *np = adev->dev.of_node;
+	int status = 0, i, num_cs;
 
 	dev_info(&adev->dev,
 		 "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
-	if (platform_info == NULL) {
-		dev_err(&adev->dev, "probe - no platform data supplied\n");
-		status = -ENODEV;
-		goto err_no_pdata;
+	if (!platform_info && IS_ENABLED(CONFIG_OF))
+		platform_info = pl022_platform_data_dt_get(dev);
+
+	if (!platform_info) {
+		dev_err(dev, "probe: no platform data defined\n");
+		return -ENODEV;
+	}
+
+	if (platform_info->num_chipselect) {
+		num_cs = platform_info->num_chipselect;
+	} else {
+		dev_err(dev, "probe: no chip select defined\n");
+		return -ENODEV;
 	}
 
 	/* Allocate master with space for data */
 	master = spi_alloc_master(dev, sizeof(struct pl022));
 	if (master == NULL) {
 		dev_err(&adev->dev, "probe - cannot alloc SPI master\n");
-		status = -ENOMEM;
-		goto err_no_master;
+		return -ENOMEM;
 	}
 
 	pl022 = spi_master_get_devdata(master);
@@ -2016,19 +2096,71 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	pl022->master_info = platform_info;
 	pl022->adev = adev;
 	pl022->vendor = id->data;
+	pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int),
+					  GFP_KERNEL);
+
+	pl022->pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR(pl022->pinctrl)) {
+		status = PTR_ERR(pl022->pinctrl);
+		goto err_no_pinctrl;
+	}
+
+	pl022->pins_default = pinctrl_lookup_state(pl022->pinctrl,
+						 PINCTRL_STATE_DEFAULT);
+	/* enable pins to be muxed in and configured */
+	if (!IS_ERR(pl022->pins_default)) {
+		status = pinctrl_select_state(pl022->pinctrl,
+				pl022->pins_default);
+		if (status)
+			dev_err(dev, "could not set default pins\n");
+	} else
+		dev_err(dev, "could not get default pinstate\n");
+
+	pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl,
+					       PINCTRL_STATE_SLEEP);
+	if (IS_ERR(pl022->pins_sleep))
+		dev_dbg(dev, "could not get sleep pinstate\n");
 
 	/*
 	 * Bus Number Which has been Assigned to this SSP controller
 	 * on this board
 	 */
 	master->bus_num = platform_info->bus_id;
-	master->num_chipselect = platform_info->num_chipselect;
+	master->num_chipselect = num_cs;
 	master->cleanup = pl022_cleanup;
 	master->setup = pl022_setup;
 	master->prepare_transfer_hardware = pl022_prepare_transfer_hardware;
 	master->transfer_one_message = pl022_transfer_one_message;
 	master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
 	master->rt = platform_info->rt;
+	master->dev.of_node = dev->of_node;
+
+	if (platform_info->num_chipselect && platform_info->chipselects) {
+		for (i = 0; i < num_cs; i++)
+			pl022->chipselects[i] = platform_info->chipselects[i];
+	} else if (IS_ENABLED(CONFIG_OF)) {
+		for (i = 0; i < num_cs; i++) {
+			int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
+
+			if (cs_gpio == -EPROBE_DEFER) {
+				status = -EPROBE_DEFER;
+				goto err_no_gpio;
+			}
+
+			pl022->chipselects[i] = cs_gpio;
+
+			if (gpio_is_valid(cs_gpio)) {
+				if (devm_gpio_request(dev, cs_gpio, "ssp-pl022"))
+					dev_err(&adev->dev,
+						"could not request %d gpio\n",
+						cs_gpio);
+				else if (gpio_direction_output(cs_gpio, 1))
+					dev_err(&adev->dev,
+						"could set gpio %d as output\n",
+						cs_gpio);
+			}
+		}
+	}
 
 	/*
 	 * Supports mode 0-3, loopback, and active low CS. Transfers are
@@ -2045,7 +2177,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 		goto err_no_ioregion;
 
 	pl022->phybase = adev->res.start;
-	pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
+	pl022->virtbase = devm_ioremap(dev, adev->res.start,
+				       resource_size(&adev->res));
 	if (pl022->virtbase == NULL) {
 		status = -ENOMEM;
 		goto err_no_ioremap;
@@ -2055,7 +2188,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 
 	pm_runtime_resume(dev);
 
-	pl022->clk = clk_get(&adev->dev, NULL);
+	pl022->clk = devm_clk_get(&adev->dev, NULL);
 	if (IS_ERR(pl022->clk)) {
 		status = PTR_ERR(pl022->clk);
 		dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
@@ -2083,8 +2216,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	       SSP_CR1(pl022->virtbase));
 	load_ssp_default_config(pl022);
 
-	status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
-			     pl022);
+	status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
+				  0, "pl022", pl022);
 	if (status < 0) {
 		dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
 		goto err_no_irq;
@@ -2124,22 +2257,18 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
  err_spi_register:
 	if (platform_info->enable_dma)
 		pl022_dma_remove(pl022);
-
-	free_irq(adev->irq[0], pl022);
  err_no_irq:
 	clk_disable(pl022->clk);
  err_no_clk_en:
 	clk_unprepare(pl022->clk);
  err_clk_prep:
-	clk_put(pl022->clk);
  err_no_clk:
-	iounmap(pl022->virtbase);
  err_no_ioremap:
 	amba_release_regions(adev);
  err_no_ioregion:
+ err_no_gpio:
+ err_no_pinctrl:
 	spi_master_put(master);
- err_no_master:
- err_no_pdata:
 	return status;
 }
 
@@ -2161,20 +2290,55 @@ pl022_remove(struct amba_device *adev)
 	if (pl022->master_info->enable_dma)
 		pl022_dma_remove(pl022);
 
-	free_irq(adev->irq[0], pl022);
 	clk_disable(pl022->clk);
 	clk_unprepare(pl022->clk);
-	clk_put(pl022->clk);
 	pm_runtime_disable(&adev->dev);
-	iounmap(pl022->virtbase);
 	amba_release_regions(adev);
 	tasklet_disable(&pl022->pump_transfers);
 	spi_unregister_master(pl022->master);
-	spi_master_put(pl022->master);
 	amba_set_drvdata(adev, NULL);
 	return 0;
 }
 
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME)
+/*
+ * These two functions are used from both suspend/resume and
+ * the runtime counterparts to handle external resources like
+ * clocks, pins and regulators when going to sleep.
+ */
+static void pl022_suspend_resources(struct pl022 *pl022)
+{
+	int ret;
+
+	clk_disable(pl022->clk);
+
+	/* Optionally let pins go into sleep states */
+	if (!IS_ERR(pl022->pins_sleep)) {
+		ret = pinctrl_select_state(pl022->pinctrl,
+					   pl022->pins_sleep);
+		if (ret)
+			dev_err(&pl022->adev->dev,
+				"could not set pins to sleep state\n");
+	}
+}
+
+static void pl022_resume_resources(struct pl022 *pl022)
+{
+	int ret;
+
+	/* Optionaly enable pins to be muxed in and configured */
+	if (!IS_ERR(pl022->pins_default)) {
+		ret = pinctrl_select_state(pl022->pinctrl,
+					   pl022->pins_default);
+		if (ret)
+			dev_err(&pl022->adev->dev,
+				"could not set default pins\n");
+	}
+
+	clk_enable(pl022->clk);
+}
+#endif
+
 #ifdef CONFIG_SUSPEND
 static int pl022_suspend(struct device *dev)
 {
@@ -2186,6 +2350,7 @@ static int pl022_suspend(struct device *dev)
 		dev_warn(dev, "cannot suspend master\n");
 		return ret;
 	}
+	pl022_suspend_resources(pl022);
 
 	dev_dbg(dev, "suspended\n");
 	return 0;
@@ -2196,6 +2361,8 @@ static int pl022_resume(struct device *dev)
 	struct pl022 *pl022 = dev_get_drvdata(dev);
 	int ret;
 
+	pl022_resume_resources(pl022);
+
 	/* Start the queue running */
 	ret = spi_master_resume(pl022->master);
 	if (ret)
@@ -2212,8 +2379,7 @@ static int pl022_runtime_suspend(struct device *dev)
 {
 	struct pl022 *pl022 = dev_get_drvdata(dev);
 
-	clk_disable(pl022->clk);
-
+	pl022_suspend_resources(pl022);
 	return 0;
 }
 
@@ -2221,8 +2387,7 @@ static int pl022_runtime_resume(struct device *dev)
 {
 	struct pl022 *pl022 = dev_get_drvdata(dev);
 
-	clk_enable(pl022->clk);
-
+	pl022_resume_resources(pl022);
 	return 0;
 }
 #endif
diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index 8ee7d790ce49..a2a080b7f42b 100644
--- a/drivers/spi/spi-s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -611,6 +611,7 @@ static int __devinit s3c24xx_spi_probe(struct platform_device *pdev)
 	if (!pdata->set_cs) {
 		if (pdata->pin_cs < 0) {
 			dev_err(&pdev->dev, "No chipselect pin\n");
+			err = -EINVAL;
 			goto err_register;
 		}
 
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 0e2a02228d5e..1860c3aca7e2 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -976,7 +976,8 @@ err_msgq:
 	spi_set_ctldata(spi, NULL);
 
 err_gpio_req:
-	kfree(cs);
+	if (spi->dev.of_node)
+		kfree(cs);
 
 	return err;
 }
@@ -1409,7 +1410,7 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int s3c64xx_spi_suspend(struct device *dev)
 {
-	struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
+	struct spi_master *master = dev_get_drvdata(dev);
 	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
 	spi_master_suspend(master);
@@ -1428,7 +1429,7 @@ static int s3c64xx_spi_suspend(struct device *dev)
 
 static int s3c64xx_spi_resume(struct device *dev)
 {
-	struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
+	struct spi_master *master = dev_get_drvdata(dev);
 	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
 
@@ -1452,7 +1453,7 @@ static int s3c64xx_spi_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 static int s3c64xx_spi_runtime_suspend(struct device *dev)
 {
-	struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
+	struct spi_master *master = dev_get_drvdata(dev);
 	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
 	clk_disable(sdd->clk);
@@ -1463,7 +1464,7 @@ static int s3c64xx_spi_runtime_suspend(struct device *dev)
 
 static int s3c64xx_spi_runtime_resume(struct device *dev)
 {
-	struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
+	struct spi_master *master = dev_get_drvdata(dev);
 	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
 	clk_enable(sdd->src_clk);
diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c
new file mode 100644
index 000000000000..9eda21d739c6
--- /dev/null
+++ b/drivers/spi/spi-sc18is602.c
@@ -0,0 +1,364 @@
+/*
+ * NXP SC18IS602/603 SPI driver
+ *
+ * Copyright (C) Guenter Roeck <linux@roeck-us.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/platform_data/sc18is602.h>
+
+enum chips { sc18is602, sc18is602b, sc18is603 };
+
+#define SC18IS602_BUFSIZ		200
+#define SC18IS602_CLOCK			7372000
+
+#define SC18IS602_MODE_CPHA		BIT(2)
+#define SC18IS602_MODE_CPOL		BIT(3)
+#define SC18IS602_MODE_LSB_FIRST	BIT(5)
+#define SC18IS602_MODE_CLOCK_DIV_4	0x0
+#define SC18IS602_MODE_CLOCK_DIV_16	0x1
+#define SC18IS602_MODE_CLOCK_DIV_64	0x2
+#define SC18IS602_MODE_CLOCK_DIV_128	0x3
+
+struct sc18is602 {
+	struct spi_master	*master;
+	struct device		*dev;
+	u8			ctrl;
+	u32			freq;
+	u32			speed;
+
+	/* I2C data */
+	struct i2c_client	*client;
+	enum chips		id;
+	u8			buffer[SC18IS602_BUFSIZ + 1];
+	int			tlen;	/* Data queued for tx in buffer */
+	int			rindex;	/* Receive data index in buffer */
+};
+
+static int sc18is602_wait_ready(struct sc18is602 *hw, int len)
+{
+	int i, err;
+	int usecs = 1000000 * len / hw->speed + 1;
+	u8 dummy[1];
+
+	for (i = 0; i < 10; i++) {
+		err = i2c_master_recv(hw->client, dummy, 1);
+		if (err >= 0)
+			return 0;
+		usleep_range(usecs, usecs * 2);
+	}
+	return -ETIMEDOUT;
+}
+
+static int sc18is602_txrx(struct sc18is602 *hw, struct spi_message *msg,
+			  struct spi_transfer *t, bool do_transfer)
+{
+	unsigned int len = t->len;
+	int ret;
+
+	if (hw->tlen == 0) {
+		/* First byte (I2C command) is chip select */
+		hw->buffer[0] = 1 << msg->spi->chip_select;
+		hw->tlen = 1;
+		hw->rindex = 0;
+	}
+	/*
+	 * We can not immediately send data to the chip, since each I2C message
+	 * resembles a full SPI message (from CS active to CS inactive).
+	 * Enqueue messages up to the first read or until do_transfer is true.
+	 */
+	if (t->tx_buf) {
+		memcpy(&hw->buffer[hw->tlen], t->tx_buf, len);
+		hw->tlen += len;
+		if (t->rx_buf)
+			do_transfer = true;
+		else
+			hw->rindex = hw->tlen - 1;
+	} else if (t->rx_buf) {
+		/*
+		 * For receive-only transfers we still need to perform a dummy
+		 * write to receive data from the SPI chip.
+		 * Read data starts at the end of transmit data (minus 1 to
+		 * account for CS).
+		 */
+		hw->rindex = hw->tlen - 1;
+		memset(&hw->buffer[hw->tlen], 0, len);
+		hw->tlen += len;
+		do_transfer = true;
+	}
+
+	if (do_transfer && hw->tlen > 1) {
+		ret = sc18is602_wait_ready(hw, SC18IS602_BUFSIZ);
+		if (ret < 0)
+			return ret;
+		ret = i2c_master_send(hw->client, hw->buffer, hw->tlen);
+		if (ret < 0)
+			return ret;
+		if (ret != hw->tlen)
+			return -EIO;
+
+		if (t->rx_buf) {
+			int rlen = hw->rindex + len;
+
+			ret = sc18is602_wait_ready(hw, hw->tlen);
+			if (ret < 0)
+				return ret;
+			ret = i2c_master_recv(hw->client, hw->buffer, rlen);
+			if (ret < 0)
+				return ret;
+			if (ret != rlen)
+				return -EIO;
+			memcpy(t->rx_buf, &hw->buffer[hw->rindex], len);
+		}
+		hw->tlen = 0;
+	}
+	return len;
+}
+
+static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode)
+{
+	u8 ctrl = 0;
+	int ret;
+
+	if (mode & SPI_CPHA)
+		ctrl |= SC18IS602_MODE_CPHA;
+	if (mode & SPI_CPOL)
+		ctrl |= SC18IS602_MODE_CPOL;
+	if (mode & SPI_LSB_FIRST)
+		ctrl |= SC18IS602_MODE_LSB_FIRST;
+
+	/* Find the closest clock speed */
+	if (hz >= hw->freq / 4) {
+		ctrl |= SC18IS602_MODE_CLOCK_DIV_4;
+		hw->speed = hw->freq / 4;
+	} else if (hz >= hw->freq / 16) {
+		ctrl |= SC18IS602_MODE_CLOCK_DIV_16;
+		hw->speed = hw->freq / 16;
+	} else if (hz >= hw->freq / 64) {
+		ctrl |= SC18IS602_MODE_CLOCK_DIV_64;
+		hw->speed = hw->freq / 64;
+	} else {
+		ctrl |= SC18IS602_MODE_CLOCK_DIV_128;
+		hw->speed = hw->freq / 128;
+	}
+
+	/*
+	 * Don't do anything if the control value did not change. The initial
+	 * value of 0xff for hw->ctrl ensures that the correct mode will be set
+	 * with the first call to this function.
+	 */
+	if (ctrl == hw->ctrl)
+		return 0;
+
+	ret = i2c_smbus_write_byte_data(hw->client, 0xf0, ctrl);
+	if (ret < 0)
+		return ret;
+
+	hw->ctrl = ctrl;
+
+	return 0;
+}
+
+static int sc18is602_check_transfer(struct spi_device *spi,
+				    struct spi_transfer *t, int tlen)
+{
+	int bpw;
+	uint32_t hz;
+
+	if (t && t->len + tlen > SC18IS602_BUFSIZ)
+		return -EINVAL;
+
+	bpw = spi->bits_per_word;
+	if (t && t->bits_per_word)
+		bpw = t->bits_per_word;
+	if (bpw != 8)
+		return -EINVAL;
+
+	hz = spi->max_speed_hz;
+	if (t && t->speed_hz)
+		hz = t->speed_hz;
+	if (hz == 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int sc18is602_transfer_one(struct spi_master *master,
+				  struct spi_message *m)
+{
+	struct sc18is602 *hw = spi_master_get_devdata(master);
+	struct spi_device *spi = m->spi;
+	struct spi_transfer *t;
+	int status = 0;
+
+	/* SC18IS602 does not support CS2 */
+	if (hw->id == sc18is602 && spi->chip_select == 2) {
+		status = -ENXIO;
+		goto error;
+	}
+
+	hw->tlen = 0;
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		u32 hz = t->speed_hz ? : spi->max_speed_hz;
+		bool do_transfer;
+
+		status = sc18is602_check_transfer(spi, t, hw->tlen);
+		if (status < 0)
+			break;
+
+		status = sc18is602_setup_transfer(hw, hz, spi->mode);
+		if (status < 0)
+			break;
+
+		do_transfer = t->cs_change || list_is_last(&t->transfer_list,
+							   &m->transfers);
+
+		if (t->len) {
+			status = sc18is602_txrx(hw, m, t, do_transfer);
+			if (status < 0)
+				break;
+			m->actual_length += status;
+		}
+		status = 0;
+
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+	}
+error:
+	m->status = status;
+	spi_finalize_current_message(master);
+
+	return status;
+}
+
+static int sc18is602_setup(struct spi_device *spi)
+{
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	if (spi->mode & ~(SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST))
+		return -EINVAL;
+
+	return sc18is602_check_transfer(spi, NULL, 0);
+}
+
+static int sc18is602_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct device_node *np = dev->of_node;
+	struct sc18is602_platform_data *pdata = dev_get_platdata(dev);
+	struct sc18is602 *hw;
+	struct spi_master *master;
+	int error;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+				     I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -EINVAL;
+
+	master = spi_alloc_master(dev, sizeof(struct sc18is602));
+	if (!master)
+		return -ENOMEM;
+
+	hw = spi_master_get_devdata(master);
+	i2c_set_clientdata(client, hw);
+
+	hw->master = master;
+	hw->client = client;
+	hw->dev = dev;
+	hw->ctrl = 0xff;
+
+	hw->id = id->driver_data;
+
+	switch (hw->id) {
+	case sc18is602:
+	case sc18is602b:
+		master->num_chipselect = 4;
+		hw->freq = SC18IS602_CLOCK;
+		break;
+	case sc18is603:
+		master->num_chipselect = 2;
+		if (pdata) {
+			hw->freq = pdata->clock_frequency;
+		} else {
+			const __be32 *val;
+			int len;
+
+			val = of_get_property(np, "clock-frequency", &len);
+			if (val && len >= sizeof(__be32))
+				hw->freq = be32_to_cpup(val);
+		}
+		if (!hw->freq)
+			hw->freq = SC18IS602_CLOCK;
+		break;
+	}
+	master->bus_num = client->adapter->nr;
+	master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST;
+	master->setup = sc18is602_setup;
+	master->transfer_one_message = sc18is602_transfer_one;
+	master->dev.of_node = np;
+
+	error = spi_register_master(master);
+	if (error)
+		goto error_reg;
+
+	return 0;
+
+error_reg:
+	spi_master_put(master);
+	return error;
+}
+
+static int sc18is602_remove(struct i2c_client *client)
+{
+	struct sc18is602 *hw = i2c_get_clientdata(client);
+	struct spi_master *master = hw->master;
+
+	spi_unregister_master(master);
+
+	return 0;
+}
+
+static const struct i2c_device_id sc18is602_id[] = {
+	{ "sc18is602", sc18is602 },
+	{ "sc18is602b", sc18is602b },
+	{ "sc18is603", sc18is603 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sc18is602_id);
+
+static struct i2c_driver sc18is602_driver = {
+	.driver = {
+		.name = "sc18is602",
+	},
+	.probe = sc18is602_probe,
+	.remove = sc18is602_remove,
+	.id_table = sc18is602_id,
+};
+
+module_i2c_driver(sc18is602_driver);
+
+MODULE_DESCRIPTION("SC18IC602/603 SPI Master Driver");
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c
index 934138c7b3d3..796c077ef439 100644
--- a/drivers/spi/spi-sh-hspi.c
+++ b/drivers/spi/spi-sh-hspi.c
@@ -283,7 +283,7 @@ static int __devinit hspi_probe(struct platform_device *pdev)
 	ret = spi_register_master(master);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "spi_register_master error.\n");
-		goto error2;
+		goto error1;
 	}
 
 	pm_runtime_enable(&pdev->dev);
@@ -292,8 +292,6 @@ static int __devinit hspi_probe(struct platform_device *pdev)
 
 	return 0;
 
- error2:
-	devm_iounmap(hspi->dev, hspi->addr);
  error1:
 	clk_put(clk);
  error0:
@@ -310,7 +308,6 @@ static int __devexit hspi_remove(struct platform_device *pdev)
 
 	clk_put(hspi->clk);
 	spi_unregister_master(hspi->master);
-	devm_iounmap(hspi->dev, hspi->addr);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-stmp.c b/drivers/spi/spi-stmp.c
index 58e385285323..911e904b3c84 100644
--- a/drivers/spi/spi-stmp.c
+++ b/drivers/spi/spi-stmp.c
@@ -594,9 +594,7 @@ static int __devexit stmp_spi_remove(struct platform_device *dev)
 	struct stmp_spi *ss;
 	struct spi_master *master;
 
-	master = platform_get_drvdata(dev);
-	if (master == NULL)
-		goto out0;
+	master = spi_master_get(platform_get_drvdata(dev));
 	ss = spi_master_get_devdata(master);
 
 	spi_unregister_master(master);
@@ -609,8 +607,6 @@ static int __devexit stmp_spi_remove(struct platform_device *dev)
 	destroy_workqueue(ss->workqueue);
 	iounmap(ss->regs);
 	spi_master_put(master);
-	platform_set_drvdata(dev, NULL);
-out0:
 	return 0;
 }
 
diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c
deleted file mode 100644
index 488d9b6e9cbe..000000000000
--- a/drivers/spi/spi-tegra.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/*
- * Driver for Nvidia TEGRA spi controller.
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *     Erik Gilling <konkers@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <linux/spi/spi.h>
-#include <linux/dmaengine.h>
-
-#include <mach/dma.h>
-
-#define SLINK_COMMAND		0x000
-#define   SLINK_BIT_LENGTH(x)		(((x) & 0x1f) << 0)
-#define   SLINK_WORD_SIZE(x)		(((x) & 0x1f) << 5)
-#define   SLINK_BOTH_EN			(1 << 10)
-#define   SLINK_CS_SW			(1 << 11)
-#define   SLINK_CS_VALUE		(1 << 12)
-#define   SLINK_CS_POLARITY		(1 << 13)
-#define   SLINK_IDLE_SDA_DRIVE_LOW	(0 << 16)
-#define   SLINK_IDLE_SDA_DRIVE_HIGH	(1 << 16)
-#define   SLINK_IDLE_SDA_PULL_LOW	(2 << 16)
-#define   SLINK_IDLE_SDA_PULL_HIGH	(3 << 16)
-#define   SLINK_IDLE_SDA_MASK		(3 << 16)
-#define   SLINK_CS_POLARITY1		(1 << 20)
-#define   SLINK_CK_SDA			(1 << 21)
-#define   SLINK_CS_POLARITY2		(1 << 22)
-#define   SLINK_CS_POLARITY3		(1 << 23)
-#define   SLINK_IDLE_SCLK_DRIVE_LOW	(0 << 24)
-#define   SLINK_IDLE_SCLK_DRIVE_HIGH	(1 << 24)
-#define   SLINK_IDLE_SCLK_PULL_LOW	(2 << 24)
-#define   SLINK_IDLE_SCLK_PULL_HIGH	(3 << 24)
-#define   SLINK_IDLE_SCLK_MASK		(3 << 24)
-#define   SLINK_M_S			(1 << 28)
-#define   SLINK_WAIT			(1 << 29)
-#define   SLINK_GO			(1 << 30)
-#define   SLINK_ENB			(1 << 31)
-
-#define SLINK_COMMAND2		0x004
-#define   SLINK_LSBFE			(1 << 0)
-#define   SLINK_SSOE			(1 << 1)
-#define   SLINK_SPIE			(1 << 4)
-#define   SLINK_BIDIROE			(1 << 6)
-#define   SLINK_MODFEN			(1 << 7)
-#define   SLINK_INT_SIZE(x)		(((x) & 0x1f) << 8)
-#define   SLINK_CS_ACTIVE_BETWEEN	(1 << 17)
-#define   SLINK_SS_EN_CS(x)		(((x) & 0x3) << 18)
-#define   SLINK_SS_SETUP(x)		(((x) & 0x3) << 20)
-#define   SLINK_FIFO_REFILLS_0		(0 << 22)
-#define   SLINK_FIFO_REFILLS_1		(1 << 22)
-#define   SLINK_FIFO_REFILLS_2		(2 << 22)
-#define   SLINK_FIFO_REFILLS_3		(3 << 22)
-#define   SLINK_FIFO_REFILLS_MASK	(3 << 22)
-#define   SLINK_WAIT_PACK_INT(x)	(((x) & 0x7) << 26)
-#define   SLINK_SPC0			(1 << 29)
-#define   SLINK_TXEN			(1 << 30)
-#define   SLINK_RXEN			(1 << 31)
-
-#define SLINK_STATUS		0x008
-#define   SLINK_COUNT(val)		(((val) >> 0) & 0x1f)
-#define   SLINK_WORD(val)		(((val) >> 5) & 0x1f)
-#define   SLINK_BLK_CNT(val)		(((val) >> 0) & 0xffff)
-#define   SLINK_MODF			(1 << 16)
-#define   SLINK_RX_UNF			(1 << 18)
-#define   SLINK_TX_OVF			(1 << 19)
-#define   SLINK_TX_FULL			(1 << 20)
-#define   SLINK_TX_EMPTY		(1 << 21)
-#define   SLINK_RX_FULL			(1 << 22)
-#define   SLINK_RX_EMPTY		(1 << 23)
-#define   SLINK_TX_UNF			(1 << 24)
-#define   SLINK_RX_OVF			(1 << 25)
-#define   SLINK_TX_FLUSH		(1 << 26)
-#define   SLINK_RX_FLUSH		(1 << 27)
-#define   SLINK_SCLK			(1 << 28)
-#define   SLINK_ERR			(1 << 29)
-#define   SLINK_RDY			(1 << 30)
-#define   SLINK_BSY			(1 << 31)
-
-#define SLINK_MAS_DATA		0x010
-#define SLINK_SLAVE_DATA	0x014
-
-#define SLINK_DMA_CTL		0x018
-#define   SLINK_DMA_BLOCK_SIZE(x)	(((x) & 0xffff) << 0)
-#define   SLINK_TX_TRIG_1		(0 << 16)
-#define   SLINK_TX_TRIG_4		(1 << 16)
-#define   SLINK_TX_TRIG_8		(2 << 16)
-#define   SLINK_TX_TRIG_16		(3 << 16)
-#define   SLINK_TX_TRIG_MASK		(3 << 16)
-#define   SLINK_RX_TRIG_1		(0 << 18)
-#define   SLINK_RX_TRIG_4		(1 << 18)
-#define   SLINK_RX_TRIG_8		(2 << 18)
-#define   SLINK_RX_TRIG_16		(3 << 18)
-#define   SLINK_RX_TRIG_MASK		(3 << 18)
-#define   SLINK_PACKED			(1 << 20)
-#define   SLINK_PACK_SIZE_4		(0 << 21)
-#define   SLINK_PACK_SIZE_8		(1 << 21)
-#define   SLINK_PACK_SIZE_16		(2 << 21)
-#define   SLINK_PACK_SIZE_32		(3 << 21)
-#define   SLINK_PACK_SIZE_MASK		(3 << 21)
-#define   SLINK_IE_TXC			(1 << 26)
-#define   SLINK_IE_RXC			(1 << 27)
-#define   SLINK_DMA_EN			(1 << 31)
-
-#define SLINK_STATUS2		0x01c
-#define   SLINK_TX_FIFO_EMPTY_COUNT(val)	(((val) & 0x3f) >> 0)
-#define   SLINK_RX_FIFO_FULL_COUNT(val)		(((val) & 0x3f) >> 16)
-
-#define SLINK_TX_FIFO		0x100
-#define SLINK_RX_FIFO		0x180
-
-static const unsigned long spi_tegra_req_sels[] = {
-	TEGRA_DMA_REQ_SEL_SL2B1,
-	TEGRA_DMA_REQ_SEL_SL2B2,
-	TEGRA_DMA_REQ_SEL_SL2B3,
-	TEGRA_DMA_REQ_SEL_SL2B4,
-};
-
-#define BB_LEN			32
-
-struct spi_tegra_data {
-	struct spi_master	*master;
-	struct platform_device	*pdev;
-	spinlock_t		lock;
-
-	struct clk		*clk;
-	void __iomem		*base;
-	unsigned long		phys;
-
-	u32			cur_speed;
-
-	struct list_head	queue;
-	struct spi_transfer	*cur;
-	unsigned		cur_pos;
-	unsigned		cur_len;
-	unsigned		cur_bytes_per_word;
-
-	/* The tegra spi controller has a bug which causes the first word
-	 * in PIO transactions to be garbage.  Since packed DMA transactions
-	 * require transfers to be 4 byte aligned we need a bounce buffer
-	 * for the generic case.
-	 */
-	int			dma_req_len;
-	struct dma_chan		*rx_dma;
-	struct dma_slave_config	sconfig;
-	struct dma_async_tx_descriptor	*rx_dma_desc;
-	dma_cookie_t		rx_cookie;
-	u32			*rx_bb;
-	dma_addr_t		rx_bb_phys;
-};
-
-static void tegra_spi_rx_dma_complete(void *args);
-static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
-					    unsigned long reg)
-{
-	return readl(tspi->base + reg);
-}
-
-static inline void spi_tegra_writel(struct spi_tegra_data *tspi,
-				    unsigned long val,
-				    unsigned long reg)
-{
-	writel(val, tspi->base + reg);
-}
-
-static void spi_tegra_go(struct spi_tegra_data *tspi)
-{
-	unsigned long val;
-
-	wmb();
-
-	val = spi_tegra_readl(tspi, SLINK_DMA_CTL);
-	val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN;
-	val |= SLINK_DMA_BLOCK_SIZE(tspi->dma_req_len / 4 - 1);
-	spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
-	tspi->rx_dma_desc = dmaengine_prep_slave_single(tspi->rx_dma,
-				tspi->rx_bb_phys, tspi->dma_req_len,
-				DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
-	if (!tspi->rx_dma_desc) {
-		dev_err(&tspi->pdev->dev, "dmaengine slave prep failed\n");
-		return;
-	}
-	tspi->rx_dma_desc->callback = tegra_spi_rx_dma_complete;
-	tspi->rx_dma_desc->callback_param = tspi;
-	tspi->rx_cookie = dmaengine_submit(tspi->rx_dma_desc);
-	dma_async_issue_pending(tspi->rx_dma);
-
-	val |= SLINK_DMA_EN;
-	spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
-}
-
-static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi,
-				  struct spi_transfer *t)
-{
-	unsigned len = min(t->len - tspi->cur_pos, BB_LEN *
-			   tspi->cur_bytes_per_word);
-	u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_pos;
-	int i, j;
-	unsigned long val;
-
-	val = spi_tegra_readl(tspi, SLINK_COMMAND);
-	val &= ~SLINK_WORD_SIZE(~0);
-	val |= SLINK_WORD_SIZE(len / tspi->cur_bytes_per_word - 1);
-	spi_tegra_writel(tspi, val, SLINK_COMMAND);
-
-	for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
-		val = 0;
-		for (j = 0; j < tspi->cur_bytes_per_word; j++)
-			val |= tx_buf[i + j] << j * 8;
-
-		spi_tegra_writel(tspi, val, SLINK_TX_FIFO);
-	}
-
-	tspi->dma_req_len = len / tspi->cur_bytes_per_word * 4;
-
-	return len;
-}
-
-static unsigned spi_tegra_drain_rx_fifo(struct spi_tegra_data *tspi,
-				  struct spi_transfer *t)
-{
-	unsigned len = tspi->cur_len;
-	u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_pos;
-	int i, j;
-	unsigned long val;
-
-	for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
-		val = tspi->rx_bb[i / tspi->cur_bytes_per_word];
-		for (j = 0; j < tspi->cur_bytes_per_word; j++)
-			rx_buf[i + j] = (val >> (j * 8)) & 0xff;
-	}
-
-	return len;
-}
-
-static void spi_tegra_start_transfer(struct spi_device *spi,
-				    struct spi_transfer *t)
-{
-	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
-	u32 speed;
-	u8 bits_per_word;
-	unsigned long val;
-
-	speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
-	bits_per_word = t->bits_per_word ? t->bits_per_word  :
-		spi->bits_per_word;
-
-	tspi->cur_bytes_per_word = (bits_per_word - 1) / 8 + 1;
-
-	if (speed != tspi->cur_speed)
-		clk_set_rate(tspi->clk, speed);
-
-	if (tspi->cur_speed == 0)
-		clk_prepare_enable(tspi->clk);
-
-	tspi->cur_speed = speed;
-
-	val = spi_tegra_readl(tspi, SLINK_COMMAND2);
-	val &= ~SLINK_SS_EN_CS(~0) | SLINK_RXEN | SLINK_TXEN;
-	if (t->rx_buf)
-		val |= SLINK_RXEN;
-	if (t->tx_buf)
-		val |= SLINK_TXEN;
-	val |= SLINK_SS_EN_CS(spi->chip_select);
-	val |= SLINK_SPIE;
-	spi_tegra_writel(tspi, val, SLINK_COMMAND2);
-
-	val = spi_tegra_readl(tspi, SLINK_COMMAND);
-	val &= ~SLINK_BIT_LENGTH(~0);
-	val |= SLINK_BIT_LENGTH(bits_per_word - 1);
-
-	/* FIXME: should probably control CS manually so that we can be sure
-	 * it does not go low between transfer and to support delay_usecs
-	 * correctly.
-	 */
-	val &= ~SLINK_IDLE_SCLK_MASK & ~SLINK_CK_SDA & ~SLINK_CS_SW;
-
-	if (spi->mode & SPI_CPHA)
-		val |= SLINK_CK_SDA;
-
-	if (spi->mode & SPI_CPOL)
-		val |= SLINK_IDLE_SCLK_DRIVE_HIGH;
-	else
-		val |= SLINK_IDLE_SCLK_DRIVE_LOW;
-
-	val |= SLINK_M_S;
-
-	spi_tegra_writel(tspi, val, SLINK_COMMAND);
-
-	spi_tegra_writel(tspi, SLINK_RX_FLUSH | SLINK_TX_FLUSH, SLINK_STATUS);
-
-	tspi->cur = t;
-	tspi->cur_pos = 0;
-	tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, t);
-
-	spi_tegra_go(tspi);
-}
-
-static void spi_tegra_start_message(struct spi_device *spi,
-				    struct spi_message *m)
-{
-	struct spi_transfer *t;
-
-	m->actual_length = 0;
-	m->status = 0;
-
-	t = list_first_entry(&m->transfers, struct spi_transfer, transfer_list);
-	spi_tegra_start_transfer(spi, t);
-}
-
-static void handle_spi_rx_dma_complete(struct spi_tegra_data *tspi)
-{
-	unsigned long flags;
-	struct spi_message *m;
-	struct spi_device *spi;
-	int timeout = 0;
-	unsigned long val;
-
-	/* the SPI controller may come back with both the BSY and RDY bits
-	 * set.  In this case we need to wait for the BSY bit to clear so
-	 * that we are sure the DMA is finished.  1000 reads was empirically
-	 * determined to be long enough.
-	 */
-	while (timeout++ < 1000) {
-		if (!(spi_tegra_readl(tspi, SLINK_STATUS) & SLINK_BSY))
-			break;
-	}
-
-	spin_lock_irqsave(&tspi->lock, flags);
-
-	val = spi_tegra_readl(tspi, SLINK_STATUS);
-	val |= SLINK_RDY;
-	spi_tegra_writel(tspi, val, SLINK_STATUS);
-
-	m = list_first_entry(&tspi->queue, struct spi_message, queue);
-
-	if (timeout >= 1000)
-		m->status = -EIO;
-
-	spi = m->state;
-
-	tspi->cur_pos += spi_tegra_drain_rx_fifo(tspi, tspi->cur);
-	m->actual_length += tspi->cur_pos;
-
-	if (tspi->cur_pos < tspi->cur->len) {
-		tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, tspi->cur);
-		spi_tegra_go(tspi);
-	} else if (!list_is_last(&tspi->cur->transfer_list,
-				 &m->transfers)) {
-		tspi->cur =  list_first_entry(&tspi->cur->transfer_list,
-					      struct spi_transfer,
-					      transfer_list);
-		spi_tegra_start_transfer(spi, tspi->cur);
-	} else {
-		list_del(&m->queue);
-
-		m->complete(m->context);
-
-		if (!list_empty(&tspi->queue)) {
-			m = list_first_entry(&tspi->queue, struct spi_message,
-					     queue);
-			spi = m->state;
-			spi_tegra_start_message(spi, m);
-		} else {
-			clk_disable_unprepare(tspi->clk);
-			tspi->cur_speed = 0;
-		}
-	}
-
-	spin_unlock_irqrestore(&tspi->lock, flags);
-}
-
-static void tegra_spi_rx_dma_complete(void *args)
-{
-	struct spi_tegra_data *tspi = args;
-	handle_spi_rx_dma_complete(tspi);
-}
-
-static int spi_tegra_setup(struct spi_device *spi)
-{
-	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
-	unsigned long cs_bit;
-	unsigned long val;
-	unsigned long flags;
-
-	dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
-		spi->bits_per_word,
-		spi->mode & SPI_CPOL ? "" : "~",
-		spi->mode & SPI_CPHA ? "" : "~",
-		spi->max_speed_hz);
-
-
-	switch (spi->chip_select) {
-	case 0:
-		cs_bit = SLINK_CS_POLARITY;
-		break;
-
-	case 1:
-		cs_bit = SLINK_CS_POLARITY1;
-		break;
-
-	case 2:
-		cs_bit = SLINK_CS_POLARITY2;
-		break;
-
-	case 4:
-		cs_bit = SLINK_CS_POLARITY3;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&tspi->lock, flags);
-
-	val = spi_tegra_readl(tspi, SLINK_COMMAND);
-	if (spi->mode & SPI_CS_HIGH)
-		val |= cs_bit;
-	else
-		val &= ~cs_bit;
-	spi_tegra_writel(tspi, val, SLINK_COMMAND);
-
-	spin_unlock_irqrestore(&tspi->lock, flags);
-
-	return 0;
-}
-
-static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
-	struct spi_transfer *t;
-	unsigned long flags;
-	int was_empty;
-
-	if (list_empty(&m->transfers) || !m->complete)
-		return -EINVAL;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->bits_per_word < 0 || t->bits_per_word > 32)
-			return -EINVAL;
-
-		if (t->len == 0)
-			return -EINVAL;
-
-		if (!t->rx_buf && !t->tx_buf)
-			return -EINVAL;
-	}
-
-	m->state = spi;
-
-	spin_lock_irqsave(&tspi->lock, flags);
-	was_empty = list_empty(&tspi->queue);
-	list_add_tail(&m->queue, &tspi->queue);
-
-	if (was_empty)
-		spi_tegra_start_message(spi, m);
-
-	spin_unlock_irqrestore(&tspi->lock, flags);
-
-	return 0;
-}
-
-static int __devinit spi_tegra_probe(struct platform_device *pdev)
-{
-	struct spi_master	*master;
-	struct spi_tegra_data	*tspi;
-	struct resource		*r;
-	int ret;
-	dma_cap_mask_t mask;
-
-	master = spi_alloc_master(&pdev->dev, sizeof *tspi);
-	if (master == NULL) {
-		dev_err(&pdev->dev, "master allocation failed\n");
-		return -ENOMEM;
-	}
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	master->bus_num = pdev->id;
-
-	master->setup = spi_tegra_setup;
-	master->transfer = spi_tegra_transfer;
-	master->num_chipselect = 4;
-
-	dev_set_drvdata(&pdev->dev, master);
-	tspi = spi_master_get_devdata(master);
-	tspi->master = master;
-	tspi->pdev = pdev;
-	spin_lock_init(&tspi->lock);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		ret = -ENODEV;
-		goto err0;
-	}
-
-	if (!request_mem_region(r->start, resource_size(r),
-				dev_name(&pdev->dev))) {
-		ret = -EBUSY;
-		goto err0;
-	}
-
-	tspi->phys = r->start;
-	tspi->base = ioremap(r->start, resource_size(r));
-	if (!tspi->base) {
-		dev_err(&pdev->dev, "can't ioremap iomem\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	tspi->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(tspi->clk)) {
-		dev_err(&pdev->dev, "can not get clock\n");
-		ret = PTR_ERR(tspi->clk);
-		goto err2;
-	}
-
-	INIT_LIST_HEAD(&tspi->queue);
-
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	tspi->rx_dma = dma_request_channel(mask, NULL, NULL);
-	if (!tspi->rx_dma) {
-		dev_err(&pdev->dev, "can not allocate rx dma channel\n");
-		ret = -ENODEV;
-		goto err3;
-	}
-
-	tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
-					 &tspi->rx_bb_phys, GFP_KERNEL);
-	if (!tspi->rx_bb) {
-		dev_err(&pdev->dev, "can not allocate rx bounce buffer\n");
-		ret = -ENOMEM;
-		goto err4;
-	}
-
-	/* Dmaengine Dma slave config */
-	tspi->sconfig.src_addr = tspi->phys + SLINK_RX_FIFO;
-	tspi->sconfig.dst_addr = tspi->phys + SLINK_RX_FIFO;
-	tspi->sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	tspi->sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	tspi->sconfig.slave_id = spi_tegra_req_sels[pdev->id];
-	tspi->sconfig.src_maxburst = 1;
-	tspi->sconfig.dst_maxburst = 1;
-	ret = dmaengine_device_control(tspi->rx_dma,
-			DMA_SLAVE_CONFIG, (unsigned long) &tspi->sconfig);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "can not do slave configure for dma %d\n",
-			ret);
-		goto err4;
-	}
-
-	master->dev.of_node = pdev->dev.of_node;
-	ret = spi_register_master(master);
-
-	if (ret < 0)
-		goto err5;
-
-	return ret;
-
-err5:
-	dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
-			  tspi->rx_bb, tspi->rx_bb_phys);
-err4:
-	dma_release_channel(tspi->rx_dma);
-err3:
-	clk_put(tspi->clk);
-err2:
-	iounmap(tspi->base);
-err1:
-	release_mem_region(r->start, resource_size(r));
-err0:
-	spi_master_put(master);
-	return ret;
-}
-
-static int __devexit spi_tegra_remove(struct platform_device *pdev)
-{
-	struct spi_master	*master;
-	struct spi_tegra_data	*tspi;
-	struct resource		*r;
-
-	master = dev_get_drvdata(&pdev->dev);
-	tspi = spi_master_get_devdata(master);
-
-	spi_unregister_master(master);
-	dma_release_channel(tspi->rx_dma);
-	dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
-			  tspi->rx_bb, tspi->rx_bb_phys);
-
-	clk_put(tspi->clk);
-	iounmap(tspi->base);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, resource_size(r));
-
-	return 0;
-}
-
-MODULE_ALIAS("platform:spi_tegra");
-
-#ifdef CONFIG_OF
-static struct of_device_id spi_tegra_of_match_table[] __devinitdata = {
-	{ .compatible = "nvidia,tegra20-spi", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, spi_tegra_of_match_table);
-#else /* CONFIG_OF */
-#define spi_tegra_of_match_table NULL
-#endif /* CONFIG_OF */
-
-static struct platform_driver spi_tegra_driver = {
-	.driver = {
-		.name =		"spi_tegra",
-		.owner =	THIS_MODULE,
-		.of_match_table = spi_tegra_of_match_table,
-	},
-	.probe =	spi_tegra_probe,
-	.remove =	__devexit_p(spi_tegra_remove),
-};
-module_platform_driver(spi_tegra_driver);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-tle62x0.c b/drivers/spi/spi-tle62x0.c
index 0ce5c12aab55..24421024deaf 100644
--- a/drivers/spi/spi-tle62x0.c
+++ b/drivers/spi/spi-tle62x0.c
@@ -316,18 +316,7 @@ static struct spi_driver tle62x0_driver = {
 	.remove		= __devexit_p(tle62x0_remove),
 };
 
-static __init int tle62x0_init(void)
-{
-	return spi_register_driver(&tle62x0_driver);
-}
-
-static __exit void tle62x0_exit(void)
-{
-	spi_unregister_driver(&tle62x0_driver);
-}
-
-module_init(tle62x0_init);
-module_exit(tle62x0_exit);
+module_spi_driver(tle62x0_driver);
 
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("TLE62x0 SPI driver");
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index 1284c9b74653..135f7406f4bf 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -1536,8 +1536,6 @@ static int __devexit pch_spi_pd_remove(struct platform_device *plat_dev)
 
 	pci_iounmap(board_dat->pdev, data->io_remap_addr);
 	spi_unregister_master(data->master);
-	spi_master_put(data->master);
-	platform_set_drvdata(plat_dev, NULL);
 
 	return 0;
 }
diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h
index fe1d7b283cb6..854b7294f6c6 100644
--- a/include/linux/amba/pl022.h
+++ b/include/linux/amba/pl022.h
@@ -244,6 +244,7 @@ struct dma_chan;
  *     indicates no delay and the device will be suspended immediately.
  * @rt: indicates the controller should run the message pump with realtime
  *     priority to minimise the transfer latency on the bus.
+ * @chipselects: list of <num_chipselects> chip select gpios
  */
 struct pl022_ssp_controller {
 	u16 bus_id;
@@ -254,6 +255,7 @@ struct pl022_ssp_controller {
 	void *dma_tx_param;
 	int autosuspend_delay;
 	bool rt;
+	int *chipselects;
 };
 
 /**
diff --git a/include/linux/platform_data/sc18is602.h b/include/linux/platform_data/sc18is602.h
new file mode 100644
index 000000000000..997b06634152
--- /dev/null
+++ b/include/linux/platform_data/sc18is602.h
@@ -0,0 +1,19 @@
+/*
+ * Platform data for NXP SC18IS602/603
+ *
+ * Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
+ *
+ * This program 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.
+ *
+ * For further information, see the Documentation/spi/sc18is602 file.
+ */
+
+/**
+ * struct sc18is602_platform_data - sc18is602 info
+ * @clock_frequency		SC18IS603 oscillator frequency
+ */
+struct sc18is602_platform_data {
+	u32 clock_frequency;
+};
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
new file mode 100644
index 000000000000..61ae1306db23
--- /dev/null
+++ b/include/linux/spi/mxs-spi.h
@@ -0,0 +1,150 @@
+/*
+ * include/linux/spi/mxs-spi.h
+ *
+ * Freescale i.MX233/i.MX28 SPI controller register definition
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __LINUX_SPI_MXS_SPI_H__
+#define __LINUX_SPI_MXS_SPI_H__
+
+#include <linux/fsl/mxs-dma.h>
+
+#define ssp_is_old(host)	((host)->devid == IMX23_SSP)
+
+/* SSP registers */
+#define HW_SSP_CTRL0				0x000
+#define  BM_SSP_CTRL0_RUN			(1 << 29)
+#define  BM_SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define  BM_SSP_CTRL0_LOCK_CS			(1 << 27)
+#define  BM_SSP_CTRL0_IGNORE_CRC		(1 << 26)
+#define  BM_SSP_CTRL0_READ			(1 << 25)
+#define  BM_SSP_CTRL0_DATA_XFER			(1 << 24)
+#define  BP_SSP_CTRL0_BUS_WIDTH			22
+#define  BM_SSP_CTRL0_BUS_WIDTH			(0x3 << 22)
+#define  BM_SSP_CTRL0_WAIT_FOR_IRQ		(1 << 21)
+#define  BM_SSP_CTRL0_WAIT_FOR_CMD		(1 << 20)
+#define  BM_SSP_CTRL0_LONG_RESP			(1 << 19)
+#define  BM_SSP_CTRL0_GET_RESP			(1 << 17)
+#define  BM_SSP_CTRL0_ENABLE			(1 << 16)
+#define  BP_SSP_CTRL0_XFER_COUNT		0
+#define  BM_SSP_CTRL0_XFER_COUNT		0xffff
+#define HW_SSP_CMD0				0x010
+#define  BM_SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define  BM_SSP_CMD0_SLOW_CLKING_EN		(1 << 22)
+#define  BM_SSP_CMD0_CONT_CLKING_EN		(1 << 21)
+#define  BM_SSP_CMD0_APPEND_8CYC		(1 << 20)
+#define  BP_SSP_CMD0_BLOCK_SIZE			16
+#define  BM_SSP_CMD0_BLOCK_SIZE			(0xf << 16)
+#define  BP_SSP_CMD0_BLOCK_COUNT		8
+#define  BM_SSP_CMD0_BLOCK_COUNT		(0xff << 8)
+#define  BP_SSP_CMD0_CMD			0
+#define  BM_SSP_CMD0_CMD			0xff
+#define HW_SSP_CMD1				0x020
+#define HW_SSP_XFER_SIZE			0x030
+#define HW_SSP_BLOCK_SIZE			0x040
+#define  BP_SSP_BLOCK_SIZE_BLOCK_COUNT		4
+#define  BM_SSP_BLOCK_SIZE_BLOCK_COUNT		(0xffffff << 4)
+#define  BP_SSP_BLOCK_SIZE_BLOCK_SIZE		0
+#define  BM_SSP_BLOCK_SIZE_BLOCK_SIZE		0xf
+#define HW_SSP_TIMING(h)			(ssp_is_old(h) ? 0x050 : 0x070)
+#define  BP_SSP_TIMING_TIMEOUT			16
+#define  BM_SSP_TIMING_TIMEOUT			(0xffff << 16)
+#define  BP_SSP_TIMING_CLOCK_DIVIDE		8
+#define  BM_SSP_TIMING_CLOCK_DIVIDE		(0xff << 8)
+#define  BF_SSP_TIMING_CLOCK_DIVIDE(v)		\
+			(((v) << 8) & BM_SSP_TIMING_CLOCK_DIVIDE)
+#define  BP_SSP_TIMING_CLOCK_RATE		0
+#define  BM_SSP_TIMING_CLOCK_RATE		0xff
+#define BF_SSP_TIMING_CLOCK_RATE(v)		\
+			(((v) << 0) & BM_SSP_TIMING_CLOCK_RATE)
+#define HW_SSP_CTRL1(h)				(ssp_is_old(h) ? 0x060 : 0x080)
+#define  BM_SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define  BM_SSP_CTRL1_SDIO_IRQ_EN		(1 << 30)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ		(1 << 29)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN	(1 << 26)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN	(1 << 24)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ		(1 << 23)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN	(1 << 20)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN	(1 << 16)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN	(1 << 14)
+#define  BM_SSP_CTRL1_DMA_ENABLE		(1 << 13)
+#define  BM_SSP_CTRL1_PHASE			(1 << 10)
+#define  BM_SSP_CTRL1_POLARITY			(1 << 9)
+#define  BP_SSP_CTRL1_WORD_LENGTH		4
+#define  BM_SSP_CTRL1_WORD_LENGTH		(0xf << 4)
+#define  BF_SSP_CTRL1_WORD_LENGTH(v)		\
+			(((v) << 4) & BM_SSP_CTRL1_WORD_LENGTH)
+#define  BV_SSP_CTRL1_WORD_LENGTH__FOUR_BITS	0x3
+#define  BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS	0x7
+#define  BV_SSP_CTRL1_WORD_LENGTH__SIXTEEN_BITS	0xF
+#define  BP_SSP_CTRL1_SSP_MODE			0
+#define  BM_SSP_CTRL1_SSP_MODE			0xf
+#define  BF_SSP_CTRL1_SSP_MODE(v)		\
+			(((v) << 0) & BM_SSP_CTRL1_SSP_MODE)
+#define  BV_SSP_CTRL1_SSP_MODE__SPI		0x0
+#define  BV_SSP_CTRL1_SSP_MODE__SSI		0x1
+#define  BV_SSP_CTRL1_SSP_MODE__SD_MMC		0x3
+#define  BV_SSP_CTRL1_SSP_MODE__MS		0x4
+
+#define HW_SSP_DATA(h)				(ssp_is_old(h) ? 0x070 : 0x090)
+
+#define HW_SSP_SDRESP0(h)			(ssp_is_old(h) ? 0x080 : 0x0a0)
+#define HW_SSP_SDRESP1(h)			(ssp_is_old(h) ? 0x090 : 0x0b0)
+#define HW_SSP_SDRESP2(h)			(ssp_is_old(h) ? 0x0a0 : 0x0c0)
+#define HW_SSP_SDRESP3(h)			(ssp_is_old(h) ? 0x0b0 : 0x0d0)
+#define HW_SSP_STATUS(h)			(ssp_is_old(h) ? 0x0c0 : 0x100)
+#define  BM_SSP_STATUS_CARD_DETECT		(1 << 28)
+#define  BM_SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define  BM_SSP_STATUS_FIFO_EMPTY		(1 << 5)
+
+#define BF_SSP(value, field)	(((value) << BP_SSP_##field) & BM_SSP_##field)
+
+#define SSP_PIO_NUM	3
+
+enum mxs_ssp_id {
+	IMX23_SSP,
+	IMX28_SSP,
+};
+
+struct mxs_ssp {
+	struct device			*dev;
+	void __iomem			*base;
+	struct clk			*clk;
+	unsigned int			clk_rate;
+	enum mxs_ssp_id			devid;
+
+	int				dma_channel;
+	struct dma_chan			*dmach;
+	struct mxs_dma_data		dma_data;
+	unsigned int			dma_dir;
+	enum dma_transfer_direction	slave_dirn;
+	u32				ssp_pio_words[SSP_PIO_NUM];
+};
+
+void mxs_ssp_set_clk_rate(struct mxs_ssp *ssp, unsigned int rate);
+
+#endif	/* __LINUX_SPI_MXS_SPI_H__ */