summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/Kconfig7
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/ep93xx_dma.c1355
-rw-r--r--drivers/spi/Kconfig48
-rw-r--r--drivers/spi/Makefile111
-rw-r--r--drivers/spi/atmel_spi.h167
-rw-r--r--drivers/spi/spi-altera.c (renamed from drivers/spi/spi_altera.c)0
-rw-r--r--drivers/spi/spi-ath79.c (renamed from drivers/spi/ath79_spi.c)2
-rw-r--r--drivers/spi/spi-atmel.c (renamed from drivers/spi/atmel_spi.c)155
-rw-r--r--drivers/spi/spi-au1550.c (renamed from drivers/spi/au1550_spi.c)2
-rw-r--r--drivers/spi/spi-bfin-sport.c (renamed from drivers/spi/spi_bfin_sport.c)0
-rw-r--r--drivers/spi/spi-bfin5xx.c (renamed from drivers/spi/spi_bfin5xx.c)218
-rw-r--r--drivers/spi/spi-bitbang-txrx.h (renamed from drivers/spi/spi_bitbang_txrx.h)0
-rw-r--r--drivers/spi/spi-bitbang.c (renamed from drivers/spi/spi_bitbang.c)8
-rw-r--r--drivers/spi/spi-butterfly.c (renamed from drivers/spi/spi_butterfly.c)4
-rw-r--r--drivers/spi/spi-coldfire-qspi.c (renamed from drivers/spi/coldfire_qspi.c)0
-rw-r--r--drivers/spi/spi-davinci.c (renamed from drivers/spi/davinci_spi.c)0
-rw-r--r--drivers/spi/spi-dw-mid.c (renamed from drivers/spi/dw_spi_mid.c)4
-rw-r--r--drivers/spi/spi-dw-mmio.c (renamed from drivers/spi/dw_spi_mmio.c)4
-rw-r--r--drivers/spi/spi-dw-pci.c (renamed from drivers/spi/dw_spi_pci.c)4
-rw-r--r--drivers/spi/spi-dw.c (renamed from drivers/spi/dw_spi.c)8
-rw-r--r--drivers/spi/spi-dw.h (renamed from drivers/spi/dw_spi.h)1
-rw-r--r--drivers/spi/spi-ep93xx.c (renamed from drivers/spi/ep93xx_spi.c)303
-rw-r--r--drivers/spi/spi-fsl-espi.c (renamed from drivers/spi/spi_fsl_espi.c)2
-rw-r--r--drivers/spi/spi-fsl-lib.c (renamed from drivers/spi/spi_fsl_lib.c)2
-rw-r--r--drivers/spi/spi-fsl-lib.h (renamed from drivers/spi/spi_fsl_lib.h)0
-rw-r--r--drivers/spi/spi-fsl-spi.c (renamed from drivers/spi/spi_fsl_spi.c)30
-rw-r--r--drivers/spi/spi-gpio.c (renamed from drivers/spi/spi_gpio.c)6
-rw-r--r--drivers/spi/spi-imx.c (renamed from drivers/spi/spi_imx.c)466
-rw-r--r--drivers/spi/spi-lm70llp.c (renamed from drivers/spi/spi_lm70llp.c)4
-rw-r--r--drivers/spi/spi-mpc512x-psc.c (renamed from drivers/spi/mpc512x_psc_spi.c)0
-rw-r--r--drivers/spi/spi-mpc52xx-psc.c (renamed from drivers/spi/mpc52xx_psc_spi.c)0
-rw-r--r--drivers/spi/spi-mpc52xx.c (renamed from drivers/spi/mpc52xx_spi.c)0
-rw-r--r--drivers/spi/spi-nuc900.c (renamed from drivers/spi/spi_nuc900.c)5
-rw-r--r--drivers/spi/spi-oc-tiny.c (renamed from drivers/spi/spi_oc_tiny.c)0
-rw-r--r--drivers/spi/spi-omap-100k.c (renamed from drivers/spi/omap_spi_100k.c)0
-rw-r--r--drivers/spi/spi-omap-uwire.c (renamed from drivers/spi/omap_uwire.c)2
-rw-r--r--drivers/spi/spi-omap2-mcspi.c (renamed from drivers/spi/omap2_mcspi.c)10
-rw-r--r--drivers/spi/spi-orion.c (renamed from drivers/spi/orion_spi.c)8
-rw-r--r--drivers/spi/spi-pl022.c (renamed from drivers/spi/amba-pl022.c)111
-rw-r--r--drivers/spi/spi-ppc4xx.c (renamed from drivers/spi/spi_ppc4xx.c)2
-rw-r--r--drivers/spi/spi-pxa2xx-pci.c (renamed from drivers/spi/pxa2xx_spi_pci.c)0
-rw-r--r--drivers/spi/spi-pxa2xx.c (renamed from drivers/spi/pxa2xx_spi.c)0
-rw-r--r--drivers/spi/spi-s3c24xx-fiq.S (renamed from drivers/spi/spi_s3c24xx_fiq.S)2
-rw-r--r--drivers/spi/spi-s3c24xx-fiq.h (renamed from drivers/spi/spi_s3c24xx_fiq.h)0
-rw-r--r--drivers/spi/spi-s3c24xx.c (renamed from drivers/spi/spi_s3c24xx.c)5
-rw-r--r--drivers/spi/spi-s3c64xx.c (renamed from drivers/spi/spi_s3c64xx.c)3
-rw-r--r--drivers/spi/spi-sh-msiof.c (renamed from drivers/spi/spi_sh_msiof.c)0
-rw-r--r--drivers/spi/spi-sh-sci.c (renamed from drivers/spi/spi_sh_sci.c)2
-rw-r--r--drivers/spi/spi-sh.c (renamed from drivers/spi/spi_sh.c)0
-rw-r--r--drivers/spi/spi-stmp.c (renamed from drivers/spi/spi_stmp.c)0
-rw-r--r--drivers/spi/spi-tegra.c (renamed from drivers/spi/spi_tegra.c)20
-rw-r--r--drivers/spi/spi-ti-ssp.c (renamed from drivers/spi/ti-ssp-spi.c)0
-rw-r--r--drivers/spi/spi-tle62x0.c (renamed from drivers/spi/tle62x0.c)2
-rw-r--r--drivers/spi/spi-topcliff-pch.c (renamed from drivers/spi/spi_topcliff_pch.c)1158
-rw-r--r--drivers/spi/spi-txx9.c (renamed from drivers/spi/spi_txx9.c)2
-rw-r--r--drivers/spi/spi-xilinx.c (renamed from drivers/spi/xilinx_spi.c)0
-rw-r--r--drivers/spi/spi.c2
-rw-r--r--drivers/spi/spi_s3c24xx_gpio.c201
-rw-r--r--drivers/spi/spidev.c2
60 files changed, 3150 insertions, 1299 deletions
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 25cf327cd1cb..2e3b3d38c465 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -237,6 +237,13 @@ config MXS_DMA
 	  Support the MXS DMA engine. This engine including APBH-DMA
 	  and APBX-DMA is integrated into Freescale i.MX23/28 chips.
 
+config EP93XX_DMA
+	bool "Cirrus Logic EP93xx DMA support"
+	depends on ARCH_EP93XX
+	select DMA_ENGINE
+	help
+	  Enable support for the Cirrus Logic EP93xx M2P/M2M DMA controller.
+
 config DMA_ENGINE
 	bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 836095ab3c5c..30cf3b1f0c5c 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
 obj-$(CONFIG_PL330_DMA) += pl330.o
 obj-$(CONFIG_PCH_DMA) += pch_dma.o
 obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
+obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
new file mode 100644
index 000000000000..0766c1e53b1d
--- /dev/null
+++ b/drivers/dma/ep93xx_dma.c
@@ -0,0 +1,1355 @@
+/*
+ * Driver for the Cirrus Logic EP93xx DMA Controller
+ *
+ * Copyright (C) 2011 Mika Westerberg
+ *
+ * DMA M2P implementation is based on the original
+ * arch/arm/mach-ep93xx/dma-m2p.c which has following copyrights:
+ *
+ *   Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *   Copyright (C) 2006 Applied Data Systems
+ *   Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
+ *
+ * This driver is based on dw_dmac and amba-pl08x drivers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <mach/dma.h>
+
+/* M2P registers */
+#define M2P_CONTROL			0x0000
+#define M2P_CONTROL_STALLINT		BIT(0)
+#define M2P_CONTROL_NFBINT		BIT(1)
+#define M2P_CONTROL_CH_ERROR_INT	BIT(3)
+#define M2P_CONTROL_ENABLE		BIT(4)
+#define M2P_CONTROL_ICE			BIT(6)
+
+#define M2P_INTERRUPT			0x0004
+#define M2P_INTERRUPT_STALL		BIT(0)
+#define M2P_INTERRUPT_NFB		BIT(1)
+#define M2P_INTERRUPT_ERROR		BIT(3)
+
+#define M2P_PPALLOC			0x0008
+#define M2P_STATUS			0x000c
+
+#define M2P_MAXCNT0			0x0020
+#define M2P_BASE0			0x0024
+#define M2P_MAXCNT1			0x0030
+#define M2P_BASE1			0x0034
+
+#define M2P_STATE_IDLE			0
+#define M2P_STATE_STALL			1
+#define M2P_STATE_ON			2
+#define M2P_STATE_NEXT			3
+
+/* M2M registers */
+#define M2M_CONTROL			0x0000
+#define M2M_CONTROL_DONEINT		BIT(2)
+#define M2M_CONTROL_ENABLE		BIT(3)
+#define M2M_CONTROL_START		BIT(4)
+#define M2M_CONTROL_DAH			BIT(11)
+#define M2M_CONTROL_SAH			BIT(12)
+#define M2M_CONTROL_PW_SHIFT		9
+#define M2M_CONTROL_PW_8		(0 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_PW_16		(1 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_PW_32		(2 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_PW_MASK		(3 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_TM_SHIFT		13
+#define M2M_CONTROL_TM_TX		(1 << M2M_CONTROL_TM_SHIFT)
+#define M2M_CONTROL_TM_RX		(2 << M2M_CONTROL_TM_SHIFT)
+#define M2M_CONTROL_RSS_SHIFT		22
+#define M2M_CONTROL_RSS_SSPRX		(1 << M2M_CONTROL_RSS_SHIFT)
+#define M2M_CONTROL_RSS_SSPTX		(2 << M2M_CONTROL_RSS_SHIFT)
+#define M2M_CONTROL_RSS_IDE		(3 << M2M_CONTROL_RSS_SHIFT)
+#define M2M_CONTROL_NO_HDSK		BIT(24)
+#define M2M_CONTROL_PWSC_SHIFT		25
+
+#define M2M_INTERRUPT			0x0004
+#define M2M_INTERRUPT_DONEINT		BIT(1)
+
+#define M2M_BCR0			0x0010
+#define M2M_BCR1			0x0014
+#define M2M_SAR_BASE0			0x0018
+#define M2M_SAR_BASE1			0x001c
+#define M2M_DAR_BASE0			0x002c
+#define M2M_DAR_BASE1			0x0030
+
+#define DMA_MAX_CHAN_BYTES		0xffff
+#define DMA_MAX_CHAN_DESCRIPTORS	32
+
+struct ep93xx_dma_engine;
+
+/**
+ * struct ep93xx_dma_desc - EP93xx specific transaction descriptor
+ * @src_addr: source address of the transaction
+ * @dst_addr: destination address of the transaction
+ * @size: size of the transaction (in bytes)
+ * @complete: this descriptor is completed
+ * @txd: dmaengine API descriptor
+ * @tx_list: list of linked descriptors
+ * @node: link used for putting this into a channel queue
+ */
+struct ep93xx_dma_desc {
+	u32				src_addr;
+	u32				dst_addr;
+	size_t				size;
+	bool				complete;
+	struct dma_async_tx_descriptor	txd;
+	struct list_head		tx_list;
+	struct list_head		node;
+};
+
+/**
+ * struct ep93xx_dma_chan - an EP93xx DMA M2P/M2M channel
+ * @chan: dmaengine API channel
+ * @edma: pointer to to the engine device
+ * @regs: memory mapped registers
+ * @irq: interrupt number of the channel
+ * @clk: clock used by this channel
+ * @tasklet: channel specific tasklet used for callbacks
+ * @lock: lock protecting the fields following
+ * @flags: flags for the channel
+ * @buffer: which buffer to use next (0/1)
+ * @last_completed: last completed cookie value
+ * @active: flattened chain of descriptors currently being processed
+ * @queue: pending descriptors which are handled next
+ * @free_list: list of free descriptors which can be used
+ * @runtime_addr: physical address currently used as dest/src (M2M only). This
+ *                is set via %DMA_SLAVE_CONFIG before slave operation is
+ *                prepared
+ * @runtime_ctrl: M2M runtime values for the control register.
+ *
+ * As EP93xx DMA controller doesn't support real chained DMA descriptors we
+ * will have slightly different scheme here: @active points to a head of
+ * flattened DMA descriptor chain.
+ *
+ * @queue holds pending transactions. These are linked through the first
+ * descriptor in the chain. When a descriptor is moved to the @active queue,
+ * the first and chained descriptors are flattened into a single list.
+ *
+ * @chan.private holds pointer to &struct ep93xx_dma_data which contains
+ * necessary channel configuration information. For memcpy channels this must
+ * be %NULL.
+ */
+struct ep93xx_dma_chan {
+	struct dma_chan			chan;
+	const struct ep93xx_dma_engine	*edma;
+	void __iomem			*regs;
+	int				irq;
+	struct clk			*clk;
+	struct tasklet_struct		tasklet;
+	/* protects the fields following */
+	spinlock_t			lock;
+	unsigned long			flags;
+/* Channel is configured for cyclic transfers */
+#define EP93XX_DMA_IS_CYCLIC		0
+
+	int				buffer;
+	dma_cookie_t			last_completed;
+	struct list_head		active;
+	struct list_head		queue;
+	struct list_head		free_list;
+	u32				runtime_addr;
+	u32				runtime_ctrl;
+};
+
+/**
+ * struct ep93xx_dma_engine - the EP93xx DMA engine instance
+ * @dma_dev: holds the dmaengine device
+ * @m2m: is this an M2M or M2P device
+ * @hw_setup: method which sets the channel up for operation
+ * @hw_shutdown: shuts the channel down and flushes whatever is left
+ * @hw_submit: pushes active descriptor(s) to the hardware
+ * @hw_interrupt: handle the interrupt
+ * @num_channels: number of channels for this instance
+ * @channels: array of channels
+ *
+ * There is one instance of this struct for the M2P channels and one for the
+ * M2M channels. hw_xxx() methods are used to perform operations which are
+ * different on M2M and M2P channels. These methods are called with channel
+ * lock held and interrupts disabled so they cannot sleep.
+ */
+struct ep93xx_dma_engine {
+	struct dma_device	dma_dev;
+	bool			m2m;
+	int			(*hw_setup)(struct ep93xx_dma_chan *);
+	void			(*hw_shutdown)(struct ep93xx_dma_chan *);
+	void			(*hw_submit)(struct ep93xx_dma_chan *);
+	int			(*hw_interrupt)(struct ep93xx_dma_chan *);
+#define INTERRUPT_UNKNOWN	0
+#define INTERRUPT_DONE		1
+#define INTERRUPT_NEXT_BUFFER	2
+
+	size_t			num_channels;
+	struct ep93xx_dma_chan	channels[];
+};
+
+static inline struct device *chan2dev(struct ep93xx_dma_chan *edmac)
+{
+	return &edmac->chan.dev->device;
+}
+
+static struct ep93xx_dma_chan *to_ep93xx_dma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct ep93xx_dma_chan, chan);
+}
+
+/**
+ * ep93xx_dma_set_active - set new active descriptor chain
+ * @edmac: channel
+ * @desc: head of the new active descriptor chain
+ *
+ * Sets @desc to be the head of the new active descriptor chain. This is the
+ * chain which is processed next. The active list must be empty before calling
+ * this function.
+ *
+ * Called with @edmac->lock held and interrupts disabled.
+ */
+static void ep93xx_dma_set_active(struct ep93xx_dma_chan *edmac,
+				  struct ep93xx_dma_desc *desc)
+{
+	BUG_ON(!list_empty(&edmac->active));
+
+	list_add_tail(&desc->node, &edmac->active);
+
+	/* Flatten the @desc->tx_list chain into @edmac->active list */
+	while (!list_empty(&desc->tx_list)) {
+		struct ep93xx_dma_desc *d = list_first_entry(&desc->tx_list,
+			struct ep93xx_dma_desc, node);
+
+		/*
+		 * We copy the callback parameters from the first descriptor
+		 * to all the chained descriptors. This way we can call the
+		 * callback without having to find out the first descriptor in
+		 * the chain. Useful for cyclic transfers.
+		 */
+		d->txd.callback = desc->txd.callback;
+		d->txd.callback_param = desc->txd.callback_param;
+
+		list_move_tail(&d->node, &edmac->active);
+	}
+}
+
+/* Called with @edmac->lock held and interrupts disabled */
+static struct ep93xx_dma_desc *
+ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
+{
+	return list_first_entry(&edmac->active, struct ep93xx_dma_desc, node);
+}
+
+/**
+ * ep93xx_dma_advance_active - advances to the next active descriptor
+ * @edmac: channel
+ *
+ * Function advances active descriptor to the next in the @edmac->active and
+ * returns %true if we still have descriptors in the chain to process.
+ * Otherwise returns %false.
+ *
+ * When the channel is in cyclic mode always returns %true.
+ *
+ * Called with @edmac->lock held and interrupts disabled.
+ */
+static bool ep93xx_dma_advance_active(struct ep93xx_dma_chan *edmac)
+{
+	list_rotate_left(&edmac->active);
+
+	if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
+		return true;
+
+	/*
+	 * If txd.cookie is set it means that we are back in the first
+	 * descriptor in the chain and hence done with it.
+	 */
+	return !ep93xx_dma_get_active(edmac)->txd.cookie;
+}
+
+/*
+ * M2P DMA implementation
+ */
+
+static void m2p_set_control(struct ep93xx_dma_chan *edmac, u32 control)
+{
+	writel(control, edmac->regs + M2P_CONTROL);
+	/*
+	 * EP93xx User's Guide states that we must perform a dummy read after
+	 * write to the control register.
+	 */
+	readl(edmac->regs + M2P_CONTROL);
+}
+
+static int m2p_hw_setup(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_data *data = edmac->chan.private;
+	u32 control;
+
+	writel(data->port & 0xf, edmac->regs + M2P_PPALLOC);
+
+	control = M2P_CONTROL_CH_ERROR_INT | M2P_CONTROL_ICE
+		| M2P_CONTROL_ENABLE;
+	m2p_set_control(edmac, control);
+
+	return 0;
+}
+
+static inline u32 m2p_channel_state(struct ep93xx_dma_chan *edmac)
+{
+	return (readl(edmac->regs + M2P_STATUS) >> 4) & 0x3;
+}
+
+static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
+{
+	u32 control;
+
+	control = readl(edmac->regs + M2P_CONTROL);
+	control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
+	m2p_set_control(edmac, control);
+
+	while (m2p_channel_state(edmac) >= M2P_STATE_ON)
+		cpu_relax();
+
+	m2p_set_control(edmac, 0);
+
+	while (m2p_channel_state(edmac) == M2P_STATE_STALL)
+		cpu_relax();
+}
+
+static void m2p_fill_desc(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+	u32 bus_addr;
+
+	if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_TO_DEVICE)
+		bus_addr = desc->src_addr;
+	else
+		bus_addr = desc->dst_addr;
+
+	if (edmac->buffer == 0) {
+		writel(desc->size, edmac->regs + M2P_MAXCNT0);
+		writel(bus_addr, edmac->regs + M2P_BASE0);
+	} else {
+		writel(desc->size, edmac->regs + M2P_MAXCNT1);
+		writel(bus_addr, edmac->regs + M2P_BASE1);
+	}
+
+	edmac->buffer ^= 1;
+}
+
+static void m2p_hw_submit(struct ep93xx_dma_chan *edmac)
+{
+	u32 control = readl(edmac->regs + M2P_CONTROL);
+
+	m2p_fill_desc(edmac);
+	control |= M2P_CONTROL_STALLINT;
+
+	if (ep93xx_dma_advance_active(edmac)) {
+		m2p_fill_desc(edmac);
+		control |= M2P_CONTROL_NFBINT;
+	}
+
+	m2p_set_control(edmac, control);
+}
+
+static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac)
+{
+	u32 irq_status = readl(edmac->regs + M2P_INTERRUPT);
+	u32 control;
+
+	if (irq_status & M2P_INTERRUPT_ERROR) {
+		struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+
+		/* Clear the error interrupt */
+		writel(1, edmac->regs + M2P_INTERRUPT);
+
+		/*
+		 * It seems that there is no easy way of reporting errors back
+		 * to client so we just report the error here and continue as
+		 * usual.
+		 *
+		 * Revisit this when there is a mechanism to report back the
+		 * errors.
+		 */
+		dev_err(chan2dev(edmac),
+			"DMA transfer failed! Details:\n"
+			"\tcookie	: %d\n"
+			"\tsrc_addr	: 0x%08x\n"
+			"\tdst_addr	: 0x%08x\n"
+			"\tsize		: %zu\n",
+			desc->txd.cookie, desc->src_addr, desc->dst_addr,
+			desc->size);
+	}
+
+	switch (irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) {
+	case M2P_INTERRUPT_STALL:
+		/* Disable interrupts */
+		control = readl(edmac->regs + M2P_CONTROL);
+		control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
+		m2p_set_control(edmac, control);
+
+		return INTERRUPT_DONE;
+
+	case M2P_INTERRUPT_NFB:
+		if (ep93xx_dma_advance_active(edmac))
+			m2p_fill_desc(edmac);
+
+		return INTERRUPT_NEXT_BUFFER;
+	}
+
+	return INTERRUPT_UNKNOWN;
+}
+
+/*
+ * M2M DMA implementation
+ *
+ * For the M2M transfers we don't use NFB at all. This is because it simply
+ * doesn't work well with memcpy transfers. When you submit both buffers it is
+ * extremely unlikely that you get an NFB interrupt, but it instead reports
+ * DONE interrupt and both buffers are already transferred which means that we
+ * weren't able to update the next buffer.
+ *
+ * So for now we "simulate" NFB by just submitting buffer after buffer
+ * without double buffering.
+ */
+
+static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
+{
+	const struct ep93xx_dma_data *data = edmac->chan.private;
+	u32 control = 0;
+
+	if (!data) {
+		/* This is memcpy channel, nothing to configure */
+		writel(control, edmac->regs + M2M_CONTROL);
+		return 0;
+	}
+
+	switch (data->port) {
+	case EP93XX_DMA_SSP:
+		/*
+		 * This was found via experimenting - anything less than 5
+		 * causes the channel to perform only a partial transfer which
+		 * leads to problems since we don't get DONE interrupt then.
+		 */
+		control = (5 << M2M_CONTROL_PWSC_SHIFT);
+		control |= M2M_CONTROL_NO_HDSK;
+
+		if (data->direction == DMA_TO_DEVICE) {
+			control |= M2M_CONTROL_DAH;
+			control |= M2M_CONTROL_TM_TX;
+			control |= M2M_CONTROL_RSS_SSPTX;
+		} else {
+			control |= M2M_CONTROL_SAH;
+			control |= M2M_CONTROL_TM_RX;
+			control |= M2M_CONTROL_RSS_SSPRX;
+		}
+		break;
+
+	case EP93XX_DMA_IDE:
+		/*
+		 * This IDE part is totally untested. Values below are taken
+		 * from the EP93xx Users's Guide and might not be correct.
+		 */
+		control |= M2M_CONTROL_NO_HDSK;
+		control |= M2M_CONTROL_RSS_IDE;
+		control |= M2M_CONTROL_PW_16;
+
+		if (data->direction == DMA_TO_DEVICE) {
+			/* Worst case from the UG */
+			control = (3 << M2M_CONTROL_PWSC_SHIFT);
+			control |= M2M_CONTROL_DAH;
+			control |= M2M_CONTROL_TM_TX;
+		} else {
+			control = (2 << M2M_CONTROL_PWSC_SHIFT);
+			control |= M2M_CONTROL_SAH;
+			control |= M2M_CONTROL_TM_RX;
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	writel(control, edmac->regs + M2M_CONTROL);
+	return 0;
+}
+
+static void m2m_hw_shutdown(struct ep93xx_dma_chan *edmac)
+{
+	/* Just disable the channel */
+	writel(0, edmac->regs + M2M_CONTROL);
+}
+
+static void m2m_fill_desc(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+
+	if (edmac->buffer == 0) {
+		writel(desc->src_addr, edmac->regs + M2M_SAR_BASE0);
+		writel(desc->dst_addr, edmac->regs + M2M_DAR_BASE0);
+		writel(desc->size, edmac->regs + M2M_BCR0);
+	} else {
+		writel(desc->src_addr, edmac->regs + M2M_SAR_BASE1);
+		writel(desc->dst_addr, edmac->regs + M2M_DAR_BASE1);
+		writel(desc->size, edmac->regs + M2M_BCR1);
+	}
+
+	edmac->buffer ^= 1;
+}
+
+static void m2m_hw_submit(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_data *data = edmac->chan.private;
+	u32 control = readl(edmac->regs + M2M_CONTROL);
+
+	/*
+	 * Since we allow clients to configure PW (peripheral width) we always
+	 * clear PW bits here and then set them according what is given in
+	 * the runtime configuration.
+	 */
+	control &= ~M2M_CONTROL_PW_MASK;
+	control |= edmac->runtime_ctrl;
+
+	m2m_fill_desc(edmac);
+	control |= M2M_CONTROL_DONEINT;
+
+	/*
+	 * Now we can finally enable the channel. For M2M channel this must be
+	 * done _after_ the BCRx registers are programmed.
+	 */
+	control |= M2M_CONTROL_ENABLE;
+	writel(control, edmac->regs + M2M_CONTROL);
+
+	if (!data) {
+		/*
+		 * For memcpy channels the software trigger must be asserted
+		 * in order to start the memcpy operation.
+		 */
+		control |= M2M_CONTROL_START;
+		writel(control, edmac->regs + M2M_CONTROL);
+	}
+}
+
+static int m2m_hw_interrupt(struct ep93xx_dma_chan *edmac)
+{
+	u32 control;
+
+	if (!(readl(edmac->regs + M2M_INTERRUPT) & M2M_INTERRUPT_DONEINT))
+		return INTERRUPT_UNKNOWN;
+
+	/* Clear the DONE bit */
+	writel(0, edmac->regs + M2M_INTERRUPT);
+
+	/* Disable interrupts and the channel */
+	control = readl(edmac->regs + M2M_CONTROL);
+	control &= ~(M2M_CONTROL_DONEINT | M2M_CONTROL_ENABLE);
+	writel(control, edmac->regs + M2M_CONTROL);
+
+	/*
+	 * Since we only get DONE interrupt we have to find out ourselves
+	 * whether there still is something to process. So we try to advance
+	 * the chain an see whether it succeeds.
+	 */
+	if (ep93xx_dma_advance_active(edmac)) {
+		edmac->edma->hw_submit(edmac);
+		return INTERRUPT_NEXT_BUFFER;
+	}
+
+	return INTERRUPT_DONE;
+}
+
+/*
+ * DMA engine API implementation
+ */
+
+static struct ep93xx_dma_desc *
+ep93xx_dma_desc_get(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *desc, *_desc;
+	struct ep93xx_dma_desc *ret = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	list_for_each_entry_safe(desc, _desc, &edmac->free_list, node) {
+		if (async_tx_test_ack(&desc->txd)) {
+			list_del_init(&desc->node);
+
+			/* Re-initialize the descriptor */
+			desc->src_addr = 0;
+			desc->dst_addr = 0;
+			desc->size = 0;
+			desc->complete = false;
+			desc->txd.cookie = 0;
+			desc->txd.callback = NULL;
+			desc->txd.callback_param = NULL;
+
+			ret = desc;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&edmac->lock, flags);
+	return ret;
+}
+
+static void ep93xx_dma_desc_put(struct ep93xx_dma_chan *edmac,
+				struct ep93xx_dma_desc *desc)
+{
+	if (desc) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&edmac->lock, flags);
+		list_splice_init(&desc->tx_list, &edmac->free_list);
+		list_add(&desc->node, &edmac->free_list);
+		spin_unlock_irqrestore(&edmac->lock, flags);
+	}
+}
+
+/**
+ * ep93xx_dma_advance_work - start processing the next pending transaction
+ * @edmac: channel
+ *
+ * If we have pending transactions queued and we are currently idling, this
+ * function takes the next queued transaction from the @edmac->queue and
+ * pushes it to the hardware for execution.
+ */
+static void ep93xx_dma_advance_work(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *new;
+	unsigned long flags;
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	if (!list_empty(&edmac->active) || list_empty(&edmac->queue)) {
+		spin_unlock_irqrestore(&edmac->lock, flags);
+		return;
+	}
+
+	/* Take the next descriptor from the pending queue */
+	new = list_first_entry(&edmac->queue, struct ep93xx_dma_desc, node);
+	list_del_init(&new->node);
+
+	ep93xx_dma_set_active(edmac, new);
+
+	/* Push it to the hardware */
+	edmac->edma->hw_submit(edmac);
+	spin_unlock_irqrestore(&edmac->lock, flags);
+}
+
+static void ep93xx_dma_unmap_buffers(struct ep93xx_dma_desc *desc)
+{
+	struct device *dev = desc->txd.chan->device->dev;
+
+	if (!(desc->txd.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+		if (desc->txd.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+			dma_unmap_single(dev, desc->src_addr, desc->size,
+					 DMA_TO_DEVICE);
+		else
+			dma_unmap_page(dev, desc->src_addr, desc->size,
+				       DMA_TO_DEVICE);
+	}
+	if (!(desc->txd.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+		if (desc->txd.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+			dma_unmap_single(dev, desc->dst_addr, desc->size,
+					 DMA_FROM_DEVICE);
+		else
+			dma_unmap_page(dev, desc->dst_addr, desc->size,
+				       DMA_FROM_DEVICE);
+	}
+}
+
+static void ep93xx_dma_tasklet(unsigned long data)
+{
+	struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data;
+	struct ep93xx_dma_desc *desc, *d;
+	dma_async_tx_callback callback;
+	void *callback_param;
+	LIST_HEAD(list);
+
+	spin_lock_irq(&edmac->lock);
+	desc = ep93xx_dma_get_active(edmac);
+	if (desc->complete) {
+		edmac->last_completed = desc->txd.cookie;
+		list_splice_init(&edmac->active, &list);
+	}
+	spin_unlock_irq(&edmac->lock);
+
+	/* Pick up the next descriptor from the queue */
+	ep93xx_dma_advance_work(edmac);
+
+	callback = desc->txd.callback;
+	callback_param = desc->txd.callback_param;
+
+	/* Now we can release all the chained descriptors */
+	list_for_each_entry_safe(desc, d, &list, node) {
+		/*
+		 * For the memcpy channels the API requires us to unmap the
+		 * buffers unless requested otherwise.
+		 */
+		if (!edmac->chan.private)
+			ep93xx_dma_unmap_buffers(desc);
+
+		ep93xx_dma_desc_put(edmac, desc);
+	}
+
+	if (callback)
+		callback(callback_param);
+}
+
+static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id)
+{
+	struct ep93xx_dma_chan *edmac = dev_id;
+	irqreturn_t ret = IRQ_HANDLED;
+
+	spin_lock(&edmac->lock);
+
+	switch (edmac->edma->hw_interrupt(edmac)) {
+	case INTERRUPT_DONE:
+		ep93xx_dma_get_active(edmac)->complete = true;
+		tasklet_schedule(&edmac->tasklet);
+		break;
+
+	case INTERRUPT_NEXT_BUFFER:
+		if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
+			tasklet_schedule(&edmac->tasklet);
+		break;
+
+	default:
+		dev_warn(chan2dev(edmac), "unknown interrupt!\n");
+		ret = IRQ_NONE;
+		break;
+	}
+
+	spin_unlock(&edmac->lock);
+	return ret;
+}
+
+/**
+ * ep93xx_dma_tx_submit - set the prepared descriptor(s) to be executed
+ * @tx: descriptor to be executed
+ *
+ * Function will execute given descriptor on the hardware or if the hardware
+ * is busy, queue the descriptor to be executed later on. Returns cookie which
+ * can be used to poll the status of the descriptor.
+ */
+static dma_cookie_t ep93xx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(tx->chan);
+	struct ep93xx_dma_desc *desc;
+	dma_cookie_t cookie;
+	unsigned long flags;
+
+	spin_lock_irqsave(&edmac->lock, flags);
+
+	cookie = edmac->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	desc = container_of(tx, struct ep93xx_dma_desc, txd);
+
+	edmac->chan.cookie = cookie;
+	desc->txd.cookie = cookie;
+
+	/*
+	 * If nothing is currently prosessed, we push this descriptor
+	 * directly to the hardware. Otherwise we put the descriptor
+	 * to the pending queue.
+	 */
+	if (list_empty(&edmac->active)) {
+		ep93xx_dma_set_active(edmac, desc);
+		edmac->edma->hw_submit(edmac);
+	} else {
+		list_add_tail(&desc->node, &edmac->queue);
+	}
+
+	spin_unlock_irqrestore(&edmac->lock, flags);
+	return cookie;
+}
+
+/**
+ * ep93xx_dma_alloc_chan_resources - allocate resources for the channel
+ * @chan: channel to allocate resources
+ *
+ * Function allocates necessary resources for the given DMA channel and
+ * returns number of allocated descriptors for the channel. Negative errno
+ * is returned in case of failure.
+ */
+static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_data *data = chan->private;
+	const char *name = dma_chan_name(chan);
+	int ret, i;
+
+	/* Sanity check the channel parameters */
+	if (!edmac->edma->m2m) {
+		if (!data)
+			return -EINVAL;
+		if (data->port < EP93XX_DMA_I2S1 ||
+		    data->port > EP93XX_DMA_IRDA)
+			return -EINVAL;
+		if (data->direction != ep93xx_dma_chan_direction(chan))
+			return -EINVAL;
+	} else {
+		if (data) {
+			switch (data->port) {
+			case EP93XX_DMA_SSP:
+			case EP93XX_DMA_IDE:
+				if (data->direction != DMA_TO_DEVICE &&
+				    data->direction != DMA_FROM_DEVICE)
+					return -EINVAL;
+				break;
+			default:
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (data && data->name)
+		name = data->name;
+
+	ret = clk_enable(edmac->clk);
+	if (ret)
+		return ret;
+
+	ret = request_irq(edmac->irq, ep93xx_dma_interrupt, 0, name, edmac);
+	if (ret)
+		goto fail_clk_disable;
+
+	spin_lock_irq(&edmac->lock);
+	edmac->last_completed = 1;
+	edmac->chan.cookie = 1;
+	ret = edmac->edma->hw_setup(edmac);
+	spin_unlock_irq(&edmac->lock);
+
+	if (ret)
+		goto fail_free_irq;
+
+	for (i = 0; i < DMA_MAX_CHAN_DESCRIPTORS; i++) {
+		struct ep93xx_dma_desc *desc;
+
+		desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+		if (!desc) {
+			dev_warn(chan2dev(edmac), "not enough descriptors\n");
+			break;
+		}
+
+		INIT_LIST_HEAD(&desc->tx_list);
+
+		dma_async_tx_descriptor_init(&desc->txd, chan);
+		desc->txd.flags = DMA_CTRL_ACK;
+		desc->txd.tx_submit = ep93xx_dma_tx_submit;
+
+		ep93xx_dma_desc_put(edmac, desc);
+	}
+
+	return i;
+
+fail_free_irq:
+	free_irq(edmac->irq, edmac);
+fail_clk_disable:
+	clk_disable(edmac->clk);
+
+	return ret;
+}
+
+/**
+ * ep93xx_dma_free_chan_resources - release resources for the channel
+ * @chan: channel
+ *
+ * Function releases all the resources allocated for the given channel.
+ * The channel must be idle when this is called.
+ */
+static void ep93xx_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_desc *desc, *d;
+	unsigned long flags;
+	LIST_HEAD(list);
+
+	BUG_ON(!list_empty(&edmac->active));
+	BUG_ON(!list_empty(&edmac->queue));
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	edmac->edma->hw_shutdown(edmac);
+	edmac->runtime_addr = 0;
+	edmac->runtime_ctrl = 0;
+	edmac->buffer = 0;
+	list_splice_init(&edmac->free_list, &list);
+	spin_unlock_irqrestore(&edmac->lock, flags);
+
+	list_for_each_entry_safe(desc, d, &list, node)
+		kfree(desc);
+
+	clk_disable(edmac->clk);
+	free_irq(edmac->irq, edmac);
+}
+
+/**
+ * ep93xx_dma_prep_dma_memcpy - prepare a memcpy DMA operation
+ * @chan: channel
+ * @dest: destination bus address
+ * @src: source bus address
+ * @len: size of the transaction
+ * @flags: flags for the descriptor
+ *
+ * Returns a valid DMA descriptor or %NULL in case of failure.
+ */
+struct dma_async_tx_descriptor *
+ep93xx_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
+			   dma_addr_t src, size_t len, unsigned long flags)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_desc *desc, *first;
+	size_t bytes, offset;
+
+	first = NULL;
+	for (offset = 0; offset < len; offset += bytes) {
+		desc = ep93xx_dma_desc_get(edmac);
+		if (!desc) {
+			dev_warn(chan2dev(edmac), "couln't get descriptor\n");
+			goto fail;
+		}
+
+		bytes = min_t(size_t, len - offset, DMA_MAX_CHAN_BYTES);
+
+		desc->src_addr = src + offset;
+		desc->dst_addr = dest + offset;
+		desc->size = bytes;
+
+		if (!first)
+			first = desc;
+		else
+			list_add_tail(&desc->node, &first->tx_list);
+	}
+
+	first->txd.cookie = -EBUSY;
+	first->txd.flags = flags;
+
+	return &first->txd;
+fail:
+	ep93xx_dma_desc_put(edmac, first);
+	return NULL;
+}
+
+/**
+ * ep93xx_dma_prep_slave_sg - prepare a slave DMA operation
+ * @chan: channel
+ * @sgl: list of buffers to transfer
+ * @sg_len: number of entries in @sgl
+ * @dir: direction of tha DMA transfer
+ * @flags: flags for the descriptor
+ *
+ * Returns a valid DMA descriptor or %NULL in case of failure.
+ */
+static struct dma_async_tx_descriptor *
+ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+			 unsigned int sg_len, enum dma_data_direction dir,
+			 unsigned long flags)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_desc *desc, *first;
+	struct scatterlist *sg;
+	int i;
+
+	if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) {
+		dev_warn(chan2dev(edmac),
+			 "channel was configured with different direction\n");
+		return NULL;
+	}
+
+	if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) {
+		dev_warn(chan2dev(edmac),
+			 "channel is already used for cyclic transfers\n");
+		return NULL;
+	}
+
+	first = NULL;
+	for_each_sg(sgl, sg, sg_len, i) {
+		size_t sg_len = sg_dma_len(sg);
+
+		if (sg_len > DMA_MAX_CHAN_BYTES) {
+			dev_warn(chan2dev(edmac), "too big transfer size %d\n",
+				 sg_len);
+			goto fail;
+		}
+
+		desc = ep93xx_dma_desc_get(edmac);
+		if (!desc) {
+			dev_warn(chan2dev(edmac), "couln't get descriptor\n");
+			goto fail;
+		}
+
+		if (dir == DMA_TO_DEVICE) {
+			desc->src_addr = sg_dma_address(sg);
+			desc->dst_addr = edmac->runtime_addr;
+		} else {
+			desc->src_addr = edmac->runtime_addr;
+			desc->dst_addr = sg_dma_address(sg);
+		}
+		desc->size = sg_len;
+
+		if (!first)
+			first = desc;
+		else
+			list_add_tail(&desc->node, &first->tx_list);
+	}
+
+	first->txd.cookie = -EBUSY;
+	first->txd.flags = flags;
+
+	return &first->txd;
+
+fail:
+	ep93xx_dma_desc_put(edmac, first);
+	return NULL;
+}
+
+/**
+ * ep93xx_dma_prep_dma_cyclic - prepare a cyclic DMA operation
+ * @chan: channel
+ * @dma_addr: DMA mapped address of the buffer
+ * @buf_len: length of the buffer (in bytes)
+ * @period_len: lenght of a single period
+ * @dir: direction of the operation
+ *
+ * Prepares a descriptor for cyclic DMA operation. This means that once the
+ * descriptor is submitted, we will be submitting in a @period_len sized
+ * buffers and calling callback once the period has been elapsed. Transfer
+ * terminates only when client calls dmaengine_terminate_all() for this
+ * channel.
+ *
+ * Returns a valid DMA descriptor or %NULL in case of failure.
+ */
+static struct dma_async_tx_descriptor *
+ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
+			   size_t buf_len, size_t period_len,
+			   enum dma_data_direction dir)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_desc *desc, *first;
+	size_t offset = 0;
+
+	if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) {
+		dev_warn(chan2dev(edmac),
+			 "channel was configured with different direction\n");
+		return NULL;
+	}
+
+	if (test_and_set_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) {
+		dev_warn(chan2dev(edmac),
+			 "channel is already used for cyclic transfers\n");
+		return NULL;
+	}
+
+	if (period_len > DMA_MAX_CHAN_BYTES) {
+		dev_warn(chan2dev(edmac), "too big period length %d\n",
+			 period_len);
+		return NULL;
+	}
+
+	/* Split the buffer into period size chunks */
+	first = NULL;
+	for (offset = 0; offset < buf_len; offset += period_len) {
+		desc = ep93xx_dma_desc_get(edmac);
+		if (!desc) {
+			dev_warn(chan2dev(edmac), "couln't get descriptor\n");
+			goto fail;
+		}
+
+		if (dir == DMA_TO_DEVICE) {
+			desc->src_addr = dma_addr + offset;
+			desc->dst_addr = edmac->runtime_addr;
+		} else {
+			desc->src_addr = edmac->runtime_addr;
+			desc->dst_addr = dma_addr + offset;
+		}
+
+		desc->size = period_len;
+
+		if (!first)
+			first = desc;
+		else
+			list_add_tail(&desc->node, &first->tx_list);
+	}
+
+	first->txd.cookie = -EBUSY;
+
+	return &first->txd;
+
+fail:
+	ep93xx_dma_desc_put(edmac, first);
+	return NULL;
+}
+
+/**
+ * ep93xx_dma_terminate_all - terminate all transactions
+ * @edmac: channel
+ *
+ * Stops all DMA transactions. All descriptors are put back to the
+ * @edmac->free_list and callbacks are _not_ called.
+ */
+static int ep93xx_dma_terminate_all(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *desc, *_d;
+	unsigned long flags;
+	LIST_HEAD(list);
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	/* First we disable and flush the DMA channel */
+	edmac->edma->hw_shutdown(edmac);
+	clear_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags);
+	list_splice_init(&edmac->active, &list);
+	list_splice_init(&edmac->queue, &list);
+	/*
+	 * We then re-enable the channel. This way we can continue submitting
+	 * the descriptors by just calling ->hw_submit() again.
+	 */
+	edmac->edma->hw_setup(edmac);
+	spin_unlock_irqrestore(&edmac->lock, flags);
+
+	list_for_each_entry_safe(desc, _d, &list, node)
+		ep93xx_dma_desc_put(edmac, desc);
+
+	return 0;
+}
+
+static int ep93xx_dma_slave_config(struct ep93xx_dma_chan *edmac,
+				   struct dma_slave_config *config)
+{
+	enum dma_slave_buswidth width;
+	unsigned long flags;
+	u32 addr, ctrl;
+
+	if (!edmac->edma->m2m)
+		return -EINVAL;
+
+	switch (config->direction) {
+	case DMA_FROM_DEVICE:
+		width = config->src_addr_width;
+		addr = config->src_addr;
+		break;
+
+	case DMA_TO_DEVICE:
+		width = config->dst_addr_width;
+		addr = config->dst_addr;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	switch (width) {
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+		ctrl = 0;
+		break;
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+		ctrl = M2M_CONTROL_PW_16;
+		break;
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+		ctrl = M2M_CONTROL_PW_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	edmac->runtime_addr = addr;
+	edmac->runtime_ctrl = ctrl;
+	spin_unlock_irqrestore(&edmac->lock, flags);
+
+	return 0;
+}
+
+/**
+ * ep93xx_dma_control - manipulate all pending operations on a channel
+ * @chan: channel
+ * @cmd: control command to perform
+ * @arg: optional argument
+ *
+ * Controls the channel. Function returns %0 in case of success or negative
+ * error in case of failure.
+ */
+static int ep93xx_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+			      unsigned long arg)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct dma_slave_config *config;
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		return ep93xx_dma_terminate_all(edmac);
+
+	case DMA_SLAVE_CONFIG:
+		config = (struct dma_slave_config *)arg;
+		return ep93xx_dma_slave_config(edmac, config);
+
+	default:
+		break;
+	}
+
+	return -ENOSYS;
+}
+
+/**
+ * ep93xx_dma_tx_status - check if a transaction is completed
+ * @chan: channel
+ * @cookie: transaction specific cookie
+ * @state: state of the transaction is stored here if given
+ *
+ * This function can be used to query state of a given transaction.
+ */
+static enum dma_status ep93xx_dma_tx_status(struct dma_chan *chan,
+					    dma_cookie_t cookie,
+					    struct dma_tx_state *state)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	dma_cookie_t last_used, last_completed;
+	enum dma_status ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	last_used = chan->cookie;
+	last_completed = edmac->last_completed;
+	spin_unlock_irqrestore(&edmac->lock, flags);
+
+	ret = dma_async_is_complete(cookie, last_completed, last_used);
+	dma_set_tx_state(state, last_completed, last_used, 0);
+
+	return ret;
+}
+
+/**
+ * ep93xx_dma_issue_pending - push pending transactions to the hardware
+ * @chan: channel
+ *
+ * When this function is called, all pending transactions are pushed to the
+ * hardware and executed.
+ */
+static void ep93xx_dma_issue_pending(struct dma_chan *chan)
+{
+	ep93xx_dma_advance_work(to_ep93xx_dma_chan(chan));
+}
+
+static int __init ep93xx_dma_probe(struct platform_device *pdev)
+{
+	struct ep93xx_dma_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct ep93xx_dma_engine *edma;
+	struct dma_device *dma_dev;
+	size_t edma_size;
+	int ret, i;
+
+	edma_size = pdata->num_channels * sizeof(struct ep93xx_dma_chan);
+	edma = kzalloc(sizeof(*edma) + edma_size, GFP_KERNEL);
+	if (!edma)
+		return -ENOMEM;
+
+	dma_dev = &edma->dma_dev;
+	edma->m2m = platform_get_device_id(pdev)->driver_data;
+	edma->num_channels = pdata->num_channels;
+
+	INIT_LIST_HEAD(&dma_dev->channels);
+	for (i = 0; i < pdata->num_channels; i++) {
+		const struct ep93xx_dma_chan_data *cdata = &pdata->channels[i];
+		struct ep93xx_dma_chan *edmac = &edma->channels[i];
+
+		edmac->chan.device = dma_dev;
+		edmac->regs = cdata->base;
+		edmac->irq = cdata->irq;
+		edmac->edma = edma;
+
+		edmac->clk = clk_get(NULL, cdata->name);
+		if (IS_ERR(edmac->clk)) {
+			dev_warn(&pdev->dev, "failed to get clock for %s\n",
+				 cdata->name);
+			continue;
+		}
+
+		spin_lock_init(&edmac->lock);
+		INIT_LIST_HEAD(&edmac->active);
+		INIT_LIST_HEAD(&edmac->queue);
+		INIT_LIST_HEAD(&edmac->free_list);
+		tasklet_init(&edmac->tasklet, ep93xx_dma_tasklet,
+			     (unsigned long)edmac);
+
+		list_add_tail(&edmac->chan.device_node,
+			      &dma_dev->channels);
+	}
+
+	dma_cap_zero(dma_dev->cap_mask);
+	dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
+	dma_cap_set(DMA_CYCLIC, dma_dev->cap_mask);
+
+	dma_dev->dev = &pdev->dev;
+	dma_dev->device_alloc_chan_resources = ep93xx_dma_alloc_chan_resources;
+	dma_dev->device_free_chan_resources = ep93xx_dma_free_chan_resources;
+	dma_dev->device_prep_slave_sg = ep93xx_dma_prep_slave_sg;
+	dma_dev->device_prep_dma_cyclic = ep93xx_dma_prep_dma_cyclic;
+	dma_dev->device_control = ep93xx_dma_control;
+	dma_dev->device_issue_pending = ep93xx_dma_issue_pending;
+	dma_dev->device_tx_status = ep93xx_dma_tx_status;
+
+	dma_set_max_seg_size(dma_dev->dev, DMA_MAX_CHAN_BYTES);
+
+	if (edma->m2m) {
+		dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+		dma_dev->device_prep_dma_memcpy = ep93xx_dma_prep_dma_memcpy;
+
+		edma->hw_setup = m2m_hw_setup;
+		edma->hw_shutdown = m2m_hw_shutdown;
+		edma->hw_submit = m2m_hw_submit;
+		edma->hw_interrupt = m2m_hw_interrupt;
+	} else {
+		dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
+
+		edma->hw_setup = m2p_hw_setup;
+		edma->hw_shutdown = m2p_hw_shutdown;
+		edma->hw_submit = m2p_hw_submit;
+		edma->hw_interrupt = m2p_hw_interrupt;
+	}
+
+	ret = dma_async_device_register(dma_dev);
+	if (unlikely(ret)) {
+		for (i = 0; i < edma->num_channels; i++) {
+			struct ep93xx_dma_chan *edmac = &edma->channels[i];
+			if (!IS_ERR_OR_NULL(edmac->clk))
+				clk_put(edmac->clk);
+		}
+		kfree(edma);
+	} else {
+		dev_info(dma_dev->dev, "EP93xx M2%s DMA ready\n",
+			 edma->m2m ? "M" : "P");
+	}
+
+	return ret;
+}
+
+static struct platform_device_id ep93xx_dma_driver_ids[] = {
+	{ "ep93xx-dma-m2p", 0 },
+	{ "ep93xx-dma-m2m", 1 },
+	{ },
+};
+
+static struct platform_driver ep93xx_dma_driver = {
+	.driver		= {
+		.name	= "ep93xx-dma",
+	},
+	.id_table	= ep93xx_dma_driver_ids,
+};
+
+static int __init ep93xx_dma_module_init(void)
+{
+	return platform_driver_probe(&ep93xx_dma_driver, ep93xx_dma_probe);
+}
+subsys_initcall(ep93xx_dma_module_init);
+
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
+MODULE_DESCRIPTION("EP93xx DMA driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index de35c3ad8a69..52e2900d9d8e 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -86,9 +86,6 @@ config SPI_BFIN_SPORT
 	help
 	  Enable support for a SPI bus via the Blackfin SPORT peripheral.
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called spi_bfin_sport.
-
 config SPI_AU1550
 	tristate "Au1550/Au12x0 SPI Controller"
 	depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
@@ -97,9 +94,6 @@ config SPI_AU1550
 	  If you say yes to this option, support will be included for the
 	  Au1550 SPI controller (may also work with Au1200,Au1210,Au1250).
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called au1550_spi.
-
 config SPI_BITBANG
 	tristate "Utilities for Bitbanging SPI masters"
 	help
@@ -130,9 +124,6 @@ config SPI_COLDFIRE_QSPI
 	  This enables support for the Coldfire QSPI controller in master
 	  mode.
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called coldfire_qspi.
-
 config SPI_DAVINCI
 	tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
 	depends on SPI_MASTER && ARCH_DAVINCI
@@ -140,9 +131,6 @@ config SPI_DAVINCI
 	help
 	  SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
 
-	  This driver can also be built as a module. The module will be called
-	  davinci_spi.
-
 config SPI_EP93XX
 	tristate "Cirrus Logic EP93xx SPI controller"
 	depends on ARCH_EP93XX
@@ -150,9 +138,6 @@ config SPI_EP93XX
 	  This enables using the Cirrus EP93xx SPI controller in master
 	  mode.
 
-	  To compile this driver as a module, choose M here. The module will be
-	  called ep93xx_spi.
-
 config SPI_GPIO
 	tristate "GPIO-based bitbanging SPI Master"
 	depends on GENERIC_GPIO
@@ -169,21 +154,6 @@ config SPI_GPIO
 	  GPIO operations, you should be able to leverage that for better
 	  speed with a custom version of this driver; see the source code.
 
-config SPI_IMX_VER_IMX1
-	def_bool y if SOC_IMX1
-
-config SPI_IMX_VER_0_0
-	def_bool y if SOC_IMX21 || SOC_IMX27
-
-config SPI_IMX_VER_0_4
-	def_bool y if SOC_IMX31
-
-config SPI_IMX_VER_0_7
-	def_bool y if ARCH_MX25 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
-
-config SPI_IMX_VER_2_3
-	def_bool y if SOC_IMX51 || SOC_IMX53
-
 config SPI_IMX
 	tristate "Freescale i.MX SPI controllers"
 	depends on ARCH_MXC
@@ -328,16 +298,6 @@ config SPI_S3C24XX_FIQ
 	  no free DMA channels, or when doing transfers that required both
 	  TX and RX data paths.
 
-config SPI_S3C24XX_GPIO
-	tristate "Samsung S3C24XX series SPI by GPIO"
-	depends on ARCH_S3C2410 && EXPERIMENTAL
-	select SPI_BITBANG
-	help
-	  SPI driver for Samsung S3C24XX series ARM SoCs using
-	  GPIO lines to provide the SPI bus. This can be used where
-	  the inbuilt hardware cannot provide the transfer mode, or
-	  where the board is using non hardware connected pins.
-
 config SPI_S3C64XX
 	tristate "Samsung S3C64XX series type SPI"
 	depends on (ARCH_S3C64XX || ARCH_S5P64X0)
@@ -385,16 +345,16 @@ config SPI_TI_SSP
 	  This selects an SPI master implementation using a TI sequencer
 	  serial port.
 
-	  To compile this driver as a module, choose M here: the
-	  module will be called ti-ssp-spi.
-
 config SPI_TOPCLIFF_PCH
-	tristate "Topcliff PCH SPI Controller"
+	tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH SPI controller"
 	depends on PCI
 	help
 	  SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus
 	  used in some x86 embedded processors.
 
+	  This driver also supports the ML7213, a companion chip for the
+	  Atom E6xx series and compatible with the Intel EG20T PCH.
+
 config SPI_TXX9
 	tristate "Toshiba TXx9 SPI controller"
 	depends on GENERIC_GPIO && CPU_TX49XX
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 0f8c69b6b19e..61c3261c388c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -7,68 +7,55 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG
 # small core, mostly translating board-specific
 # config declarations into driver model code
 obj-$(CONFIG_SPI_MASTER)		+= spi.o
+obj-$(CONFIG_SPI_SPIDEV)		+= spidev.o
 
 # SPI master controller drivers (bus)
-obj-$(CONFIG_SPI_ALTERA)		+= spi_altera.o
-obj-$(CONFIG_SPI_ATMEL)			+= atmel_spi.o
-obj-$(CONFIG_SPI_ATH79)			+= ath79_spi.o
-obj-$(CONFIG_SPI_BFIN)			+= spi_bfin5xx.o
-obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi_bfin_sport.o
-obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
-obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o
-obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
-obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= coldfire_qspi.o
-obj-$(CONFIG_SPI_DAVINCI)		+= davinci_spi.o
-obj-$(CONFIG_SPI_DESIGNWARE)		+= dw_spi.o
-obj-$(CONFIG_SPI_DW_PCI)		+= dw_spi_midpci.o
-dw_spi_midpci-objs			:= dw_spi_pci.o dw_spi_mid.o
-obj-$(CONFIG_SPI_DW_MMIO)		+= dw_spi_mmio.o
-obj-$(CONFIG_SPI_EP93XX)		+= ep93xx_spi.o
-obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o
-obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
-obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
-obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
-obj-$(CONFIG_SPI_PXA2XX_PCI)		+= pxa2xx_spi_pci.o
-obj-$(CONFIG_SPI_OC_TINY)		+= spi_oc_tiny.o
-obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
-obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
-obj-$(CONFIG_SPI_OMAP_100K)		+= omap_spi_100k.o
-obj-$(CONFIG_SPI_ORION)			+= orion_spi.o
-obj-$(CONFIG_SPI_PL022)			+= amba-pl022.o
-obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
-obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
-obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
-obj-$(CONFIG_SPI_FSL_LIB)		+= spi_fsl_lib.o
-obj-$(CONFIG_SPI_FSL_ESPI)		+= spi_fsl_espi.o
-obj-$(CONFIG_SPI_FSL_SPI)		+= spi_fsl_spi.o
-obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
-obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
-obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
-obj-$(CONFIG_SPI_S3C64XX)		+= spi_s3c64xx.o
-obj-$(CONFIG_SPI_TEGRA)			+= spi_tegra.o
-obj-$(CONFIG_SPI_TI_SSP)		+= ti-ssp-spi.o
-obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi_topcliff_pch.o
-obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
-obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
-obj-$(CONFIG_SPI_SH)			+= spi_sh.o
-obj-$(CONFIG_SPI_SH_SCI)		+= spi_sh_sci.o
-obj-$(CONFIG_SPI_SH_MSIOF)		+= spi_sh_msiof.o
-obj-$(CONFIG_SPI_STMP3XXX)		+= spi_stmp.o
-obj-$(CONFIG_SPI_NUC900)		+= spi_nuc900.o
+obj-$(CONFIG_SPI_ALTERA)		+= spi-altera.o
+obj-$(CONFIG_SPI_ATMEL)			+= spi-atmel.o
+obj-$(CONFIG_SPI_ATH79)			+= spi-ath79.o
+obj-$(CONFIG_SPI_AU1550)		+= spi-au1550.o
+obj-$(CONFIG_SPI_BFIN)			+= spi-bfin5xx.o
+obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi-bfin-sport.o
+obj-$(CONFIG_SPI_BITBANG)		+= spi-bitbang.o
+obj-$(CONFIG_SPI_BUTTERFLY)		+= spi-butterfly.o
+obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= spi-coldfire-qspi.o
+obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o
+obj-$(CONFIG_SPI_DESIGNWARE)		+= spi-dw.o
+obj-$(CONFIG_SPI_DW_MMIO)		+= spi-dw-mmio.o
+obj-$(CONFIG_SPI_DW_PCI)		+= spi-dw-midpci.o
+spi-dw-midpci-objs			:= spi-dw-pci.o spi-dw-mid.o
+obj-$(CONFIG_SPI_EP93XX)		+= spi-ep93xx.o
+obj-$(CONFIG_SPI_FSL_LIB)		+= spi-fsl-lib.o
+obj-$(CONFIG_SPI_FSL_ESPI)		+= spi-fsl-espi.o
+obj-$(CONFIG_SPI_FSL_SPI)		+= spi-fsl-spi.o
+obj-$(CONFIG_SPI_GPIO)			+= spi-gpio.o
+obj-$(CONFIG_SPI_IMX)			+= spi-imx.o
+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_NUC900)		+= spi-nuc900.o
+obj-$(CONFIG_SPI_OC_TINY)		+= spi-oc-tiny.o
+obj-$(CONFIG_SPI_OMAP_UWIRE)		+= spi-omap-uwire.o
+obj-$(CONFIG_SPI_OMAP_100K)		+= spi-omap-100k.o
+obj-$(CONFIG_SPI_OMAP24XX)		+= spi-omap2-mcspi.o
+obj-$(CONFIG_SPI_ORION)			+= spi-orion.o
+obj-$(CONFIG_SPI_PL022)			+= spi-pl022.o
+obj-$(CONFIG_SPI_PPC4xx)		+= spi-ppc4xx.o
+obj-$(CONFIG_SPI_PXA2XX)		+= spi-pxa2xx.o
+obj-$(CONFIG_SPI_PXA2XX_PCI)		+= spi-pxa2xx-pci.o
+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_SH)			+= spi-sh.o
+obj-$(CONFIG_SPI_SH_MSIOF)		+= spi-sh-msiof.o
+obj-$(CONFIG_SPI_SH_SCI)		+= spi-sh-sci.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
+obj-$(CONFIG_SPI_TXX9)			+= spi-txx9.o
+obj-$(CONFIG_SPI_XILINX)		+= spi-xilinx.o
 
-# special build for s3c24xx spi driver with fiq support
-spi_s3c24xx_hw-y			:= spi_s3c24xx.o
-spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o
-
-# 	... add above this line ...
-
-# SPI protocol drivers (device/link on bus)
-obj-$(CONFIG_SPI_SPIDEV)	+= spidev.o
-obj-$(CONFIG_SPI_TLE62X0)	+= tle62x0.o
-# 	... add above this line ...
-
-# SPI slave controller drivers (upstream link)
-# 	... add above this line ...
-
-# SPI slave drivers (protocol for that link)
-# 	... add above this line ...
diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h
deleted file mode 100644
index 6e06b6ad3a45..000000000000
--- a/drivers/spi/atmel_spi.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Register definitions for Atmel Serial Peripheral Interface (SPI)
- *
- * Copyright (C) 2006 Atmel Corporation
- *
- * 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.
- */
-#ifndef __ATMEL_SPI_H__
-#define __ATMEL_SPI_H__
-
-/* SPI register offsets */
-#define SPI_CR					0x0000
-#define SPI_MR					0x0004
-#define SPI_RDR					0x0008
-#define SPI_TDR					0x000c
-#define SPI_SR					0x0010
-#define SPI_IER					0x0014
-#define SPI_IDR					0x0018
-#define SPI_IMR					0x001c
-#define SPI_CSR0				0x0030
-#define SPI_CSR1				0x0034
-#define SPI_CSR2				0x0038
-#define SPI_CSR3				0x003c
-#define SPI_RPR					0x0100
-#define SPI_RCR					0x0104
-#define SPI_TPR					0x0108
-#define SPI_TCR					0x010c
-#define SPI_RNPR				0x0110
-#define SPI_RNCR				0x0114
-#define SPI_TNPR				0x0118
-#define SPI_TNCR				0x011c
-#define SPI_PTCR				0x0120
-#define SPI_PTSR				0x0124
-
-/* Bitfields in CR */
-#define SPI_SPIEN_OFFSET			0
-#define SPI_SPIEN_SIZE				1
-#define SPI_SPIDIS_OFFSET			1
-#define SPI_SPIDIS_SIZE				1
-#define SPI_SWRST_OFFSET			7
-#define SPI_SWRST_SIZE				1
-#define SPI_LASTXFER_OFFSET			24
-#define SPI_LASTXFER_SIZE			1
-
-/* Bitfields in MR */
-#define SPI_MSTR_OFFSET				0
-#define SPI_MSTR_SIZE				1
-#define SPI_PS_OFFSET				1
-#define SPI_PS_SIZE				1
-#define SPI_PCSDEC_OFFSET			2
-#define SPI_PCSDEC_SIZE				1
-#define SPI_FDIV_OFFSET				3
-#define SPI_FDIV_SIZE				1
-#define SPI_MODFDIS_OFFSET			4
-#define SPI_MODFDIS_SIZE			1
-#define SPI_LLB_OFFSET				7
-#define SPI_LLB_SIZE				1
-#define SPI_PCS_OFFSET				16
-#define SPI_PCS_SIZE				4
-#define SPI_DLYBCS_OFFSET			24
-#define SPI_DLYBCS_SIZE				8
-
-/* Bitfields in RDR */
-#define SPI_RD_OFFSET				0
-#define SPI_RD_SIZE				16
-
-/* Bitfields in TDR */
-#define SPI_TD_OFFSET				0
-#define SPI_TD_SIZE				16
-
-/* Bitfields in SR */
-#define SPI_RDRF_OFFSET				0
-#define SPI_RDRF_SIZE				1
-#define SPI_TDRE_OFFSET				1
-#define SPI_TDRE_SIZE				1
-#define SPI_MODF_OFFSET				2
-#define SPI_MODF_SIZE				1
-#define SPI_OVRES_OFFSET			3
-#define SPI_OVRES_SIZE				1
-#define SPI_ENDRX_OFFSET			4
-#define SPI_ENDRX_SIZE				1
-#define SPI_ENDTX_OFFSET			5
-#define SPI_ENDTX_SIZE				1
-#define SPI_RXBUFF_OFFSET			6
-#define SPI_RXBUFF_SIZE				1
-#define SPI_TXBUFE_OFFSET			7
-#define SPI_TXBUFE_SIZE				1
-#define SPI_NSSR_OFFSET				8
-#define SPI_NSSR_SIZE				1
-#define SPI_TXEMPTY_OFFSET			9
-#define SPI_TXEMPTY_SIZE			1
-#define SPI_SPIENS_OFFSET			16
-#define SPI_SPIENS_SIZE				1
-
-/* Bitfields in CSR0 */
-#define SPI_CPOL_OFFSET				0
-#define SPI_CPOL_SIZE				1
-#define SPI_NCPHA_OFFSET			1
-#define SPI_NCPHA_SIZE				1
-#define SPI_CSAAT_OFFSET			3
-#define SPI_CSAAT_SIZE				1
-#define SPI_BITS_OFFSET				4
-#define SPI_BITS_SIZE				4
-#define SPI_SCBR_OFFSET				8
-#define SPI_SCBR_SIZE				8
-#define SPI_DLYBS_OFFSET			16
-#define SPI_DLYBS_SIZE				8
-#define SPI_DLYBCT_OFFSET			24
-#define SPI_DLYBCT_SIZE				8
-
-/* Bitfields in RCR */
-#define SPI_RXCTR_OFFSET			0
-#define SPI_RXCTR_SIZE				16
-
-/* Bitfields in TCR */
-#define SPI_TXCTR_OFFSET			0
-#define SPI_TXCTR_SIZE				16
-
-/* Bitfields in RNCR */
-#define SPI_RXNCR_OFFSET			0
-#define SPI_RXNCR_SIZE				16
-
-/* Bitfields in TNCR */
-#define SPI_TXNCR_OFFSET			0
-#define SPI_TXNCR_SIZE				16
-
-/* Bitfields in PTCR */
-#define SPI_RXTEN_OFFSET			0
-#define SPI_RXTEN_SIZE				1
-#define SPI_RXTDIS_OFFSET			1
-#define SPI_RXTDIS_SIZE				1
-#define SPI_TXTEN_OFFSET			8
-#define SPI_TXTEN_SIZE				1
-#define SPI_TXTDIS_OFFSET			9
-#define SPI_TXTDIS_SIZE				1
-
-/* Constants for BITS */
-#define SPI_BITS_8_BPT				0
-#define SPI_BITS_9_BPT				1
-#define SPI_BITS_10_BPT				2
-#define SPI_BITS_11_BPT				3
-#define SPI_BITS_12_BPT				4
-#define SPI_BITS_13_BPT				5
-#define SPI_BITS_14_BPT				6
-#define SPI_BITS_15_BPT				7
-#define SPI_BITS_16_BPT				8
-
-/* Bit manipulation macros */
-#define SPI_BIT(name) \
-	(1 << SPI_##name##_OFFSET)
-#define SPI_BF(name,value) \
-	(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
-#define SPI_BFEXT(name,value) \
-	(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
-#define SPI_BFINS(name,value,old) \
-	( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
-	  | SPI_BF(name,value))
-
-/* Register access macros */
-#define spi_readl(port,reg) \
-	__raw_readl((port)->regs + SPI_##reg)
-#define spi_writel(port,reg,value) \
-	__raw_writel((value), (port)->regs + SPI_##reg)
-
-#endif /* __ATMEL_SPI_H__ */
diff --git a/drivers/spi/spi_altera.c b/drivers/spi/spi-altera.c
index 4813a63ce6fb..4813a63ce6fb 100644
--- a/drivers/spi/spi_altera.c
+++ b/drivers/spi/spi-altera.c
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/spi-ath79.c
index fcff810ea3b0..03019bf5a5e9 100644
--- a/drivers/spi/ath79_spi.c
+++ b/drivers/spi/spi-ath79.c
@@ -232,7 +232,7 @@ static __devinit int ath79_spi_probe(struct platform_device *pdev)
 		goto err_put_master;
 	}
 
-	sp->base = ioremap(r->start, r->end - r->start + 1);
+	sp->base = ioremap(r->start, resource_size(r));
 	if (!sp->base) {
 		ret = -ENXIO;
 		goto err_put_master;
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/spi-atmel.c
index 08711e9202ab..82dee9a6c0de 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/spi-atmel.c
@@ -25,7 +25,160 @@
 #include <mach/gpio.h>
 #include <mach/cpu.h>
 
-#include "atmel_spi.h"
+/* SPI register offsets */
+#define SPI_CR					0x0000
+#define SPI_MR					0x0004
+#define SPI_RDR					0x0008
+#define SPI_TDR					0x000c
+#define SPI_SR					0x0010
+#define SPI_IER					0x0014
+#define SPI_IDR					0x0018
+#define SPI_IMR					0x001c
+#define SPI_CSR0				0x0030
+#define SPI_CSR1				0x0034
+#define SPI_CSR2				0x0038
+#define SPI_CSR3				0x003c
+#define SPI_RPR					0x0100
+#define SPI_RCR					0x0104
+#define SPI_TPR					0x0108
+#define SPI_TCR					0x010c
+#define SPI_RNPR				0x0110
+#define SPI_RNCR				0x0114
+#define SPI_TNPR				0x0118
+#define SPI_TNCR				0x011c
+#define SPI_PTCR				0x0120
+#define SPI_PTSR				0x0124
+
+/* Bitfields in CR */
+#define SPI_SPIEN_OFFSET			0
+#define SPI_SPIEN_SIZE				1
+#define SPI_SPIDIS_OFFSET			1
+#define SPI_SPIDIS_SIZE				1
+#define SPI_SWRST_OFFSET			7
+#define SPI_SWRST_SIZE				1
+#define SPI_LASTXFER_OFFSET			24
+#define SPI_LASTXFER_SIZE			1
+
+/* Bitfields in MR */
+#define SPI_MSTR_OFFSET				0
+#define SPI_MSTR_SIZE				1
+#define SPI_PS_OFFSET				1
+#define SPI_PS_SIZE				1
+#define SPI_PCSDEC_OFFSET			2
+#define SPI_PCSDEC_SIZE				1
+#define SPI_FDIV_OFFSET				3
+#define SPI_FDIV_SIZE				1
+#define SPI_MODFDIS_OFFSET			4
+#define SPI_MODFDIS_SIZE			1
+#define SPI_LLB_OFFSET				7
+#define SPI_LLB_SIZE				1
+#define SPI_PCS_OFFSET				16
+#define SPI_PCS_SIZE				4
+#define SPI_DLYBCS_OFFSET			24
+#define SPI_DLYBCS_SIZE				8
+
+/* Bitfields in RDR */
+#define SPI_RD_OFFSET				0
+#define SPI_RD_SIZE				16
+
+/* Bitfields in TDR */
+#define SPI_TD_OFFSET				0
+#define SPI_TD_SIZE				16
+
+/* Bitfields in SR */
+#define SPI_RDRF_OFFSET				0
+#define SPI_RDRF_SIZE				1
+#define SPI_TDRE_OFFSET				1
+#define SPI_TDRE_SIZE				1
+#define SPI_MODF_OFFSET				2
+#define SPI_MODF_SIZE				1
+#define SPI_OVRES_OFFSET			3
+#define SPI_OVRES_SIZE				1
+#define SPI_ENDRX_OFFSET			4
+#define SPI_ENDRX_SIZE				1
+#define SPI_ENDTX_OFFSET			5
+#define SPI_ENDTX_SIZE				1
+#define SPI_RXBUFF_OFFSET			6
+#define SPI_RXBUFF_SIZE				1
+#define SPI_TXBUFE_OFFSET			7
+#define SPI_TXBUFE_SIZE				1
+#define SPI_NSSR_OFFSET				8
+#define SPI_NSSR_SIZE				1
+#define SPI_TXEMPTY_OFFSET			9
+#define SPI_TXEMPTY_SIZE			1
+#define SPI_SPIENS_OFFSET			16
+#define SPI_SPIENS_SIZE				1
+
+/* Bitfields in CSR0 */
+#define SPI_CPOL_OFFSET				0
+#define SPI_CPOL_SIZE				1
+#define SPI_NCPHA_OFFSET			1
+#define SPI_NCPHA_SIZE				1
+#define SPI_CSAAT_OFFSET			3
+#define SPI_CSAAT_SIZE				1
+#define SPI_BITS_OFFSET				4
+#define SPI_BITS_SIZE				4
+#define SPI_SCBR_OFFSET				8
+#define SPI_SCBR_SIZE				8
+#define SPI_DLYBS_OFFSET			16
+#define SPI_DLYBS_SIZE				8
+#define SPI_DLYBCT_OFFSET			24
+#define SPI_DLYBCT_SIZE				8
+
+/* Bitfields in RCR */
+#define SPI_RXCTR_OFFSET			0
+#define SPI_RXCTR_SIZE				16
+
+/* Bitfields in TCR */
+#define SPI_TXCTR_OFFSET			0
+#define SPI_TXCTR_SIZE				16
+
+/* Bitfields in RNCR */
+#define SPI_RXNCR_OFFSET			0
+#define SPI_RXNCR_SIZE				16
+
+/* Bitfields in TNCR */
+#define SPI_TXNCR_OFFSET			0
+#define SPI_TXNCR_SIZE				16
+
+/* Bitfields in PTCR */
+#define SPI_RXTEN_OFFSET			0
+#define SPI_RXTEN_SIZE				1
+#define SPI_RXTDIS_OFFSET			1
+#define SPI_RXTDIS_SIZE				1
+#define SPI_TXTEN_OFFSET			8
+#define SPI_TXTEN_SIZE				1
+#define SPI_TXTDIS_OFFSET			9
+#define SPI_TXTDIS_SIZE				1
+
+/* Constants for BITS */
+#define SPI_BITS_8_BPT				0
+#define SPI_BITS_9_BPT				1
+#define SPI_BITS_10_BPT				2
+#define SPI_BITS_11_BPT				3
+#define SPI_BITS_12_BPT				4
+#define SPI_BITS_13_BPT				5
+#define SPI_BITS_14_BPT				6
+#define SPI_BITS_15_BPT				7
+#define SPI_BITS_16_BPT				8
+
+/* Bit manipulation macros */
+#define SPI_BIT(name) \
+	(1 << SPI_##name##_OFFSET)
+#define SPI_BF(name,value) \
+	(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
+#define SPI_BFEXT(name,value) \
+	(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
+#define SPI_BFINS(name,value,old) \
+	( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
+	  | SPI_BF(name,value))
+
+/* Register access macros */
+#define spi_readl(port,reg) \
+	__raw_readl((port)->regs + SPI_##reg)
+#define spi_writel(port,reg,value) \
+	__raw_writel((value), (port)->regs + SPI_##reg)
+
 
 /*
  * The core SPI transfer engine just talks to a register bank to set up
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/spi-au1550.c
index b50563d320e1..bddee5f516b2 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/spi-au1550.c
@@ -1,5 +1,5 @@
 /*
- * au1550_spi.c - au1550 psc spi controller driver
+ * au1550 psc spi controller driver
  * may work also with au1200, au1210, au1250
  * will not work on au1000, au1100 and au1500 (no full spi controller there)
  *
diff --git a/drivers/spi/spi_bfin_sport.c b/drivers/spi/spi-bfin-sport.c
index e557ff617b11..e557ff617b11 100644
--- a/drivers/spi/spi_bfin_sport.c
+++ b/drivers/spi/spi-bfin-sport.c
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index cc880c95e7de..b8d25f2b7038 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -58,7 +58,7 @@ struct bfin_spi_master_data {
 	struct spi_master *master;
 
 	/* Regs base of SPI controller */
-	void __iomem *regs_base;
+	struct bfin_spi_regs __iomem *regs;
 
 	/* Pin request list */
 	u16 *pin_req;
@@ -122,34 +122,14 @@ struct bfin_spi_slave_data {
 	const struct bfin_spi_transfer_ops *ops;
 };
 
-#define DEFINE_SPI_REG(reg, off) \
-static inline u16 read_##reg(struct bfin_spi_master_data *drv_data) \
-	{ return bfin_read16(drv_data->regs_base + off); } \
-static inline void write_##reg(struct bfin_spi_master_data *drv_data, u16 v) \
-	{ bfin_write16(drv_data->regs_base + off, v); }
-
-DEFINE_SPI_REG(CTRL, 0x00)
-DEFINE_SPI_REG(FLAG, 0x04)
-DEFINE_SPI_REG(STAT, 0x08)
-DEFINE_SPI_REG(TDBR, 0x0C)
-DEFINE_SPI_REG(RDBR, 0x10)
-DEFINE_SPI_REG(BAUD, 0x14)
-DEFINE_SPI_REG(SHAW, 0x18)
-
 static void bfin_spi_enable(struct bfin_spi_master_data *drv_data)
 {
-	u16 cr;
-
-	cr = read_CTRL(drv_data);
-	write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
+	bfin_write_or(&drv_data->regs->ctl, BIT_CTL_ENABLE);
 }
 
 static void bfin_spi_disable(struct bfin_spi_master_data *drv_data)
 {
-	u16 cr;
-
-	cr = read_CTRL(drv_data);
-	write_CTRL(drv_data, (cr & (~BIT_CTL_ENABLE)));
+	bfin_write_and(&drv_data->regs->ctl, ~BIT_CTL_ENABLE);
 }
 
 /* Caculate the SPI_BAUD register value based on input HZ */
@@ -172,10 +152,10 @@ static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
 	unsigned long limit = loops_per_jiffy << 1;
 
 	/* wait for stop and clear stat */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF) && --limit)
+	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF) && --limit)
 		cpu_relax();
 
-	write_STAT(drv_data, BIT_STAT_CLR);
+	bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
 
 	return limit;
 }
@@ -183,29 +163,19 @@ static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
 /* Chip select operation functions for cs_change flag */
 static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip)
 {
-	if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
-		u16 flag = read_FLAG(drv_data);
-
-		flag &= ~chip->flag;
-
-		write_FLAG(drv_data, flag);
-	} else {
+	if (likely(chip->chip_select_num < MAX_CTRL_CS))
+		bfin_write_and(&drv_data->regs->flg, ~chip->flag);
+	else
 		gpio_set_value(chip->cs_gpio, 0);
-	}
 }
 
 static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
                                  struct bfin_spi_slave_data *chip)
 {
-	if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
-		u16 flag = read_FLAG(drv_data);
-
-		flag |= chip->flag;
-
-		write_FLAG(drv_data, flag);
-	} else {
+	if (likely(chip->chip_select_num < MAX_CTRL_CS))
+		bfin_write_or(&drv_data->regs->flg, chip->flag);
+	else
 		gpio_set_value(chip->cs_gpio, 1);
-	}
 
 	/* Move delay here for consistency */
 	if (chip->cs_chg_udelay)
@@ -216,25 +186,15 @@ static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
 static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data,
                                       struct bfin_spi_slave_data *chip)
 {
-	if (chip->chip_select_num < MAX_CTRL_CS) {
-		u16 flag = read_FLAG(drv_data);
-
-		flag |= (chip->flag >> 8);
-
-		write_FLAG(drv_data, flag);
-	}
+	if (chip->chip_select_num < MAX_CTRL_CS)
+		bfin_write_or(&drv_data->regs->flg, chip->flag >> 8);
 }
 
 static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data,
                                        struct bfin_spi_slave_data *chip)
 {
-	if (chip->chip_select_num < MAX_CTRL_CS) {
-		u16 flag = read_FLAG(drv_data);
-
-		flag &= ~(chip->flag >> 8);
-
-		write_FLAG(drv_data, flag);
-	}
+	if (chip->chip_select_num < MAX_CTRL_CS)
+		bfin_write_and(&drv_data->regs->flg, ~(chip->flag >> 8));
 }
 
 /* stop controller and re-config current chip*/
@@ -243,15 +203,15 @@ static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
 	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
 
 	/* Clear status and disable clock */
-	write_STAT(drv_data, BIT_STAT_CLR);
+	bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
 	bfin_spi_disable(drv_data);
 	dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
 
 	SSYNC();
 
 	/* Load the registers */
-	write_CTRL(drv_data, chip->ctl_reg);
-	write_BAUD(drv_data, chip->baud);
+	bfin_write(&drv_data->regs->ctl, chip->ctl_reg);
+	bfin_write(&drv_data->regs->baud, chip->baud);
 
 	bfin_spi_enable(drv_data);
 	bfin_spi_cs_active(drv_data, chip);
@@ -260,7 +220,7 @@ static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
 /* used to kick off transfer in rx mode and read unwanted RX data */
 static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data)
 {
-	(void) read_RDBR(drv_data);
+	(void) bfin_read(&drv_data->regs->rdbr);
 }
 
 static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
@@ -269,10 +229,10 @@ static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
 	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->tx < drv_data->tx_end) {
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
+		bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));
 		/* wait until transfer finished.
 		   checking SPIF or TXS may not guarantee transfer completion */
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
 			cpu_relax();
 		/* discard RX data and clear RXS */
 		bfin_spi_dummy_read(drv_data);
@@ -287,10 +247,10 @@ static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data)
 	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, tx_val);
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+		bfin_write(&drv_data->regs->tdbr, tx_val);
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
 			cpu_relax();
-		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
+		*(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);
 	}
 }
 
@@ -300,10 +260,10 @@ static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data)
 	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+		bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
 			cpu_relax();
-		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
+		*(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);
 	}
 }
 
@@ -319,11 +279,11 @@ static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data)
 	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->tx < drv_data->tx_end) {
-		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+		bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));
 		drv_data->tx += 2;
 		/* wait until transfer finished.
 		   checking SPIF or TXS may not guarantee transfer completion */
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
 			cpu_relax();
 		/* discard RX data and clear RXS */
 		bfin_spi_dummy_read(drv_data);
@@ -338,10 +298,10 @@ static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data)
 	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, tx_val);
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+		bfin_write(&drv_data->regs->tdbr, tx_val);
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
 			cpu_relax();
-		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+		*(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
 		drv_data->rx += 2;
 	}
 }
@@ -352,11 +312,11 @@ static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data)
 	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+		bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));
 		drv_data->tx += 2;
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
 			cpu_relax();
-		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+		*(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
 		drv_data->rx += 2;
 	}
 }
@@ -428,7 +388,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
 	int loop = 0;
 
 	/* wait until transfer finished. */
-	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
 		cpu_relax();
 
 	if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) ||
@@ -439,11 +399,11 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
 			if (n_bytes % 2) {
 				u16 *buf = (u16 *)drv_data->rx;
 				for (loop = 0; loop < n_bytes / 2; loop++)
-					*buf++ = read_RDBR(drv_data);
+					*buf++ = bfin_read(&drv_data->regs->rdbr);
 			} else {
 				u8 *buf = (u8 *)drv_data->rx;
 				for (loop = 0; loop < n_bytes; loop++)
-					*buf++ = read_RDBR(drv_data);
+					*buf++ = bfin_read(&drv_data->regs->rdbr);
 			}
 			drv_data->rx += n_bytes;
 		}
@@ -468,15 +428,15 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
 			u16 *buf = (u16 *)drv_data->rx;
 			u16 *buf2 = (u16 *)drv_data->tx;
 			for (loop = 0; loop < n_bytes / 2; loop++) {
-				*buf++ = read_RDBR(drv_data);
-				write_TDBR(drv_data, *buf2++);
+				*buf++ = bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, *buf2++);
 			}
 		} else {
 			u8 *buf = (u8 *)drv_data->rx;
 			u8 *buf2 = (u8 *)drv_data->tx;
 			for (loop = 0; loop < n_bytes; loop++) {
-				*buf++ = read_RDBR(drv_data);
-				write_TDBR(drv_data, *buf2++);
+				*buf++ = bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, *buf2++);
 			}
 		}
 	} else if (drv_data->rx) {
@@ -485,14 +445,14 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
 		if (n_bytes % 2) {
 			u16 *buf = (u16 *)drv_data->rx;
 			for (loop = 0; loop < n_bytes / 2; loop++) {
-				*buf++ = read_RDBR(drv_data);
-				write_TDBR(drv_data, chip->idle_tx_val);
+				*buf++ = bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
 			}
 		} else {
 			u8 *buf = (u8 *)drv_data->rx;
 			for (loop = 0; loop < n_bytes; loop++) {
-				*buf++ = read_RDBR(drv_data);
-				write_TDBR(drv_data, chip->idle_tx_val);
+				*buf++ = bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
 			}
 		}
 	} else if (drv_data->tx) {
@@ -501,14 +461,14 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
 		if (n_bytes % 2) {
 			u16 *buf = (u16 *)drv_data->tx;
 			for (loop = 0; loop < n_bytes / 2; loop++) {
-				read_RDBR(drv_data);
-				write_TDBR(drv_data, *buf++);
+				bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, *buf++);
 			}
 		} else {
 			u8 *buf = (u8 *)drv_data->tx;
 			for (loop = 0; loop < n_bytes; loop++) {
-				read_RDBR(drv_data);
-				write_TDBR(drv_data, *buf++);
+				bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, *buf++);
 			}
 		}
 	}
@@ -528,19 +488,19 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
 	struct spi_message *msg = drv_data->cur_msg;
 	unsigned long timeout;
 	unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
-	u16 spistat = read_STAT(drv_data);
+	u16 spistat = bfin_read(&drv_data->regs->stat);
 
 	dev_dbg(&drv_data->pdev->dev,
 		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
 		dmastat, spistat);
 
 	if (drv_data->rx != NULL) {
-		u16 cr = read_CTRL(drv_data);
+		u16 cr = bfin_read(&drv_data->regs->ctl);
 		/* discard old RX data and clear RXS */
 		bfin_spi_dummy_read(drv_data);
-		write_CTRL(drv_data, cr & ~BIT_CTL_ENABLE); /* Disable SPI */
-		write_CTRL(drv_data, cr & ~BIT_CTL_TIMOD); /* Restore State */
-		write_STAT(drv_data, BIT_STAT_CLR); /* Clear Status */
+		bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_ENABLE); /* Disable SPI */
+		bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_TIMOD); /* Restore State */
+		bfin_write(&drv_data->regs->stat, BIT_STAT_CLR); /* Clear Status */
 	}
 
 	clear_dma_irqstat(drv_data->dma_channel);
@@ -552,17 +512,17 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
 	 * register until it goes low for 2 successive reads
 	 */
 	if (drv_data->tx != NULL) {
-		while ((read_STAT(drv_data) & BIT_STAT_TXS) ||
-		       (read_STAT(drv_data) & BIT_STAT_TXS))
+		while ((bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS) ||
+		       (bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS))
 			cpu_relax();
 	}
 
 	dev_dbg(&drv_data->pdev->dev,
 		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
-		dmastat, read_STAT(drv_data));
+		dmastat, bfin_read(&drv_data->regs->stat));
 
 	timeout = jiffies + HZ;
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
 		if (!time_before(jiffies, timeout)) {
 			dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");
 			break;
@@ -699,9 +659,9 @@ static void bfin_spi_pump_transfers(unsigned long data)
 		bfin_spi_giveback(drv_data);
 		return;
 	}
-	cr = read_CTRL(drv_data) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
+	cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
 	cr |= cr_width;
-	write_CTRL(drv_data, cr);
+	bfin_write(&drv_data->regs->ctl, cr);
 
 	dev_dbg(&drv_data->pdev->dev,
 		"transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n",
@@ -712,11 +672,11 @@ static void bfin_spi_pump_transfers(unsigned long data)
 
 	/* Speed setup (surely valid because already checked) */
 	if (transfer->speed_hz)
-		write_BAUD(drv_data, hz_to_spi_baud(transfer->speed_hz));
+		bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));
 	else
-		write_BAUD(drv_data, chip->baud);
+		bfin_write(&drv_data->regs->baud, chip->baud);
 
-	write_STAT(drv_data, BIT_STAT_CLR);
+	bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
 	bfin_spi_cs_active(drv_data, chip);
 
 	dev_dbg(&drv_data->pdev->dev,
@@ -749,7 +709,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
 		}
 
 		/* poll for SPI completion before start */
-		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
 			cpu_relax();
 
 		/* dirty hack for autobuffer DMA mode */
@@ -766,7 +726,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
 			enable_dma(drv_data->dma_channel);
 
 			/* start SPI transfer */
-			write_CTRL(drv_data, cr | BIT_CTL_TIMOD_DMA_TX);
+			bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TIMOD_DMA_TX);
 
 			/* just return here, there can only be one transfer
 			 * in this mode
@@ -821,7 +781,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
 		set_dma_config(drv_data->dma_channel, dma_config);
 		local_irq_save(flags);
 		SSYNC();
-		write_CTRL(drv_data, cr);
+		bfin_write(&drv_data->regs->ctl, cr);
 		enable_dma(drv_data->dma_channel);
 		dma_enable_irq(drv_data->dma_channel);
 		local_irq_restore(flags);
@@ -835,7 +795,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
 	 * problems with setting up the output value in TDBR prior to the
 	 * start of the transfer.
 	 */
-	write_CTRL(drv_data, cr | BIT_CTL_TXMOD);
+	bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TXMOD);
 
 	if (chip->pio_interrupt) {
 		/* SPI irq should have been disabled by now */
@@ -845,19 +805,19 @@ static void bfin_spi_pump_transfers(unsigned long data)
 
 		/* start transfer */
 		if (drv_data->tx == NULL)
-			write_TDBR(drv_data, chip->idle_tx_val);
+			bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
 		else {
 			int loop;
 			if (bits_per_word % 16 == 0) {
 				u16 *buf = (u16 *)drv_data->tx;
 				for (loop = 0; loop < bits_per_word / 16;
 						loop++) {
-					write_TDBR(drv_data, *buf++);
+					bfin_write(&drv_data->regs->tdbr, *buf++);
 				}
 			} else if (bits_per_word % 8 == 0) {
 				u8 *buf = (u8 *)drv_data->tx;
 				for (loop = 0; loop < bits_per_word / 8; loop++)
-					write_TDBR(drv_data, *buf++);
+					bfin_write(&drv_data->regs->tdbr, *buf++);
 			}
 
 			drv_data->tx += drv_data->n_bytes;
@@ -1005,7 +965,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
 
 #define MAX_SPI_SSEL	7
 
-static u16 ssel[][MAX_SPI_SSEL] = {
+static const u16 ssel[][MAX_SPI_SSEL] = {
 	{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
 	P_SPI0_SSEL4, P_SPI0_SSEL5,
 	P_SPI0_SSEL6, P_SPI0_SSEL7},
@@ -1226,7 +1186,7 @@ static void bfin_spi_cleanup(struct spi_device *spi)
 	spi_set_ctldata(spi, NULL);
 }
 
-static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
+static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
 {
 	INIT_LIST_HEAD(&drv_data->queue);
 	spin_lock_init(&drv_data->lock);
@@ -1248,7 +1208,7 @@ static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
 	return 0;
 }
 
-static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
+static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
 {
 	unsigned long flags;
 
@@ -1270,7 +1230,7 @@ static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
 	return 0;
 }
 
-static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
+static int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
 {
 	unsigned long flags;
 	unsigned limit = 500;
@@ -1299,7 +1259,7 @@ static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
 	return status;
 }
 
-static inline int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
+static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
 {
 	int status;
 
@@ -1353,8 +1313,8 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
 		goto out_error_get_res;
 	}
 
-	drv_data->regs_base = ioremap(res->start, resource_size(res));
-	if (drv_data->regs_base == NULL) {
+	drv_data->regs = ioremap(res->start, resource_size(res));
+	if (drv_data->regs == NULL) {
 		dev_err(dev, "Cannot map IO\n");
 		status = -ENXIO;
 		goto out_error_ioremap;
@@ -1397,8 +1357,8 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
 	/* Reset SPI registers. If these registers were used by the boot loader,
 	 * the sky may fall on your head if you enable the dma controller.
 	 */
-	write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
-	write_FLAG(drv_data, 0xFF00);
+	bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER);
+	bfin_write(&drv_data->regs->flg, 0xFF00);
 
 	/* Register with the SPI framework */
 	platform_set_drvdata(pdev, drv_data);
@@ -1408,15 +1368,15 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
 		goto out_error_queue_alloc;
 	}
 
-	dev_info(dev, "%s, Version %s, regs_base@%p, dma channel@%d\n",
-		DRV_DESC, DRV_VERSION, drv_data->regs_base,
+	dev_info(dev, "%s, Version %s, regs@%p, dma channel@%d\n",
+		DRV_DESC, DRV_VERSION, drv_data->regs,
 		drv_data->dma_channel);
 	return status;
 
 out_error_queue_alloc:
 	bfin_spi_destroy_queue(drv_data);
 out_error_free_io:
-	iounmap((void *) drv_data->regs_base);
+	iounmap(drv_data->regs);
 out_error_ioremap:
 out_error_get_res:
 	spi_master_put(master);
@@ -1473,14 +1433,14 @@ static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
 	if (status != 0)
 		return status;
 
-	drv_data->ctrl_reg = read_CTRL(drv_data);
-	drv_data->flag_reg = read_FLAG(drv_data);
+	drv_data->ctrl_reg = bfin_read(&drv_data->regs->ctl);
+	drv_data->flag_reg = bfin_read(&drv_data->regs->flg);
 
 	/*
 	 * reset SPI_CTL and SPI_FLG registers
 	 */
-	write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
-	write_FLAG(drv_data, 0xFF00);
+	bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER);
+	bfin_write(&drv_data->regs->flg, 0xFF00);
 
 	return 0;
 }
@@ -1490,8 +1450,8 @@ static int bfin_spi_resume(struct platform_device *pdev)
 	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
 	int status = 0;
 
-	write_CTRL(drv_data, drv_data->ctrl_reg);
-	write_FLAG(drv_data, drv_data->flag_reg);
+	bfin_write(&drv_data->regs->ctl, drv_data->ctrl_reg);
+	bfin_write(&drv_data->regs->flg, drv_data->flag_reg);
 
 	/* Start the queue running */
 	status = bfin_spi_start_queue(drv_data);
diff --git a/drivers/spi/spi_bitbang_txrx.h b/drivers/spi/spi-bitbang-txrx.h
index c16bf853c3eb..c16bf853c3eb 100644
--- a/drivers/spi/spi_bitbang_txrx.h
+++ b/drivers/spi/spi-bitbang-txrx.h
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi-bitbang.c
index 14a63f6010d1..02d57fbba295 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -1,5 +1,5 @@
 /*
- * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities
+ * polling/bitbanging SPI master controller driver utilities
  *
  * 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
@@ -68,7 +68,7 @@ static unsigned bitbang_txrx_8(
 	unsigned		ns,
 	struct spi_transfer	*t
 ) {
-	unsigned		bits = spi->bits_per_word;
+	unsigned		bits = t->bits_per_word ? : spi->bits_per_word;
 	unsigned		count = t->len;
 	const u8		*tx = t->tx_buf;
 	u8			*rx = t->rx_buf;
@@ -94,7 +94,7 @@ static unsigned bitbang_txrx_16(
 	unsigned		ns,
 	struct spi_transfer	*t
 ) {
-	unsigned		bits = spi->bits_per_word;
+	unsigned		bits = t->bits_per_word ? : spi->bits_per_word;
 	unsigned		count = t->len;
 	const u16		*tx = t->tx_buf;
 	u16			*rx = t->rx_buf;
@@ -120,7 +120,7 @@ static unsigned bitbang_txrx_32(
 	unsigned		ns,
 	struct spi_transfer	*t
 ) {
-	unsigned		bits = spi->bits_per_word;
+	unsigned		bits = t->bits_per_word ? : spi->bits_per_word;
 	unsigned		count = t->len;
 	const u32		*tx = t->tx_buf;
 	u32			*rx = t->rx_buf;
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi-butterfly.c
index 0d4ceba3b590..9f907ec52def 100644
--- a/drivers/spi/spi_butterfly.c
+++ b/drivers/spi/spi-butterfly.c
@@ -1,5 +1,5 @@
 /*
- * spi_butterfly.c - parport-to-butterfly adapter
+ * parport-to-butterfly adapter
  *
  * Copyright (C) 2005 David Brownell
  *
@@ -149,7 +149,7 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
 #define	spidelay(X)	do{}while(0)
 //#define	spidelay	ndelay
 
-#include "spi_bitbang_txrx.h"
+#include "spi-bitbang-txrx.h"
 
 static u32
 butterfly_txrx_word_mode0(struct spi_device *spi,
diff --git a/drivers/spi/coldfire_qspi.c b/drivers/spi/spi-coldfire-qspi.c
index ae2cd1c1fda8..ae2cd1c1fda8 100644
--- a/drivers/spi/coldfire_qspi.c
+++ b/drivers/spi/spi-coldfire-qspi.c
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/spi-davinci.c
index 1f0ed8005c91..1f0ed8005c91 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/spi-davinci.c
diff --git a/drivers/spi/dw_spi_mid.c b/drivers/spi/spi-dw-mid.c
index 489178243d88..130e55537db6 100644
--- a/drivers/spi/dw_spi_mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -1,5 +1,5 @@
 /*
- * dw_spi_mid.c - special handling for DW core on Intel MID platform
+ * Special handling for DW core on Intel MID platform
  *
  * Copyright (c) 2009, Intel Corporation.
  *
@@ -23,7 +23,7 @@
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 
-#include "dw_spi.h"
+#include "spi-dw.h"
 
 #ifdef CONFIG_SPI_DW_MID_DMA
 #include <linux/intel_mid_dma.h>
diff --git a/drivers/spi/dw_spi_mmio.c b/drivers/spi/spi-dw-mmio.c
index e0e813dad150..34eb66501dbf 100644
--- a/drivers/spi/dw_spi_mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -1,5 +1,5 @@
 /*
- * dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core
+ * Memory-mapped interface driver for DW SPI Core
  *
  * Copyright (c) 2010, Octasic semiconductor.
  *
@@ -16,7 +16,7 @@
 #include <linux/spi/spi.h>
 #include <linux/scatterlist.h>
 
-#include "dw_spi.h"
+#include "spi-dw.h"
 
 #define DRIVER_NAME "dw_spi_mmio"
 
diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/spi-dw-pci.c
index ad260aa5e526..c5f37f03ac8b 100644
--- a/drivers/spi/dw_spi_pci.c
+++ b/drivers/spi/spi-dw-pci.c
@@ -1,5 +1,5 @@
 /*
- * dw_spi_pci.c - PCI interface driver for DW SPI Core
+ * PCI interface driver for DW SPI Core
  *
  * Copyright (c) 2009, Intel Corporation.
  *
@@ -22,7 +22,7 @@
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 
-#include "dw_spi.h"
+#include "spi-dw.h"
 
 #define DRIVER_NAME "dw_spi_pci"
 
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/spi-dw.c
index 919fa9d9e16b..857cd30b44bb 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/spi-dw.c
@@ -1,5 +1,5 @@
 /*
- * dw_spi.c - Designware SPI core controller driver (refer pxa2xx_spi.c)
+ * Designware SPI core controller driver (refer pxa2xx_spi.c)
  *
  * Copyright (c) 2009, Intel Corporation.
  *
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 
-#include "dw_spi.h"
+#include "spi-dw.h"
 
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -818,9 +818,11 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
 	dws->prev_chip = NULL;
 	dws->dma_inited = 0;
 	dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
+	snprintf(dws->name, sizeof(dws->name), "dw_spi%d",
+			dws->bus_num);
 
 	ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
-			"dw_spi", dws);
+			dws->name, dws);
 	if (ret < 0) {
 		dev_err(&master->dev, "can not get IRQ\n");
 		goto err_free_master;
diff --git a/drivers/spi/dw_spi.h b/drivers/spi/spi-dw.h
index 7a5e78d2a5cb..8b7b07bf6c3f 100644
--- a/drivers/spi/dw_spi.h
+++ b/drivers/spi/spi-dw.h
@@ -96,6 +96,7 @@ struct dw_spi {
 	struct spi_device	*cur_dev;
 	struct device		*parent_dev;
 	enum dw_ssi_type	type;
+	char			name[16];
 
 	void __iomem		*regs;
 	unsigned long		paddr;
diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/spi-ep93xx.c
index d3570071e98f..1cf645479bfe 100644
--- a/drivers/spi/ep93xx_spi.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -1,7 +1,7 @@
 /*
  * Driver for Cirrus Logic EP93xx SPI controller.
  *
- * Copyright (c) 2010 Mika Westerberg
+ * Copyright (C) 2010-2011 Mika Westerberg
  *
  * Explicit FIFO handling code was inspired by amba-pl022 driver.
  *
@@ -21,13 +21,16 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/dmaengine.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
 #include <linux/sched.h>
+#include <linux/scatterlist.h>
 #include <linux/spi/spi.h>
 
+#include <mach/dma.h>
 #include <mach/ep93xx_spi.h>
 
 #define SSPCR0			0x0000
@@ -71,6 +74,7 @@
  * @pdev: pointer to platform device
  * @clk: clock for the controller
  * @regs_base: pointer to ioremap()'d registers
+ * @sspdr_phys: physical address of the SSPDR register
  * @irq: IRQ number used by the driver
  * @min_rate: minimum clock rate (in Hz) supported by the controller
  * @max_rate: maximum clock rate (in Hz) supported by the controller
@@ -84,6 +88,14 @@
  * @rx: current byte in transfer to receive
  * @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one
  *              frame decreases this level and sending one frame increases it.
+ * @dma_rx: RX DMA channel
+ * @dma_tx: TX DMA channel
+ * @dma_rx_data: RX parameters passed to the DMA engine
+ * @dma_tx_data: TX parameters passed to the DMA engine
+ * @rx_sgt: sg table for RX transfers
+ * @tx_sgt: sg table for TX transfers
+ * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by
+ *            the client
  *
  * This structure holds EP93xx SPI controller specific information. When
  * @running is %true, driver accepts transfer requests from protocol drivers.
@@ -100,6 +112,7 @@ struct ep93xx_spi {
 	const struct platform_device	*pdev;
 	struct clk			*clk;
 	void __iomem			*regs_base;
+	unsigned long			sspdr_phys;
 	int				irq;
 	unsigned long			min_rate;
 	unsigned long			max_rate;
@@ -112,6 +125,13 @@ struct ep93xx_spi {
 	size_t				tx;
 	size_t				rx;
 	size_t				fifo_level;
+	struct dma_chan			*dma_rx;
+	struct dma_chan			*dma_tx;
+	struct ep93xx_dma_data		dma_rx_data;
+	struct ep93xx_dma_data		dma_tx_data;
+	struct sg_table			rx_sgt;
+	struct sg_table			tx_sgt;
+	void				*zeropage;
 };
 
 /**
@@ -496,14 +516,195 @@ static int ep93xx_spi_read_write(struct ep93xx_spi *espi)
 		espi->fifo_level++;
 	}
 
-	if (espi->rx == t->len) {
-		msg->actual_length += t->len;
+	if (espi->rx == t->len)
 		return 0;
-	}
 
 	return -EINPROGRESS;
 }
 
+static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi)
+{
+	/*
+	 * Now everything is set up for the current transfer. We prime the TX
+	 * FIFO, enable interrupts, and wait for the transfer to complete.
+	 */
+	if (ep93xx_spi_read_write(espi)) {
+		ep93xx_spi_enable_interrupts(espi);
+		wait_for_completion(&espi->wait);
+	}
+}
+
+/**
+ * ep93xx_spi_dma_prepare() - prepares a DMA transfer
+ * @espi: ep93xx SPI controller struct
+ * @dir: DMA transfer direction
+ *
+ * Function configures the DMA, maps the buffer and prepares the DMA
+ * descriptor. Returns a valid DMA descriptor in case of success and ERR_PTR
+ * in case of failure.
+ */
+static struct dma_async_tx_descriptor *
+ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
+{
+	struct spi_transfer *t = espi->current_msg->state;
+	struct dma_async_tx_descriptor *txd;
+	enum dma_slave_buswidth buswidth;
+	struct dma_slave_config conf;
+	struct scatterlist *sg;
+	struct sg_table *sgt;
+	struct dma_chan *chan;
+	const void *buf, *pbuf;
+	size_t len = t->len;
+	int i, ret, nents;
+
+	if (bits_per_word(espi) > 8)
+		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	else
+		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+
+	memset(&conf, 0, sizeof(conf));
+	conf.direction = dir;
+
+	if (dir == DMA_FROM_DEVICE) {
+		chan = espi->dma_rx;
+		buf = t->rx_buf;
+		sgt = &espi->rx_sgt;
+
+		conf.src_addr = espi->sspdr_phys;
+		conf.src_addr_width = buswidth;
+	} else {
+		chan = espi->dma_tx;
+		buf = t->tx_buf;
+		sgt = &espi->tx_sgt;
+
+		conf.dst_addr = espi->sspdr_phys;
+		conf.dst_addr_width = buswidth;
+	}
+
+	ret = dmaengine_slave_config(chan, &conf);
+	if (ret)
+		return ERR_PTR(ret);
+
+	/*
+	 * We need to split the transfer into PAGE_SIZE'd chunks. This is
+	 * because we are using @espi->zeropage to provide a zero RX buffer
+	 * for the TX transfers and we have only allocated one page for that.
+	 *
+	 * For performance reasons we allocate a new sg_table only when
+	 * needed. Otherwise we will re-use the current one. Eventually the
+	 * last sg_table is released in ep93xx_spi_release_dma().
+	 */
+
+	nents = DIV_ROUND_UP(len, PAGE_SIZE);
+	if (nents != sgt->nents) {
+		sg_free_table(sgt);
+
+		ret = sg_alloc_table(sgt, nents, GFP_KERNEL);
+		if (ret)
+			return ERR_PTR(ret);
+	}
+
+	pbuf = buf;
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes = min_t(size_t, len, PAGE_SIZE);
+
+		if (buf) {
+			sg_set_page(sg, virt_to_page(pbuf), bytes,
+				    offset_in_page(pbuf));
+		} else {
+			sg_set_page(sg, virt_to_page(espi->zeropage),
+				    bytes, 0);
+		}
+
+		pbuf += bytes;
+		len -= bytes;
+	}
+
+	if (WARN_ON(len)) {
+		dev_warn(&espi->pdev->dev, "len = %d expected 0!", len);
+		return ERR_PTR(-EINVAL);
+	}
+
+	nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
+	if (!nents)
+		return ERR_PTR(-ENOMEM);
+
+	txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents,
+						 dir, DMA_CTRL_ACK);
+	if (!txd) {
+		dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
+		return ERR_PTR(-ENOMEM);
+	}
+	return txd;
+}
+
+/**
+ * ep93xx_spi_dma_finish() - finishes with a DMA transfer
+ * @espi: ep93xx SPI controller struct
+ * @dir: DMA transfer direction
+ *
+ * Function finishes with the DMA transfer. After this, the DMA buffer is
+ * unmapped.
+ */
+static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
+				  enum dma_data_direction dir)
+{
+	struct dma_chan *chan;
+	struct sg_table *sgt;
+
+	if (dir == DMA_FROM_DEVICE) {
+		chan = espi->dma_rx;
+		sgt = &espi->rx_sgt;
+	} else {
+		chan = espi->dma_tx;
+		sgt = &espi->tx_sgt;
+	}
+
+	dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
+}
+
+static void ep93xx_spi_dma_callback(void *callback_param)
+{
+	complete(callback_param);
+}
+
+static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
+{
+	struct spi_message *msg = espi->current_msg;
+	struct dma_async_tx_descriptor *rxd, *txd;
+
+	rxd = ep93xx_spi_dma_prepare(espi, DMA_FROM_DEVICE);
+	if (IS_ERR(rxd)) {
+		dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
+		msg->status = PTR_ERR(rxd);
+		return;
+	}
+
+	txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE);
+	if (IS_ERR(txd)) {
+		ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+		dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd));
+		msg->status = PTR_ERR(txd);
+		return;
+	}
+
+	/* We are ready when RX is done */
+	rxd->callback = ep93xx_spi_dma_callback;
+	rxd->callback_param = &espi->wait;
+
+	/* Now submit both descriptors and wait while they finish */
+	dmaengine_submit(rxd);
+	dmaengine_submit(txd);
+
+	dma_async_issue_pending(espi->dma_rx);
+	dma_async_issue_pending(espi->dma_tx);
+
+	wait_for_completion(&espi->wait);
+
+	ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE);
+	ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+}
+
 /**
  * ep93xx_spi_process_transfer() - processes one SPI transfer
  * @espi: ep93xx SPI controller struct
@@ -556,13 +757,14 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
 	espi->tx = 0;
 
 	/*
-	 * Now everything is set up for the current transfer. We prime the TX
-	 * FIFO, enable interrupts, and wait for the transfer to complete.
+	 * There is no point of setting up DMA for the transfers which will
+	 * fit into the FIFO and can be transferred with a single interrupt.
+	 * So in these cases we will be using PIO and don't bother for DMA.
 	 */
-	if (ep93xx_spi_read_write(espi)) {
-		ep93xx_spi_enable_interrupts(espi);
-		wait_for_completion(&espi->wait);
-	}
+	if (espi->dma_rx && t->len > SPI_FIFO_SIZE)
+		ep93xx_spi_dma_transfer(espi);
+	else
+		ep93xx_spi_pio_transfer(espi);
 
 	/*
 	 * In case of error during transmit, we bail out from processing
@@ -571,6 +773,8 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
 	if (msg->status)
 		return;
 
+	msg->actual_length += t->len;
+
 	/*
 	 * After this transfer is finished, perform any possible
 	 * post-transfer actions requested by the protocol driver.
@@ -752,6 +956,75 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static bool ep93xx_spi_dma_filter(struct dma_chan *chan, void *filter_param)
+{
+	if (ep93xx_dma_chan_is_m2p(chan))
+		return false;
+
+	chan->private = filter_param;
+	return true;
+}
+
+static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
+{
+	dma_cap_mask_t mask;
+	int ret;
+
+	espi->zeropage = (void *)get_zeroed_page(GFP_KERNEL);
+	if (!espi->zeropage)
+		return -ENOMEM;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	espi->dma_rx_data.port = EP93XX_DMA_SSP;
+	espi->dma_rx_data.direction = DMA_FROM_DEVICE;
+	espi->dma_rx_data.name = "ep93xx-spi-rx";
+
+	espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter,
+					   &espi->dma_rx_data);
+	if (!espi->dma_rx) {
+		ret = -ENODEV;
+		goto fail_free_page;
+	}
+
+	espi->dma_tx_data.port = EP93XX_DMA_SSP;
+	espi->dma_tx_data.direction = DMA_TO_DEVICE;
+	espi->dma_tx_data.name = "ep93xx-spi-tx";
+
+	espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter,
+					   &espi->dma_tx_data);
+	if (!espi->dma_tx) {
+		ret = -ENODEV;
+		goto fail_release_rx;
+	}
+
+	return 0;
+
+fail_release_rx:
+	dma_release_channel(espi->dma_rx);
+	espi->dma_rx = NULL;
+fail_free_page:
+	free_page((unsigned long)espi->zeropage);
+
+	return ret;
+}
+
+static void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
+{
+	if (espi->dma_rx) {
+		dma_release_channel(espi->dma_rx);
+		sg_free_table(&espi->rx_sgt);
+	}
+	if (espi->dma_tx) {
+		dma_release_channel(espi->dma_tx);
+		sg_free_table(&espi->tx_sgt);
+	}
+
+	if (espi->zeropage)
+		free_page((unsigned long)espi->zeropage);
+}
+
 static int __init ep93xx_spi_probe(struct platform_device *pdev)
 {
 	struct spi_master *master;
@@ -818,6 +1091,7 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)
 		goto fail_put_clock;
 	}
 
+	espi->sspdr_phys = res->start + SSPDR;
 	espi->regs_base = ioremap(res->start, resource_size(res));
 	if (!espi->regs_base) {
 		dev_err(&pdev->dev, "failed to map resources\n");
@@ -832,10 +1106,13 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)
 		goto fail_unmap_regs;
 	}
 
+	if (info->use_dma && ep93xx_spi_setup_dma(espi))
+		dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
+
 	espi->wq = create_singlethread_workqueue("ep93xx_spid");
 	if (!espi->wq) {
 		dev_err(&pdev->dev, "unable to create workqueue\n");
-		goto fail_free_irq;
+		goto fail_free_dma;
 	}
 	INIT_WORK(&espi->msg_work, ep93xx_spi_work);
 	INIT_LIST_HEAD(&espi->msg_queue);
@@ -857,7 +1134,8 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)
 
 fail_free_queue:
 	destroy_workqueue(espi->wq);
-fail_free_irq:
+fail_free_dma:
+	ep93xx_spi_release_dma(espi);
 	free_irq(espi->irq, espi);
 fail_unmap_regs:
 	iounmap(espi->regs_base);
@@ -901,6 +1179,7 @@ static int __exit ep93xx_spi_remove(struct platform_device *pdev)
 	}
 	spin_unlock_irq(&espi->lock);
 
+	ep93xx_spi_release_dma(espi);
 	free_irq(espi->irq, espi);
 	iounmap(espi->regs_base);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi-fsl-espi.c
index 496f895a0024..54e499d5f92c 100644
--- a/drivers/spi/spi_fsl_espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -22,7 +22,7 @@
 #include <linux/err.h>
 #include <sysdev/fsl_soc.h>
 
-#include "spi_fsl_lib.h"
+#include "spi-fsl-lib.h"
 
 /* eSPI Controller registers */
 struct fsl_espi_reg {
diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi-fsl-lib.c
index ff59f42ae990..2674fad7f68a 100644
--- a/drivers/spi/spi_fsl_lib.c
+++ b/drivers/spi/spi-fsl-lib.c
@@ -25,7 +25,7 @@
 #include <linux/of_spi.h>
 #include <sysdev/fsl_soc.h>
 
-#include "spi_fsl_lib.h"
+#include "spi-fsl-lib.h"
 
 #define MPC8XXX_SPI_RX_BUF(type) 					  \
 void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi-fsl-lib.h
index cbe881b9ea76..cbe881b9ea76 100644
--- a/drivers/spi/spi_fsl_lib.h
+++ b/drivers/spi/spi-fsl-lib.h
diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi-fsl-spi.c
index 7963c9b49566..d2407558773f 100644
--- a/drivers/spi/spi_fsl_spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -37,7 +37,7 @@
 #include <asm/cpm.h>
 #include <asm/qe.h>
 
-#include "spi_fsl_lib.h"
+#include "spi-fsl-lib.h"
 
 /* CPM1 and CPM2 are mutually exclusive. */
 #ifdef CONFIG_CPM1
@@ -684,7 +684,7 @@ static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
 	struct device_node *np = dev->of_node;
 	const u32 *iprop;
 	int size;
-	unsigned long spi_base_ofs;
+	void __iomem *spi_base;
 	unsigned long pram_ofs = -ENOMEM;
 
 	/* Can't use of_address_to_resource(), QE muram isn't at 0. */
@@ -702,33 +702,27 @@ static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
 		return pram_ofs;
 	}
 
-	/* CPM1 and CPM2 pram must be at a fixed addr. */
-	if (!iprop || size != sizeof(*iprop) * 4)
-		return -ENOMEM;
-
-	spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
-	if (IS_ERR_VALUE(spi_base_ofs))
-		return -ENOMEM;
+	spi_base = of_iomap(np, 1);
+	if (spi_base == NULL)
+		return -EINVAL;
 
 	if (mspi->flags & SPI_CPM2) {
 		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
-		if (!IS_ERR_VALUE(pram_ofs)) {
-			u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
-
-			out_be16(spi_base, pram_ofs);
-		}
+		out_be16(spi_base, pram_ofs);
 	} else {
-		struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
+		struct spi_pram __iomem *pram = spi_base;
 		u16 rpbase = in_be16(&pram->rpbase);
 
 		/* Microcode relocation patch applied? */
 		if (rpbase)
 			pram_ofs = rpbase;
-		else
-			return spi_base_ofs;
+		else {
+			pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+			out_be16(spi_base, pram_ofs);
+		}
 	}
 
-	cpm_muram_free(spi_base_ofs);
+	iounmap(spi_base);
 	return pram_ofs;
 }
 
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi-gpio.c
index 63e51b011d50..0e88ab745490 100644
--- a/drivers/spi/spi_gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -1,5 +1,5 @@
 /*
- * spi_gpio.c - SPI master driver using generic bitbanged GPIO
+ * SPI master driver using generic bitbanged GPIO
  *
  * Copyright (C) 2006,2008 David Brownell
  *
@@ -69,7 +69,7 @@ struct spi_gpio {
  *		#define	SPI_MOSI_GPIO	120
  *		#define	SPI_SCK_GPIO	121
  *		#define	SPI_N_CHIPSEL	4
- *		#include "spi_gpio.c"
+ *		#include "spi-gpio.c"
  */
 
 #ifndef DRIVER_NAME
@@ -127,7 +127,7 @@ static inline int getmiso(const struct spi_device *spi)
  */
 #define spidelay(nsecs)	do {} while (0)
 
-#include "spi_bitbang_txrx.h"
+#include "spi-bitbang-txrx.h"
 
 /*
  * These functions can leverage inline expansion of GPIO calls to shrink
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi-imx.c
index 69d6dba67c19..8ac6542aedcd 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi-imx.c
@@ -34,6 +34,9 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
 #include <mach/spi.h>
 
@@ -45,9 +48,6 @@
 #define MXC_CSPIINT		0x0c
 #define MXC_RESET		0x1c
 
-#define MX3_CSPISTAT		0x14
-#define MX3_CSPISTAT_RR		(1 << 3)
-
 /* generic defines to abstract from the different register layouts */
 #define MXC_INT_RR	(1 << 0) /* Receive data ready interrupt */
 #define MXC_INT_TE	(1 << 1) /* Transmit FIFO empty interrupt */
@@ -60,12 +60,12 @@ struct spi_imx_config {
 };
 
 enum spi_imx_devtype {
-	SPI_IMX_VER_IMX1,
-	SPI_IMX_VER_0_0,
-	SPI_IMX_VER_0_4,
-	SPI_IMX_VER_0_5,
-	SPI_IMX_VER_0_7,
-	SPI_IMX_VER_2_3,
+	IMX1_CSPI,
+	IMX21_CSPI,
+	IMX27_CSPI,
+	IMX31_CSPI,
+	IMX35_CSPI,	/* CSPI on all i.mx except above */
+	IMX51_ECSPI,	/* ECSPI on i.mx51 and later */
 };
 
 struct spi_imx_data;
@@ -76,7 +76,7 @@ struct spi_imx_devtype_data {
 	void (*trigger)(struct spi_imx_data *);
 	int (*rx_available)(struct spi_imx_data *);
 	void (*reset)(struct spi_imx_data *);
-	unsigned int fifosize;
+	enum spi_imx_devtype devtype;
 };
 
 struct spi_imx_data {
@@ -87,7 +87,6 @@ struct spi_imx_data {
 	int irq;
 	struct clk *clk;
 	unsigned long spi_clk;
-	int *chipselect;
 
 	unsigned int count;
 	void (*tx)(struct spi_imx_data *);
@@ -96,9 +95,25 @@ struct spi_imx_data {
 	const void *tx_buf;
 	unsigned int txfifo; /* number of words pushed in tx FIFO */
 
-	struct spi_imx_devtype_data devtype_data;
+	struct spi_imx_devtype_data *devtype_data;
+	int chipselect[0];
 };
 
+static inline int is_imx27_cspi(struct spi_imx_data *d)
+{
+	return d->devtype_data->devtype == IMX27_CSPI;
+}
+
+static inline int is_imx35_cspi(struct spi_imx_data *d)
+{
+	return d->devtype_data->devtype == IMX35_CSPI;
+}
+
+static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
+{
+	return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+}
+
 #define MXC_SPI_BUF_RX(type)						\
 static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx)		\
 {									\
@@ -140,14 +155,9 @@ static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,
 
 /* MX21, MX27 */
 static unsigned int spi_imx_clkdiv_1(unsigned int fin,
-		unsigned int fspi)
+		unsigned int fspi, unsigned int max)
 {
-	int i, max;
-
-	if (cpu_is_mx21())
-		max = 18;
-	else
-		max = 16;
+	int i;
 
 	for (i = 2; i < max; i++)
 		if (fspi * mxc_clkdivs[i] >= fin)
@@ -171,30 +181,30 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
 	return 7;
 }
 
-#define SPI_IMX2_3_CTRL		0x08
-#define SPI_IMX2_3_CTRL_ENABLE		(1 <<  0)
-#define SPI_IMX2_3_CTRL_XCH		(1 <<  2)
-#define SPI_IMX2_3_CTRL_MODE_MASK	(0xf << 4)
-#define SPI_IMX2_3_CTRL_POSTDIV_OFFSET	8
-#define SPI_IMX2_3_CTRL_PREDIV_OFFSET	12
-#define SPI_IMX2_3_CTRL_CS(cs)		((cs) << 18)
-#define SPI_IMX2_3_CTRL_BL_OFFSET	20
+#define MX51_ECSPI_CTRL		0x08
+#define MX51_ECSPI_CTRL_ENABLE		(1 <<  0)
+#define MX51_ECSPI_CTRL_XCH		(1 <<  2)
+#define MX51_ECSPI_CTRL_MODE_MASK	(0xf << 4)
+#define MX51_ECSPI_CTRL_POSTDIV_OFFSET	8
+#define MX51_ECSPI_CTRL_PREDIV_OFFSET	12
+#define MX51_ECSPI_CTRL_CS(cs)		((cs) << 18)
+#define MX51_ECSPI_CTRL_BL_OFFSET	20
 
-#define SPI_IMX2_3_CONFIG	0x0c
-#define SPI_IMX2_3_CONFIG_SCLKPHA(cs)	(1 << ((cs) +  0))
-#define SPI_IMX2_3_CONFIG_SCLKPOL(cs)	(1 << ((cs) +  4))
-#define SPI_IMX2_3_CONFIG_SBBCTRL(cs)	(1 << ((cs) +  8))
-#define SPI_IMX2_3_CONFIG_SSBPOL(cs)	(1 << ((cs) + 12))
+#define MX51_ECSPI_CONFIG	0x0c
+#define MX51_ECSPI_CONFIG_SCLKPHA(cs)	(1 << ((cs) +  0))
+#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 SPI_IMX2_3_INT		0x10
-#define SPI_IMX2_3_INT_TEEN		(1 <<  0)
-#define SPI_IMX2_3_INT_RREN		(1 <<  3)
+#define MX51_ECSPI_INT		0x10
+#define MX51_ECSPI_INT_TEEN		(1 <<  0)
+#define MX51_ECSPI_INT_RREN		(1 <<  3)
 
-#define SPI_IMX2_3_STAT		0x18
-#define SPI_IMX2_3_STAT_RR		(1 <<  3)
+#define MX51_ECSPI_STAT		0x18
+#define MX51_ECSPI_STAT_RR		(1 <<  3)
 
 /* MX51 eCSPI */
-static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi)
+static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
 {
 	/*
 	 * there are two 4-bit dividers, the pre-divider divides by
@@ -222,36 +232,36 @@ static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi)
 
 	pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
 			__func__, fin, fspi, post, pre);
-	return (pre << SPI_IMX2_3_CTRL_PREDIV_OFFSET) |
-		(post << SPI_IMX2_3_CTRL_POSTDIV_OFFSET);
+	return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) |
+		(post << MX51_ECSPI_CTRL_POSTDIV_OFFSET);
 }
 
-static void __maybe_unused spi_imx2_3_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
 	unsigned val = 0;
 
 	if (enable & MXC_INT_TE)
-		val |= SPI_IMX2_3_INT_TEEN;
+		val |= MX51_ECSPI_INT_TEEN;
 
 	if (enable & MXC_INT_RR)
-		val |= SPI_IMX2_3_INT_RREN;
+		val |= MX51_ECSPI_INT_RREN;
 
-	writel(val, spi_imx->base + SPI_IMX2_3_INT);
+	writel(val, spi_imx->base + MX51_ECSPI_INT);
 }
 
-static void __maybe_unused spi_imx2_3_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
 {
 	u32 reg;
 
-	reg = readl(spi_imx->base + SPI_IMX2_3_CTRL);
-	reg |= SPI_IMX2_3_CTRL_XCH;
-	writel(reg, spi_imx->base + SPI_IMX2_3_CTRL);
+	reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
+	reg |= MX51_ECSPI_CTRL_XCH;
+	writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
 }
 
-static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
 		struct spi_imx_config *config)
 {
-	u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0;
+	u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;
 
 	/*
 	 * The hardware seems to have a race condition when changing modes. The
@@ -260,42 +270,42 @@ static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx,
 	 * the same time.
 	 * So set master mode for all channels as we do not support slave mode.
 	 */
-	ctrl |= SPI_IMX2_3_CTRL_MODE_MASK;
+	ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
 
 	/* set clock speed */
-	ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz);
+	ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz);
 
 	/* set chip select to use */
-	ctrl |= SPI_IMX2_3_CTRL_CS(config->cs);
+	ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
 
-	ctrl |= (config->bpw - 1) << SPI_IMX2_3_CTRL_BL_OFFSET;
+	ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET;
 
-	cfg |= SPI_IMX2_3_CONFIG_SBBCTRL(config->cs);
+	cfg |= MX51_ECSPI_CONFIG_SBBCTRL(config->cs);
 
 	if (config->mode & SPI_CPHA)
-		cfg |= SPI_IMX2_3_CONFIG_SCLKPHA(config->cs);
+		cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
 
 	if (config->mode & SPI_CPOL)
-		cfg |= SPI_IMX2_3_CONFIG_SCLKPOL(config->cs);
+		cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
 
 	if (config->mode & SPI_CS_HIGH)
-		cfg |= SPI_IMX2_3_CONFIG_SSBPOL(config->cs);
+		cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
 
-	writel(ctrl, spi_imx->base + SPI_IMX2_3_CTRL);
-	writel(cfg, spi_imx->base + SPI_IMX2_3_CONFIG);
+	writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
+	writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
 	return 0;
 }
 
-static int __maybe_unused spi_imx2_3_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused mx51_ecspi_rx_available(struct spi_imx_data *spi_imx)
 {
-	return readl(spi_imx->base + SPI_IMX2_3_STAT) & SPI_IMX2_3_STAT_RR;
+	return readl(spi_imx->base + MX51_ECSPI_STAT) & MX51_ECSPI_STAT_RR;
 }
 
-static void __maybe_unused spi_imx2_3_reset(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx51_ecspi_reset(struct spi_imx_data *spi_imx)
 {
 	/* drain receive buffer */
-	while (spi_imx2_3_rx_available(spi_imx))
+	while (mx51_ecspi_rx_available(spi_imx))
 		readl(spi_imx->base + MXC_CSPIRXDATA);
 }
 
@@ -343,32 +353,7 @@ static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
 	writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int __maybe_unused spi_imx0_4_config(struct spi_imx_data *spi_imx,
-		struct spi_imx_config *config)
-{
-	unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
-	int cs = spi_imx->chipselect[config->cs];
-
-	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
-		MX31_CSPICTRL_DR_SHIFT;
-
-	reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
-
-	if (config->mode & SPI_CPHA)
-		reg |= MX31_CSPICTRL_PHA;
-	if (config->mode & SPI_CPOL)
-		reg |= MX31_CSPICTRL_POL;
-	if (config->mode & SPI_CS_HIGH)
-		reg |= MX31_CSPICTRL_SSPOL;
-	if (cs < 0)
-		reg |= (cs + 32) << MX31_CSPICTRL_CS_SHIFT;
-
-	writel(reg, spi_imx->base + MXC_CSPICTRL);
-
-	return 0;
-}
-
-static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx,
 		struct spi_imx_config *config)
 {
 	unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
@@ -377,8 +362,12 @@ static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,
 	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
 		MX31_CSPICTRL_DR_SHIFT;
 
-	reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
-	reg |= MX31_CSPICTRL_SSCTL;
+	if (is_imx35_cspi(spi_imx)) {
+		reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
+		reg |= MX31_CSPICTRL_SSCTL;
+	} else {
+		reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
+	}
 
 	if (config->mode & SPI_CPHA)
 		reg |= MX31_CSPICTRL_PHA;
@@ -387,7 +376,9 @@ static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,
 	if (config->mode & SPI_CS_HIGH)
 		reg |= MX31_CSPICTRL_SSPOL;
 	if (cs < 0)
-		reg |= (cs + 32) << MX35_CSPICTRL_CS_SHIFT;
+		reg |= (cs + 32) <<
+			(is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT :
+						  MX31_CSPICTRL_CS_SHIFT);
 
 	writel(reg, spi_imx->base + MXC_CSPICTRL);
 
@@ -399,77 +390,78 @@ static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx)
 	return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
 }
 
-static void __maybe_unused spi_imx0_4_reset(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx31_reset(struct spi_imx_data *spi_imx)
 {
 	/* drain receive buffer */
-	while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
+	while (readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR)
 		readl(spi_imx->base + MXC_CSPIRXDATA);
 }
 
-#define MX27_INTREG_RR		(1 << 4)
-#define MX27_INTREG_TEEN	(1 << 9)
-#define MX27_INTREG_RREN	(1 << 13)
+#define MX21_INTREG_RR		(1 << 4)
+#define MX21_INTREG_TEEN	(1 << 9)
+#define MX21_INTREG_RREN	(1 << 13)
 
-#define MX27_CSPICTRL_POL	(1 << 5)
-#define MX27_CSPICTRL_PHA	(1 << 6)
-#define MX27_CSPICTRL_SSPOL	(1 << 8)
-#define MX27_CSPICTRL_XCH	(1 << 9)
-#define MX27_CSPICTRL_ENABLE	(1 << 10)
-#define MX27_CSPICTRL_MASTER	(1 << 11)
-#define MX27_CSPICTRL_DR_SHIFT	14
-#define MX27_CSPICTRL_CS_SHIFT	19
+#define MX21_CSPICTRL_POL	(1 << 5)
+#define MX21_CSPICTRL_PHA	(1 << 6)
+#define MX21_CSPICTRL_SSPOL	(1 << 8)
+#define MX21_CSPICTRL_XCH	(1 << 9)
+#define MX21_CSPICTRL_ENABLE	(1 << 10)
+#define MX21_CSPICTRL_MASTER	(1 << 11)
+#define MX21_CSPICTRL_DR_SHIFT	14
+#define MX21_CSPICTRL_CS_SHIFT	19
 
-static void __maybe_unused mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx21_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
 	unsigned int val = 0;
 
 	if (enable & MXC_INT_TE)
-		val |= MX27_INTREG_TEEN;
+		val |= MX21_INTREG_TEEN;
 	if (enable & MXC_INT_RR)
-		val |= MX27_INTREG_RREN;
+		val |= MX21_INTREG_RREN;
 
 	writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void __maybe_unused mx27_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx)
 {
 	unsigned int reg;
 
 	reg = readl(spi_imx->base + MXC_CSPICTRL);
-	reg |= MX27_CSPICTRL_XCH;
+	reg |= MX21_CSPICTRL_XCH;
 	writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int __maybe_unused mx27_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx21_config(struct spi_imx_data *spi_imx,
 		struct spi_imx_config *config)
 {
-	unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER;
+	unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER;
 	int cs = spi_imx->chipselect[config->cs];
+	unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18;
 
-	reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) <<
-		MX27_CSPICTRL_DR_SHIFT;
+	reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max) <<
+		MX21_CSPICTRL_DR_SHIFT;
 	reg |= config->bpw - 1;
 
 	if (config->mode & SPI_CPHA)
-		reg |= MX27_CSPICTRL_PHA;
+		reg |= MX21_CSPICTRL_PHA;
 	if (config->mode & SPI_CPOL)
-		reg |= MX27_CSPICTRL_POL;
+		reg |= MX21_CSPICTRL_POL;
 	if (config->mode & SPI_CS_HIGH)
-		reg |= MX27_CSPICTRL_SSPOL;
+		reg |= MX21_CSPICTRL_SSPOL;
 	if (cs < 0)
-		reg |= (cs + 32) << MX27_CSPICTRL_CS_SHIFT;
+		reg |= (cs + 32) << MX21_CSPICTRL_CS_SHIFT;
 
 	writel(reg, spi_imx->base + MXC_CSPICTRL);
 
 	return 0;
 }
 
-static int __maybe_unused mx27_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused mx21_rx_available(struct spi_imx_data *spi_imx)
 {
-	return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR;
+	return readl(spi_imx->base + MXC_CSPIINT) & MX21_INTREG_RR;
 }
 
-static void __maybe_unused spi_imx0_0_reset(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx21_reset(struct spi_imx_data *spi_imx)
 {
 	writel(1, spi_imx->base + MXC_RESET);
 }
@@ -535,61 +527,94 @@ static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx)
 	writel(1, spi_imx->base + MXC_RESET);
 }
 
-/*
- * These version numbers are taken from the Freescale driver.  Unfortunately it
- * doesn't support i.MX1, so this entry doesn't match the scheme. :-(
- */
-static struct spi_imx_devtype_data spi_imx_devtype_data[] __devinitdata = {
-#ifdef CONFIG_SPI_IMX_VER_IMX1
-	[SPI_IMX_VER_IMX1] = {
-		.intctrl = mx1_intctrl,
-		.config = mx1_config,
-		.trigger = mx1_trigger,
-		.rx_available = mx1_rx_available,
-		.reset = mx1_reset,
-		.fifosize = 8,
-	},
-#endif
-#ifdef CONFIG_SPI_IMX_VER_0_0
-	[SPI_IMX_VER_0_0] = {
-		.intctrl = mx27_intctrl,
-		.config = mx27_config,
-		.trigger = mx27_trigger,
-		.rx_available = mx27_rx_available,
-		.reset = spi_imx0_0_reset,
-		.fifosize = 8,
-	},
-#endif
-#ifdef CONFIG_SPI_IMX_VER_0_4
-	[SPI_IMX_VER_0_4] = {
-		.intctrl = mx31_intctrl,
-		.config = spi_imx0_4_config,
-		.trigger = mx31_trigger,
-		.rx_available = mx31_rx_available,
-		.reset = spi_imx0_4_reset,
-		.fifosize = 8,
-	},
-#endif
-#ifdef CONFIG_SPI_IMX_VER_0_7
-	[SPI_IMX_VER_0_7] = {
-		.intctrl = mx31_intctrl,
-		.config = spi_imx0_7_config,
-		.trigger = mx31_trigger,
-		.rx_available = mx31_rx_available,
-		.reset = spi_imx0_4_reset,
-		.fifosize = 8,
-	},
-#endif
-#ifdef CONFIG_SPI_IMX_VER_2_3
-	[SPI_IMX_VER_2_3] = {
-		.intctrl = spi_imx2_3_intctrl,
-		.config = spi_imx2_3_config,
-		.trigger = spi_imx2_3_trigger,
-		.rx_available = spi_imx2_3_rx_available,
-		.reset = spi_imx2_3_reset,
-		.fifosize = 64,
-	},
-#endif
+static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
+	.intctrl = mx1_intctrl,
+	.config = mx1_config,
+	.trigger = mx1_trigger,
+	.rx_available = mx1_rx_available,
+	.reset = mx1_reset,
+	.devtype = IMX1_CSPI,
+};
+
+static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
+	.intctrl = mx21_intctrl,
+	.config = mx21_config,
+	.trigger = mx21_trigger,
+	.rx_available = mx21_rx_available,
+	.reset = mx21_reset,
+	.devtype = IMX21_CSPI,
+};
+
+static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
+	/* i.mx27 cspi shares the functions with i.mx21 one */
+	.intctrl = mx21_intctrl,
+	.config = mx21_config,
+	.trigger = mx21_trigger,
+	.rx_available = mx21_rx_available,
+	.reset = mx21_reset,
+	.devtype = IMX27_CSPI,
+};
+
+static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
+	.intctrl = mx31_intctrl,
+	.config = mx31_config,
+	.trigger = mx31_trigger,
+	.rx_available = mx31_rx_available,
+	.reset = mx31_reset,
+	.devtype = IMX31_CSPI,
+};
+
+static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
+	/* i.mx35 and later cspi shares the functions with i.mx31 one */
+	.intctrl = mx31_intctrl,
+	.config = mx31_config,
+	.trigger = mx31_trigger,
+	.rx_available = mx31_rx_available,
+	.reset = mx31_reset,
+	.devtype = IMX35_CSPI,
+};
+
+static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
+	.intctrl = mx51_ecspi_intctrl,
+	.config = mx51_ecspi_config,
+	.trigger = mx51_ecspi_trigger,
+	.rx_available = mx51_ecspi_rx_available,
+	.reset = mx51_ecspi_reset,
+	.devtype = IMX51_ECSPI,
+};
+
+static struct platform_device_id spi_imx_devtype[] = {
+	{
+		.name = "imx1-cspi",
+		.driver_data = (kernel_ulong_t) &imx1_cspi_devtype_data,
+	}, {
+		.name = "imx21-cspi",
+		.driver_data = (kernel_ulong_t) &imx21_cspi_devtype_data,
+	}, {
+		.name = "imx27-cspi",
+		.driver_data = (kernel_ulong_t) &imx27_cspi_devtype_data,
+	}, {
+		.name = "imx31-cspi",
+		.driver_data = (kernel_ulong_t) &imx31_cspi_devtype_data,
+	}, {
+		.name = "imx35-cspi",
+		.driver_data = (kernel_ulong_t) &imx35_cspi_devtype_data,
+	}, {
+		.name = "imx51-ecspi",
+		.driver_data = (kernel_ulong_t) &imx51_ecspi_devtype_data,
+	}, {
+		/* sentinel */
+	}
+};
+
+static const struct of_device_id spi_imx_dt_ids[] = {
+	{ .compatible = "fsl,imx1-cspi", .data = &imx1_cspi_devtype_data, },
+	{ .compatible = "fsl,imx21-cspi", .data = &imx21_cspi_devtype_data, },
+	{ .compatible = "fsl,imx27-cspi", .data = &imx27_cspi_devtype_data, },
+	{ .compatible = "fsl,imx31-cspi", .data = &imx31_cspi_devtype_data, },
+	{ .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, },
+	{ .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
+	{ /* sentinel */ }
 };
 
 static void spi_imx_chipselect(struct spi_device *spi, int is_active)
@@ -607,21 +632,21 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active)
 
 static void spi_imx_push(struct spi_imx_data *spi_imx)
 {
-	while (spi_imx->txfifo < spi_imx->devtype_data.fifosize) {
+	while (spi_imx->txfifo < spi_imx_get_fifosize(spi_imx)) {
 		if (!spi_imx->count)
 			break;
 		spi_imx->tx(spi_imx);
 		spi_imx->txfifo++;
 	}
 
-	spi_imx->devtype_data.trigger(spi_imx);
+	spi_imx->devtype_data->trigger(spi_imx);
 }
 
 static irqreturn_t spi_imx_isr(int irq, void *dev_id)
 {
 	struct spi_imx_data *spi_imx = dev_id;
 
-	while (spi_imx->devtype_data.rx_available(spi_imx)) {
+	while (spi_imx->devtype_data->rx_available(spi_imx)) {
 		spi_imx->rx(spi_imx);
 		spi_imx->txfifo--;
 	}
@@ -635,12 +660,12 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
 		/* No data left to push, but still waiting for rx data,
 		 * enable receive data available interrupt.
 		 */
-		spi_imx->devtype_data.intctrl(
+		spi_imx->devtype_data->intctrl(
 				spi_imx, MXC_INT_RR);
 		return IRQ_HANDLED;
 	}
 
-	spi_imx->devtype_data.intctrl(spi_imx, 0);
+	spi_imx->devtype_data->intctrl(spi_imx, 0);
 	complete(&spi_imx->xfer_done);
 
 	return IRQ_HANDLED;
@@ -677,7 +702,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
 	} else
 		BUG();
 
-	spi_imx->devtype_data.config(spi_imx, &config);
+	spi_imx->devtype_data->config(spi_imx, &config);
 
 	return 0;
 }
@@ -696,7 +721,7 @@ static int spi_imx_transfer(struct spi_device *spi,
 
 	spi_imx_push(spi_imx);
 
-	spi_imx->devtype_data.intctrl(spi_imx, MXC_INT_TE);
+	spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE);
 
 	wait_for_completion(&spi_imx->xfer_done);
 
@@ -723,72 +748,47 @@ static void spi_imx_cleanup(struct spi_device *spi)
 {
 }
 
-static struct platform_device_id spi_imx_devtype[] = {
-	{
-		.name = "imx1-cspi",
-		.driver_data = SPI_IMX_VER_IMX1,
-	}, {
-		.name = "imx21-cspi",
-		.driver_data = SPI_IMX_VER_0_0,
-	}, {
-		.name = "imx25-cspi",
-		.driver_data = SPI_IMX_VER_0_7,
-	}, {
-		.name = "imx27-cspi",
-		.driver_data = SPI_IMX_VER_0_0,
-	}, {
-		.name = "imx31-cspi",
-		.driver_data = SPI_IMX_VER_0_4,
-	}, {
-		.name = "imx35-cspi",
-		.driver_data = SPI_IMX_VER_0_7,
-	}, {
-		.name = "imx51-cspi",
-		.driver_data = SPI_IMX_VER_0_7,
-	}, {
-		.name = "imx51-ecspi",
-		.driver_data = SPI_IMX_VER_2_3,
-	}, {
-		.name = "imx53-cspi",
-		.driver_data = SPI_IMX_VER_0_7,
-	}, {
-		.name = "imx53-ecspi",
-		.driver_data = SPI_IMX_VER_2_3,
-	}, {
-		/* sentinel */
-	}
-};
-
 static int __devinit spi_imx_probe(struct platform_device *pdev)
 {
-	struct spi_imx_master *mxc_platform_info;
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *of_id =
+			of_match_device(spi_imx_dt_ids, &pdev->dev);
+	struct spi_imx_master *mxc_platform_info =
+			dev_get_platdata(&pdev->dev);
 	struct spi_master *master;
 	struct spi_imx_data *spi_imx;
 	struct resource *res;
-	int i, ret;
+	int i, ret, num_cs;
 
-	mxc_platform_info = dev_get_platdata(&pdev->dev);
-	if (!mxc_platform_info) {
+	if (!np && !mxc_platform_info) {
 		dev_err(&pdev->dev, "can't get the platform data\n");
 		return -EINVAL;
 	}
 
-	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
+	ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
+	if (ret < 0)
+		num_cs = mxc_platform_info->num_chipselect;
+
+	master = spi_alloc_master(&pdev->dev,
+			sizeof(struct spi_imx_data) + sizeof(int) * num_cs);
 	if (!master)
 		return -ENOMEM;
 
 	platform_set_drvdata(pdev, master);
 
 	master->bus_num = pdev->id;
-	master->num_chipselect = mxc_platform_info->num_chipselect;
+	master->num_chipselect = num_cs;
 
 	spi_imx = spi_master_get_devdata(master);
 	spi_imx->bitbang.master = spi_master_get(master);
-	spi_imx->chipselect = mxc_platform_info->chipselect;
 
 	for (i = 0; i < master->num_chipselect; i++) {
-		if (spi_imx->chipselect[i] < 0)
+		int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
+		if (cs_gpio < 0)
+			cs_gpio = mxc_platform_info->chipselect[i];
+		if (cs_gpio < 0)
 			continue;
+		spi_imx->chipselect[i] = cs_gpio;
 		ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
 		if (ret) {
 			while (i > 0) {
@@ -810,8 +810,8 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
 
 	init_completion(&spi_imx->xfer_done);
 
-	spi_imx->devtype_data =
-		spi_imx_devtype_data[pdev->id_entry->driver_data];
+	spi_imx->devtype_data = of_id ? of_id->data :
+		(struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -854,10 +854,11 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
 	clk_enable(spi_imx->clk);
 	spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
 
-	spi_imx->devtype_data.reset(spi_imx);
+	spi_imx->devtype_data->reset(spi_imx);
 
-	spi_imx->devtype_data.intctrl(spi_imx, 0);
+	spi_imx->devtype_data->intctrl(spi_imx, 0);
 
+	master->dev.of_node = pdev->dev.of_node;
 	ret = spi_bitbang_start(&spi_imx->bitbang);
 	if (ret) {
 		dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
@@ -920,6 +921,7 @@ static struct platform_driver spi_imx_driver = {
 	.driver = {
 		   .name = DRIVER_NAME,
 		   .owner = THIS_MODULE,
+		   .of_match_table = spi_imx_dt_ids,
 		   },
 	.id_table = spi_imx_devtype,
 	.probe = spi_imx_probe,
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi-lm70llp.c
index 7746a41ab6d6..933eb9d9ddd4 100644
--- a/drivers/spi/spi_lm70llp.c
+++ b/drivers/spi/spi-lm70llp.c
@@ -1,5 +1,5 @@
 /*
- * spi_lm70llp.c - driver for LM70EVAL-LLP board for the LM70 sensor
+ * Driver for LM70EVAL-LLP board for the LM70 sensor
  *
  * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
  *
@@ -174,7 +174,7 @@ static inline int getmiso(struct spi_device *s)
 }
 /*--------------------------------------------------------------------*/
 
-#include "spi_bitbang_txrx.h"
+#include "spi-bitbang-txrx.h"
 
 static void lm70_chipselect(struct spi_device *spi, int value)
 {
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/spi-mpc512x-psc.c
index 6a5b4238fb6b..6a5b4238fb6b 100644
--- a/drivers/spi/mpc512x_psc_spi.c
+++ b/drivers/spi/spi-mpc512x-psc.c
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/spi-mpc52xx-psc.c
index e30baf0852ac..e30baf0852ac 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/spi-mpc52xx-psc.c
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/spi-mpc52xx.c
index 015a974bed72..015a974bed72 100644
--- a/drivers/spi/mpc52xx_spi.c
+++ b/drivers/spi/spi-mpc52xx.c
diff --git a/drivers/spi/spi_nuc900.c b/drivers/spi/spi-nuc900.c
index 3cd15f690f16..c0a6ce81f9c0 100644
--- a/drivers/spi/spi_nuc900.c
+++ b/drivers/spi/spi-nuc900.c
@@ -1,5 +1,4 @@
-/* linux/drivers/spi/spi_nuc900.c
- *
+/*
  * Copyright (c) 2009 Nuvoton technology.
  * Wan ZongShun <mcuos.com@gmail.com>
  *
@@ -7,7 +6,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
-*/
+ */
 
 #include <linux/init.h>
 #include <linux/spinlock.h>
diff --git a/drivers/spi/spi_oc_tiny.c b/drivers/spi/spi-oc-tiny.c
index f1bde66cea19..f1bde66cea19 100644
--- a/drivers/spi/spi_oc_tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
diff --git a/drivers/spi/omap_spi_100k.c b/drivers/spi/spi-omap-100k.c
index 9bd1c92ad96e..9bd1c92ad96e 100644
--- a/drivers/spi/omap_spi_100k.c
+++ b/drivers/spi/spi-omap-100k.c
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/spi-omap-uwire.c
index 160d3266205f..00a8e9d7dbe4 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/spi-omap-uwire.c
@@ -1,5 +1,5 @@
 /*
- * omap_uwire.c -- MicroWire interface driver for OMAP
+ * MicroWire interface driver for OMAP
  *
  * Copyright 2003 MontaVista Software Inc. <source@mvista.com>
  *
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 969cdd2fe124..fde3a2d4f120 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -1116,8 +1116,8 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
 		status = -ENODEV;
 		goto err1;
 	}
-	if (!request_mem_region(r->start, (r->end - r->start) + 1,
-			dev_name(&pdev->dev))) {
+	if (!request_mem_region(r->start, resource_size(r),
+				dev_name(&pdev->dev))) {
 		status = -EBUSY;
 		goto err1;
 	}
@@ -1125,7 +1125,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
 	r->start += pdata->regs_offset;
 	r->end += pdata->regs_offset;
 	mcspi->phys = r->start;
-	mcspi->base = ioremap(r->start, r->end - r->start + 1);
+	mcspi->base = ioremap(r->start, resource_size(r));
 	if (!mcspi->base) {
 		dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
 		status = -ENOMEM;
@@ -1190,7 +1190,7 @@ err4:
 err3:
 	kfree(mcspi->dma_channels);
 err2:
-	release_mem_region(r->start, (r->end - r->start) + 1);
+	release_mem_region(r->start, resource_size(r));
 	iounmap(mcspi->base);
 err1:
 	return status;
@@ -1210,7 +1210,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
 
 	omap2_mcspi_disable_clocks(mcspi);
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, (r->end - r->start) + 1);
+	release_mem_region(r->start, resource_size(r));
 
 	base = mcspi->base;
 	spi_unregister_master(master);
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/spi-orion.c
index 0b677dc041ad..9421a390a5e3 100644
--- a/drivers/spi/orion_spi.c
+++ b/drivers/spi/spi-orion.c
@@ -1,5 +1,5 @@
 /*
- * orion_spi.c -- Marvell Orion SPI controller driver
+ * Marvell Orion SPI controller driver
  *
  * Author: Shadi Ammouri <shadi@marvell.com>
  * Copyright (C) 2007-2008 Marvell Ltd.
@@ -489,7 +489,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	if (!request_mem_region(r->start, (r->end - r->start) + 1,
+	if (!request_mem_region(r->start, resource_size(r),
 				dev_name(&pdev->dev))) {
 		status = -EBUSY;
 		goto out;
@@ -511,7 +511,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)
 	return status;
 
 out_rel_mem:
-	release_mem_region(r->start, (r->end - r->start) + 1);
+	release_mem_region(r->start, resource_size(r));
 
 out:
 	spi_master_put(master);
@@ -531,7 +531,7 @@ static int __exit orion_spi_remove(struct platform_device *pdev)
 	cancel_work_sync(&spi->work);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, (r->end - r->start) + 1);
+	release_mem_region(r->start, resource_size(r));
 
 	spi_unregister_master(master);
 
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/spi-pl022.c
index d18ce9e946d8..eba88c749fb1 100644
--- a/drivers/spi/amba-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1,6 +1,4 @@
 /*
- * drivers/spi/amba-pl022.c
- *
  * A driver for the ARM PL022 PrimeCell SSP/SPI bus master.
  *
  * Copyright (C) 2008-2009 ST-Ericsson AB
@@ -42,6 +40,7 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
+#include <linux/pm_runtime.h>
 
 /*
  * This macro is used to define some register default values.
@@ -383,6 +382,8 @@ struct pl022 {
 	enum ssp_reading		read;
 	enum ssp_writing		write;
 	u32				exp_fifo_level;
+	enum ssp_rx_level_trig		rx_lev_trig;
+	enum ssp_tx_level_trig		tx_lev_trig;
 	/* DMA settings */
 #ifdef CONFIG_DMA_ENGINE
 	struct dma_chan			*dma_rx_channel;
@@ -517,6 +518,7 @@ static void giveback(struct pl022 *pl022)
 	clk_disable(pl022->clk);
 	amba_pclk_disable(pl022->adev);
 	amba_vcore_disable(pl022->adev);
+	pm_runtime_put(&pl022->adev->dev);
 }
 
 /**
@@ -909,12 +911,10 @@ static int configure_dma(struct pl022 *pl022)
 	struct dma_slave_config rx_conf = {
 		.src_addr = SSP_DR(pl022->phybase),
 		.direction = DMA_FROM_DEVICE,
-		.src_maxburst = pl022->vendor->fifodepth >> 1,
 	};
 	struct dma_slave_config tx_conf = {
 		.dst_addr = SSP_DR(pl022->phybase),
 		.direction = DMA_TO_DEVICE,
-		.dst_maxburst = pl022->vendor->fifodepth >> 1,
 	};
 	unsigned int pages;
 	int ret;
@@ -928,6 +928,54 @@ static int configure_dma(struct pl022 *pl022)
 	if (!rxchan || !txchan)
 		return -ENODEV;
 
+	/*
+	 * If supplied, the DMA burstsize should equal the FIFO trigger level.
+	 * Notice that the DMA engine uses one-to-one mapping. Since we can
+	 * not trigger on 2 elements this needs explicit mapping rather than
+	 * calculation.
+	 */
+	switch (pl022->rx_lev_trig) {
+	case SSP_RX_1_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 1;
+		break;
+	case SSP_RX_4_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 4;
+		break;
+	case SSP_RX_8_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 8;
+		break;
+	case SSP_RX_16_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 16;
+		break;
+	case SSP_RX_32_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 32;
+		break;
+	default:
+		rx_conf.src_maxburst = pl022->vendor->fifodepth >> 1;
+		break;
+	}
+
+	switch (pl022->tx_lev_trig) {
+	case SSP_TX_1_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 1;
+		break;
+	case SSP_TX_4_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 4;
+		break;
+	case SSP_TX_8_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 8;
+		break;
+	case SSP_TX_16_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 16;
+		break;
+	case SSP_TX_32_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 32;
+		break;
+	default:
+		tx_conf.dst_maxburst = pl022->vendor->fifodepth >> 1;
+		break;
+	}
+
 	switch (pl022->read) {
 	case READING_NULL:
 		/* Use the same as for writing */
@@ -1496,6 +1544,7 @@ static void pump_messages(struct work_struct *work)
 	 * and core will be disabled when giveback() is called in each method
 	 * (poll/interrupt/DMA)
 	 */
+	pm_runtime_get_sync(&pl022->adev->dev);
 	amba_vcore_enable(pl022->adev);
 	amba_pclk_enable(pl022->adev);
 	clk_enable(pl022->clk);
@@ -1629,17 +1678,57 @@ static int verify_controller_parameters(struct pl022 *pl022,
 			"Communication mode is configured incorrectly\n");
 		return -EINVAL;
 	}
-	if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM)
-	    || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) {
+	switch (chip_info->rx_lev_trig) {
+	case SSP_RX_1_OR_MORE_ELEM:
+	case SSP_RX_4_OR_MORE_ELEM:
+	case SSP_RX_8_OR_MORE_ELEM:
+		/* These are always OK, all variants can handle this */
+		break;
+	case SSP_RX_16_OR_MORE_ELEM:
+		if (pl022->vendor->fifodepth < 16) {
+			dev_err(&pl022->adev->dev,
+			"RX FIFO Trigger Level is configured incorrectly\n");
+			return -EINVAL;
+		}
+		break;
+	case SSP_RX_32_OR_MORE_ELEM:
+		if (pl022->vendor->fifodepth < 32) {
+			dev_err(&pl022->adev->dev,
+			"RX FIFO Trigger Level is configured incorrectly\n");
+			return -EINVAL;
+		}
+		break;
+	default:
 		dev_err(&pl022->adev->dev,
 			"RX FIFO Trigger Level is configured incorrectly\n");
 		return -EINVAL;
+		break;
 	}
-	if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC)
-	    || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) {
+	switch (chip_info->tx_lev_trig) {
+	case SSP_TX_1_OR_MORE_EMPTY_LOC:
+	case SSP_TX_4_OR_MORE_EMPTY_LOC:
+	case SSP_TX_8_OR_MORE_EMPTY_LOC:
+		/* These are always OK, all variants can handle this */
+		break;
+	case SSP_TX_16_OR_MORE_EMPTY_LOC:
+		if (pl022->vendor->fifodepth < 16) {
+			dev_err(&pl022->adev->dev,
+			"TX FIFO Trigger Level is configured incorrectly\n");
+			return -EINVAL;
+		}
+		break;
+	case SSP_TX_32_OR_MORE_EMPTY_LOC:
+		if (pl022->vendor->fifodepth < 32) {
+			dev_err(&pl022->adev->dev,
+			"TX FIFO Trigger Level is configured incorrectly\n");
+			return -EINVAL;
+		}
+		break;
+	default:
 		dev_err(&pl022->adev->dev,
 			"TX FIFO Trigger Level is configured incorrectly\n");
 		return -EINVAL;
+		break;
 	}
 	if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
 		if ((chip_info->ctrl_len < SSP_BITS_4)
@@ -1874,6 +1963,9 @@ static int pl022_setup(struct spi_device *spi)
 		goto err_config_params;
 	}
 
+	pl022->rx_lev_trig = chip_info->rx_lev_trig;
+	pl022->tx_lev_trig = chip_info->tx_lev_trig;
+
 	/* Now set controller state based on controller data */
 	chip->xfer_type = chip_info->com_mode;
 	if (!chip_info->cs_control) {
@@ -2094,6 +2186,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	}
 	printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
 	       adev->res.start, pl022->virtbase);
+	pm_runtime_enable(dev);
+	pm_runtime_resume(dev);
 
 	pl022->clk = clk_get(&adev->dev, NULL);
 	if (IS_ERR(pl022->clk)) {
@@ -2155,6 +2249,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	destroy_queue(pl022);
 	pl022_dma_remove(pl022);
 	free_irq(adev->irq[0], pl022);
+	pm_runtime_disable(&adev->dev);
  err_no_irq:
 	clk_put(pl022->clk);
  err_no_clk:
diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi-ppc4xx.c
index 2a298c029194..b267fd901e54 100644
--- a/drivers/spi/spi_ppc4xx.c
+++ b/drivers/spi/spi-ppc4xx.c
@@ -502,7 +502,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op)
 		goto free_gpios;
 	}
 	hw->mapbase = resource.start;
-	hw->mapsize = resource.end - resource.start + 1;
+	hw->mapsize = resource_size(&resource);
 
 	/* Sanity check */
 	if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) {
diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/spi-pxa2xx-pci.c
index 378e504f89eb..378e504f89eb 100644
--- a/drivers/spi/pxa2xx_spi_pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/spi-pxa2xx.c
index dc25bee8d33f..dc25bee8d33f 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/spi-pxa2xx.c
diff --git a/drivers/spi/spi_s3c24xx_fiq.S b/drivers/spi/spi-s3c24xx-fiq.S
index 3793cae361db..059f2dc1fda2 100644
--- a/drivers/spi/spi_s3c24xx_fiq.S
+++ b/drivers/spi/spi-s3c24xx-fiq.S
@@ -17,7 +17,7 @@
 #include <mach/regs-irq.h>
 #include <plat/regs-spi.h>
 
-#include "spi_s3c24xx_fiq.h"
+#include "spi-s3c24xx-fiq.h"
 
 	.text
 
diff --git a/drivers/spi/spi_s3c24xx_fiq.h b/drivers/spi/spi-s3c24xx-fiq.h
index a5950bb25b51..a5950bb25b51 100644
--- a/drivers/spi/spi_s3c24xx_fiq.h
+++ b/drivers/spi/spi-s3c24xx-fiq.h
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index 1a5fcabfd565..1996ac57ef91 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -1,5 +1,4 @@
-/* linux/drivers/spi/spi_s3c24xx.c
- *
+/*
  * Copyright (c) 2006 Ben Dooks
  * Copyright 2006-2009 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -32,7 +31,7 @@
 #include <plat/fiq.h>
 #include <asm/fiq.h>
 
-#include "spi_s3c24xx_fiq.h"
+#include "spi-s3c24xx-fiq.h"
 
 /**
  * s3c24xx_spi_devstate - per device data
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 8945e201e42e..595dacc7645f 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -1,5 +1,4 @@
-/* linux/drivers/spi/spi_s3c64xx.c
- *
+/*
  * Copyright (C) 2009 Samsung Electronics Ltd.
  *	Jaswinder Singh <jassi.brar@samsung.com>
  *
diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi-sh-msiof.c
index e00d94b22250..e00d94b22250 100644
--- a/drivers/spi/spi_sh_msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi-sh-sci.c
index 5c6439161199..e7779c09f6ef 100644
--- a/drivers/spi/spi_sh_sci.c
+++ b/drivers/spi/spi-sh-sci.c
@@ -78,7 +78,7 @@ static inline u32 getmiso(struct spi_device *dev)
 
 #define spidelay(x) ndelay(x)
 
-#include "spi_bitbang_txrx.h"
+#include "spi-bitbang-txrx.h"
 
 static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,
 				      unsigned nsecs, u32 word, u8 bits)
diff --git a/drivers/spi/spi_sh.c b/drivers/spi/spi-sh.c
index 9eedd71ad898..9eedd71ad898 100644
--- a/drivers/spi/spi_sh.c
+++ b/drivers/spi/spi-sh.c
diff --git a/drivers/spi/spi_stmp.c b/drivers/spi/spi-stmp.c
index fadff76eb7e0..fadff76eb7e0 100644
--- a/drivers/spi/spi_stmp.c
+++ b/drivers/spi/spi-stmp.c
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi-tegra.c
index 6c3aa6ecaade..a5a6302dc8e0 100644
--- a/drivers/spi/spi_tegra.c
+++ b/drivers/spi/spi-tegra.c
@@ -498,14 +498,14 @@ static int __init spi_tegra_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	if (!request_mem_region(r->start, (r->end - r->start) + 1,
+	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, r->end - r->start + 1);
+	tspi->base = ioremap(r->start, resource_size(r));
 	if (!tspi->base) {
 		dev_err(&pdev->dev, "can't ioremap iomem\n");
 		ret = -ENOMEM;
@@ -546,6 +546,7 @@ static int __init spi_tegra_probe(struct platform_device *pdev)
 	tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
 	tspi->rx_dma_req.dev = tspi;
 
+	master->dev.of_node = pdev->dev.of_node;
 	ret = spi_register_master(master);
 
 	if (ret < 0)
@@ -563,7 +564,7 @@ err3:
 err2:
 	iounmap(tspi->base);
 err1:
-	release_mem_region(r->start, (r->end - r->start) + 1);
+	release_mem_region(r->start, resource_size(r));
 err0:
 	spi_master_put(master);
 	return ret;
@@ -588,17 +589,28 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev)
 	iounmap(tspi->base);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, (r->end - r->start) + 1);
+	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,
 	},
 	.remove =	__devexit_p(spi_tegra_remove),
 };
diff --git a/drivers/spi/ti-ssp-spi.c b/drivers/spi/spi-ti-ssp.c
index ee22795c7973..ee22795c7973 100644
--- a/drivers/spi/ti-ssp-spi.c
+++ b/drivers/spi/spi-ti-ssp.c
diff --git a/drivers/spi/tle62x0.c b/drivers/spi/spi-tle62x0.c
index 32a40876532f..940e73d1cf09 100644
--- a/drivers/spi/tle62x0.c
+++ b/drivers/spi/spi-tle62x0.c
@@ -1,5 +1,5 @@
 /*
- * tle62x0.c -- support Infineon TLE62x0 driver chips
+ * Support Infineon TLE62x0 driver chips
  *
  * Copyright (c) 2007 Simtec Electronics
  *	Ben Dooks, <ben@simtec.co.uk>
diff --git a/drivers/spi/spi_topcliff_pch.c b/drivers/spi/spi-topcliff-pch.c
index 79e48d451137..1d23f3831866 100644
--- a/drivers/spi/spi_topcliff_pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -26,6 +26,10 @@
 #include <linux/spi/spidev.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <linux/dmaengine.h>
+#include <linux/pch_dma.h>
 
 /* Register offsets */
 #define PCH_SPCR		0x00	/* SPI control register */
@@ -35,6 +39,7 @@
 #define PCH_SPDRR		0x10	/* SPI read data register */
 #define PCH_SSNXCR		0x18	/* SSN Expand Control Register */
 #define PCH_SRST		0x1C	/* SPI reset register */
+#define PCH_ADDRESS_SIZE	0x20
 
 #define PCH_SPSR_TFD		0x000007C0
 #define PCH_SPSR_RFD		0x0000F800
@@ -52,8 +57,6 @@
 #define STATUS_EXITING		2
 #define PCH_SLEEP_TIME		10
 
-#define PCH_ADDRESS_SIZE	0x20
-
 #define SSN_LOW			0x02U
 #define SSN_NO_CONTROL		0x00U
 #define PCH_MAX_CS		0xFF
@@ -73,22 +76,57 @@
 #define SPSR_TFI_BIT		(1 << 0)
 #define SPSR_RFI_BIT		(1 << 1)
 #define SPSR_FI_BIT		(1 << 2)
+#define SPSR_ORF_BIT		(1 << 3)
 #define SPBRR_SIZE_BIT		(1 << 10)
 
-#define PCH_ALL			(SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|SPCR_ORIE_BIT|SPCR_MDFIE_BIT)
+#define PCH_ALL			(SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|\
+				SPCR_ORIE_BIT|SPCR_MDFIE_BIT)
 
 #define SPCR_RFIC_FIELD		20
 #define SPCR_TFIC_FIELD		16
 
-#define SPSR_INT_BITS		0x1F
-#define MASK_SPBRR_SPBR_BITS	(~((1 << 10) - 1))
-#define MASK_RFIC_SPCR_BITS	(~(0xf << 20))
-#define MASK_TFIC_SPCR_BITS	(~(0xf000f << 12))
+#define MASK_SPBRR_SPBR_BITS	((1 << 10) - 1)
+#define MASK_RFIC_SPCR_BITS	(0xf << SPCR_RFIC_FIELD)
+#define MASK_TFIC_SPCR_BITS	(0xf << SPCR_TFIC_FIELD)
 
 #define PCH_CLOCK_HZ		50000000
 #define PCH_MAX_SPBR		1023
 
+/* Definition for ML7213 by OKI SEMICONDUCTOR */
+#define PCI_VENDOR_ID_ROHM		0x10DB
+#define PCI_DEVICE_ID_ML7213_SPI	0x802c
+#define PCI_DEVICE_ID_ML7223_SPI	0x800F
 
+/*
+ * Set the number of SPI instance max
+ * Intel EG20T PCH :		1ch
+ * OKI SEMICONDUCTOR ML7213 IOH :	2ch
+ * OKI SEMICONDUCTOR ML7223 IOH :	1ch
+*/
+#define PCH_SPI_MAX_DEV			2
+
+#define PCH_BUF_SIZE		4096
+#define PCH_DMA_TRANS_SIZE	12
+
+static int use_dma = 1;
+
+struct pch_spi_dma_ctrl {
+	struct dma_async_tx_descriptor	*desc_tx;
+	struct dma_async_tx_descriptor	*desc_rx;
+	struct pch_dma_slave		param_tx;
+	struct pch_dma_slave		param_rx;
+	struct dma_chan		*chan_tx;
+	struct dma_chan		*chan_rx;
+	struct scatterlist		*sg_tx_p;
+	struct scatterlist		*sg_rx_p;
+	struct scatterlist		sg_tx;
+	struct scatterlist		sg_rx;
+	int				nent;
+	void				*tx_buf_virt;
+	void				*rx_buf_virt;
+	dma_addr_t			tx_buf_dma;
+	dma_addr_t			rx_buf_dma;
+};
 /**
  * struct pch_spi_data - Holds the SPI channel specific details
  * @io_remap_addr:		The remapped PCI base address
@@ -121,9 +159,13 @@
  * @cur_trans:			The current transfer that this SPI driver is
  *				handling
  * @board_dat:			Reference to the SPI device data structure
+ * @plat_dev:			platform_device structure
+ * @ch:				SPI channel number
+ * @irq_reg_sts:		Status of IRQ registration
  */
 struct pch_spi_data {
 	void __iomem *io_remap_addr;
+	unsigned long io_base_addr;
 	struct spi_master *master;
 	struct work_struct work;
 	struct workqueue_struct *wk;
@@ -144,27 +186,36 @@ struct pch_spi_data {
 	struct spi_message *current_msg;
 	struct spi_transfer *cur_trans;
 	struct pch_spi_board_data *board_dat;
+	struct platform_device	*plat_dev;
+	int ch;
+	struct pch_spi_dma_ctrl dma;
+	int use_dma;
+	u8 irq_reg_sts;
 };
 
 /**
  * struct pch_spi_board_data - Holds the SPI device specific details
  * @pdev:		Pointer to the PCI device
- * @irq_reg_sts:	Status of IRQ registration
- * @pci_req_sts:	Status of pci_request_regions
  * @suspend_sts:	Status of suspend
- * @data:		Pointer to SPI channel data structure
+ * @num:		The number of SPI device instance
  */
 struct pch_spi_board_data {
 	struct pci_dev *pdev;
-	u8 irq_reg_sts;
-	u8 pci_req_sts;
 	u8 suspend_sts;
-	struct pch_spi_data *data;
+	int num;
+};
+
+struct pch_pd_dev_save {
+	int num;
+	struct platform_device *pd_save[PCH_SPI_MAX_DEV];
+	struct pch_spi_board_data *board_dat;
 };
 
 static struct pci_device_id pch_spi_pcidev_id[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_GE_SPI)},
-	{0,}
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI),    1, },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, },
+	{ }
 };
 
 /**
@@ -251,10 +302,10 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
 			reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */
 
 			/* reset rx threshold */
-			reg_spcr_val &= MASK_RFIC_SPCR_BITS;
+			reg_spcr_val &= ~MASK_RFIC_SPCR_BITS;
 			reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD);
-			iowrite32(((reg_spcr_val) &= (~(SPCR_RFIE_BIT))),
-				 (io_remap_addr + PCH_SPCR));
+
+			iowrite32(reg_spcr_val, (io_remap_addr + PCH_SPCR));
 		}
 
 		/* update counts */
@@ -265,12 +316,15 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
 
 	/* if transfer complete interrupt */
 	if (reg_spsr_val & SPSR_FI_BIT) {
-		/* disable FI & RFI interrupts */
-		pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
-				   SPCR_FIE_BIT | SPCR_RFIE_BIT);
+		if (tx_index < bpw_len)
+			dev_err(&data->master->dev,
+				"%s : Transfer is not completed", __func__);
+		/* disable interrupts */
+		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
 
 		/* transfer is completed;inform pch_spi_process_messages */
 		data->transfer_complete = true;
+		data->transfer_active = false;
 		wake_up(&data->wait);
 	}
 }
@@ -283,24 +337,28 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
 static irqreturn_t pch_spi_handler(int irq, void *dev_id)
 {
 	u32 reg_spsr_val;
-	struct pch_spi_data *data;
 	void __iomem *spsr;
 	void __iomem *io_remap_addr;
 	irqreturn_t ret = IRQ_NONE;
-	struct pch_spi_board_data *board_dat = dev_id;
+	struct pch_spi_data *data = dev_id;
+	struct pch_spi_board_data *board_dat = data->board_dat;
 
 	if (board_dat->suspend_sts) {
 		dev_dbg(&board_dat->pdev->dev,
 			"%s returning due to suspend\n", __func__);
 		return IRQ_NONE;
 	}
+	if (data->use_dma)
+		return IRQ_NONE;
 
-	data = board_dat->data;
 	io_remap_addr = data->io_remap_addr;
 	spsr = io_remap_addr + PCH_SPSR;
 
 	reg_spsr_val = ioread32(spsr);
 
+	if (reg_spsr_val & SPSR_ORF_BIT)
+		dev_err(&board_dat->pdev->dev, "%s Over run error", __func__);
+
 	/* Check if the interrupt is for SPI device */
 	if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) {
 		pch_spi_handler_sub(data, reg_spsr_val, io_remap_addr);
@@ -326,7 +384,7 @@ static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz)
 	if (n_spbr > PCH_MAX_SPBR)
 		n_spbr = PCH_MAX_SPBR;
 
-	pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, ~MASK_SPBRR_SPBR_BITS);
+	pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, MASK_SPBRR_SPBR_BITS);
 }
 
 /**
@@ -435,26 +493,27 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
 	dev_dbg(&pspi->dev, "%s Transfer List not empty. "
 		"Transfer Speed is set.\n", __func__);
 
+	spin_lock_irqsave(&data->lock, flags);
 	/* validate Tx/Rx buffers and Transfer length */
 	list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {
 		if (!transfer->tx_buf && !transfer->rx_buf) {
 			dev_err(&pspi->dev,
 				"%s Tx and Rx buffer NULL\n", __func__);
 			retval = -EINVAL;
-			goto err_out;
+			goto err_return_spinlock;
 		}
 
 		if (!transfer->len) {
 			dev_err(&pspi->dev, "%s Transfer length invalid\n",
 				__func__);
 			retval = -EINVAL;
-			goto err_out;
+			goto err_return_spinlock;
 		}
 
 		dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"
 			" valid\n", __func__);
 
-		/* if baud rate hs been specified validate the same */
+		/* if baud rate has been specified validate the same */
 		if (transfer->speed_hz > PCH_MAX_BAUDRATE)
 			transfer->speed_hz = PCH_MAX_BAUDRATE;
 
@@ -465,25 +524,24 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
 				retval = -EINVAL;
 				dev_err(&pspi->dev,
 					"%s Invalid bits per word\n", __func__);
-				goto err_out;
+				goto err_return_spinlock;
 			}
 		}
 	}
-
-	spin_lock_irqsave(&data->lock, flags);
+	spin_unlock_irqrestore(&data->lock, flags);
 
 	/* We won't process any messages if we have been asked to terminate */
 	if (data->status == STATUS_EXITING) {
 		dev_err(&pspi->dev, "%s status = STATUS_EXITING.\n", __func__);
 		retval = -ESHUTDOWN;
-		goto err_return_spinlock;
+		goto err_out;
 	}
 
 	/* If suspended ,return -EINVAL */
 	if (data->board_dat->suspend_sts) {
 		dev_err(&pspi->dev, "%s suspend; returning EINVAL\n", __func__);
 		retval = -EINVAL;
-		goto err_return_spinlock;
+		goto err_out;
 	}
 
 	/* set status of message */
@@ -491,9 +549,11 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
 	dev_dbg(&pspi->dev, "%s - pmsg->status =%d\n", __func__, pmsg->status);
 
 	pmsg->status = -EINPROGRESS;
-
+	spin_lock_irqsave(&data->lock, flags);
 	/* add message to queue */
 	list_add_tail(&pmsg->queue, &data->queue);
+	spin_unlock_irqrestore(&data->lock, flags);
+
 	dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
 
 	/* schedule work queue to run */
@@ -502,11 +562,13 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
 
 	retval = 0;
 
-err_return_spinlock:
-	spin_unlock_irqrestore(&data->lock, flags);
 err_out:
 	dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
 	return retval;
+err_return_spinlock:
+	dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return retval;
 }
 
 static inline void pch_spi_select_chip(struct pch_spi_data *data,
@@ -527,8 +589,7 @@ static inline void pch_spi_select_chip(struct pch_spi_data *data,
 	pch_spi_setup_transfer(pspi);
 }
 
-static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
-			   struct spi_message **ppmsg)
+static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
 {
 	int size;
 	u32 n_writes;
@@ -537,8 +598,6 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
 	const u8 *tx_buf;
 	const u16 *tx_sbuf;
 
-	pmsg = *ppmsg;
-
 	/* set baud rate if needed */
 	if (data->cur_trans->speed_hz) {
 		dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
@@ -621,10 +680,9 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
 	data->transfer_active = true;
 }
 
-
-static void pch_spi_nomore_transfer(struct pch_spi_data *data,
-						struct spi_message *pmsg)
+static void pch_spi_nomore_transfer(struct pch_spi_data *data)
 {
+	struct spi_message *pmsg;
 	dev_dbg(&data->master->dev, "%s called\n", __func__);
 	/* Invoke complete callback
 	 * [To the spi core..indicating end of transfer] */
@@ -675,29 +733,21 @@ static void pch_spi_nomore_transfer(struct pch_spi_data *data,
 
 static void pch_spi_set_ir(struct pch_spi_data *data)
 {
-	/* enable interrupts */
-	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) {
+	/* enable interrupts, set threshold, enable SPI */
+	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH)
 		/* set receive threshold to PCH_RX_THOLD */
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   PCH_RX_THOLD << SPCR_RFIC_FIELD,
-				   ~MASK_RFIC_SPCR_BITS);
-		/* enable FI and RFI interrupts */
-		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   SPCR_RFIE_BIT | SPCR_FIE_BIT, 0);
-	} else {
+				   PCH_RX_THOLD << SPCR_RFIC_FIELD |
+				   SPCR_FIE_BIT | SPCR_RFIE_BIT |
+				   SPCR_ORIE_BIT | SPCR_SPE_BIT,
+				   MASK_RFIC_SPCR_BITS | PCH_ALL);
+	else
 		/* set receive threshold to maximum */
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD,
-				   ~MASK_TFIC_SPCR_BITS);
-		/* enable FI interrupt */
-		pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_FIE_BIT, 0);
-	}
-
-	dev_dbg(&data->master->dev,
-		"%s:invoking pch_spi_set_enable to enable SPI\n", __func__);
-
-	/* SPI set enable */
-	pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, SPCR_SPE_BIT, 0);
+				   PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD |
+				   SPCR_FIE_BIT | SPCR_ORIE_BIT |
+				   SPCR_SPE_BIT,
+				   MASK_RFIC_SPCR_BITS | PCH_ALL);
 
 	/* Wait until the transfer completes; go to sleep after
 				 initiating the transfer. */
@@ -710,15 +760,13 @@ static void pch_spi_set_ir(struct pch_spi_data *data)
 	dev_dbg(&data->master->dev,
 		"%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
 
-	data->transfer_active = false;
-	dev_dbg(&data->master->dev,
-		"%s set data->transfer_active = false\n", __func__);
-
 	/* clear all interrupts */
 	pch_spi_writereg(data->master, PCH_SPSR,
 			 pch_spi_readreg(data->master, PCH_SPSR));
-	/* disable interrupts */
-	pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+	/* Disable interrupts and SPI transfer */
+	pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL | SPCR_SPE_BIT);
+	/* clear FIFO */
+	pch_spi_clear_fifo(data->master);
 }
 
 static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)
@@ -742,6 +790,327 @@ static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)
 	}
 }
 
+static void pch_spi_copy_rx_data_for_dma(struct pch_spi_data *data, int bpw)
+{
+	int j;
+	u8 *rx_buf;
+	u16 *rx_sbuf;
+	const u8 *rx_dma_buf;
+	const u16 *rx_dma_sbuf;
+
+	/* copy Rx Data */
+	if (!data->cur_trans->rx_buf)
+		return;
+
+	if (bpw == 8) {
+		rx_buf = data->cur_trans->rx_buf;
+		rx_dma_buf = data->dma.rx_buf_virt;
+		for (j = 0; j < data->bpw_len; j++)
+			*rx_buf++ = *rx_dma_buf++ & 0xFF;
+	} else {
+		rx_sbuf = data->cur_trans->rx_buf;
+		rx_dma_sbuf = data->dma.rx_buf_virt;
+		for (j = 0; j < data->bpw_len; j++)
+			*rx_sbuf++ = *rx_dma_sbuf++;
+	}
+}
+
+static void pch_spi_start_transfer(struct pch_spi_data *data)
+{
+	struct pch_spi_dma_ctrl *dma;
+	unsigned long flags;
+
+	dma = &data->dma;
+
+	spin_lock_irqsave(&data->lock, flags);
+
+	/* disable interrupts, SPI set enable */
+	pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_SPE_BIT, PCH_ALL);
+
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* Wait until the transfer completes; go to sleep after
+				 initiating the transfer. */
+	dev_dbg(&data->master->dev,
+		"%s:waiting for transfer to get over\n", __func__);
+	wait_event_interruptible(data->wait, data->transfer_complete);
+
+	dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent,
+			    DMA_FROM_DEVICE);
+	async_tx_ack(dma->desc_rx);
+	async_tx_ack(dma->desc_tx);
+	kfree(dma->sg_tx_p);
+	kfree(dma->sg_rx_p);
+
+	spin_lock_irqsave(&data->lock, flags);
+	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
+	dev_dbg(&data->master->dev,
+		"%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
+
+	/* clear fifo threshold, disable interrupts, disable SPI transfer */
+	pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
+			   MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS | PCH_ALL |
+			   SPCR_SPE_BIT);
+	/* clear all interrupts */
+	pch_spi_writereg(data->master, PCH_SPSR,
+			 pch_spi_readreg(data->master, PCH_SPSR));
+	/* clear FIFO */
+	pch_spi_clear_fifo(data->master);
+
+	spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static void pch_dma_rx_complete(void *arg)
+{
+	struct pch_spi_data *data = arg;
+
+	/* transfer is completed;inform pch_spi_process_messages_dma */
+	data->transfer_complete = true;
+	wake_up_interruptible(&data->wait);
+}
+
+static bool pch_spi_filter(struct dma_chan *chan, void *slave)
+{
+	struct pch_dma_slave *param = slave;
+
+	if ((chan->chan_id == param->chan_id) &&
+	    (param->dma_dev == chan->device->dev)) {
+		chan->private = param;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
+{
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+	struct pci_dev *dma_dev;
+	struct pch_dma_slave *param;
+	struct pch_spi_dma_ctrl *dma;
+	unsigned int width;
+
+	if (bpw == 8)
+		width = PCH_DMA_WIDTH_1_BYTE;
+	else
+		width = PCH_DMA_WIDTH_2_BYTES;
+
+	dma = &data->dma;
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	/* Get DMA's dev information */
+	dma_dev = pci_get_bus_and_slot(2, PCI_DEVFN(12, 0));
+
+	/* Set Tx DMA */
+	param = &dma->param_tx;
+	param->dma_dev = &dma_dev->dev;
+	param->chan_id = data->master->bus_num * 2; /* Tx = 0, 2 */
+	param->tx_reg = data->io_base_addr + PCH_SPDWR;
+	param->width = width;
+	chan = dma_request_channel(mask, pch_spi_filter, param);
+	if (!chan) {
+		dev_err(&data->master->dev,
+			"ERROR: dma_request_channel FAILS(Tx)\n");
+		data->use_dma = 0;
+		return;
+	}
+	dma->chan_tx = chan;
+
+	/* Set Rx DMA */
+	param = &dma->param_rx;
+	param->dma_dev = &dma_dev->dev;
+	param->chan_id = data->master->bus_num * 2 + 1; /* Rx = Tx + 1 */
+	param->rx_reg = data->io_base_addr + PCH_SPDRR;
+	param->width = width;
+	chan = dma_request_channel(mask, pch_spi_filter, param);
+	if (!chan) {
+		dev_err(&data->master->dev,
+			"ERROR: dma_request_channel FAILS(Rx)\n");
+		dma_release_channel(dma->chan_tx);
+		dma->chan_tx = NULL;
+		data->use_dma = 0;
+		return;
+	}
+	dma->chan_rx = chan;
+}
+
+static void pch_spi_release_dma(struct pch_spi_data *data)
+{
+	struct pch_spi_dma_ctrl *dma;
+
+	dma = &data->dma;
+	if (dma->chan_tx) {
+		dma_release_channel(dma->chan_tx);
+		dma->chan_tx = NULL;
+	}
+	if (dma->chan_rx) {
+		dma_release_channel(dma->chan_rx);
+		dma->chan_rx = NULL;
+	}
+	return;
+}
+
+static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
+{
+	const u8 *tx_buf;
+	const u16 *tx_sbuf;
+	u8 *tx_dma_buf;
+	u16 *tx_dma_sbuf;
+	struct scatterlist *sg;
+	struct dma_async_tx_descriptor *desc_tx;
+	struct dma_async_tx_descriptor *desc_rx;
+	int num;
+	int i;
+	int size;
+	int rem;
+	unsigned long flags;
+	struct pch_spi_dma_ctrl *dma;
+
+	dma = &data->dma;
+
+	/* set baud rate if needed */
+	if (data->cur_trans->speed_hz) {
+		dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
+		spin_lock_irqsave(&data->lock, flags);
+		pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz);
+		spin_unlock_irqrestore(&data->lock, flags);
+	}
+
+	/* set bits per word if needed */
+	if (data->cur_trans->bits_per_word &&
+	    (data->current_msg->spi->bits_per_word !=
+	     data->cur_trans->bits_per_word)) {
+		dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__);
+		spin_lock_irqsave(&data->lock, flags);
+		pch_spi_set_bits_per_word(data->master,
+					  data->cur_trans->bits_per_word);
+		spin_unlock_irqrestore(&data->lock, flags);
+		*bpw = data->cur_trans->bits_per_word;
+	} else {
+		*bpw = data->current_msg->spi->bits_per_word;
+	}
+	data->bpw_len = data->cur_trans->len / (*bpw / 8);
+
+	/* copy Tx Data */
+	if (data->cur_trans->tx_buf != NULL) {
+		if (*bpw == 8) {
+			tx_buf = data->cur_trans->tx_buf;
+			tx_dma_buf = dma->tx_buf_virt;
+			for (i = 0; i < data->bpw_len; i++)
+				*tx_dma_buf++ = *tx_buf++;
+		} else {
+			tx_sbuf = data->cur_trans->tx_buf;
+			tx_dma_sbuf = dma->tx_buf_virt;
+			for (i = 0; i < data->bpw_len; i++)
+				*tx_dma_sbuf++ = *tx_sbuf++;
+		}
+	}
+	if (data->bpw_len > PCH_DMA_TRANS_SIZE) {
+		num = data->bpw_len / PCH_DMA_TRANS_SIZE + 1;
+		size = PCH_DMA_TRANS_SIZE;
+		rem = data->bpw_len % PCH_DMA_TRANS_SIZE;
+	} else {
+		num = 1;
+		size = data->bpw_len;
+		rem = data->bpw_len;
+	}
+	dev_dbg(&data->master->dev, "%s num=%d size=%d rem=%d\n",
+		__func__, num, size, rem);
+	spin_lock_irqsave(&data->lock, flags);
+
+	/* set receive fifo threshold and transmit fifo threshold */
+	pch_spi_setclr_reg(data->master, PCH_SPCR,
+			   ((size - 1) << SPCR_RFIC_FIELD) |
+			   ((PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE) <<
+			    SPCR_TFIC_FIELD),
+			   MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS);
+
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* RX */
+	dma->sg_rx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+	sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */
+	/* offset, length setting */
+	sg = dma->sg_rx_p;
+	for (i = 0; i < num; i++, sg++) {
+		if (i == 0) {
+			sg->offset = 0;
+			sg_set_page(sg, virt_to_page(dma->rx_buf_virt), rem,
+				    sg->offset);
+			sg_dma_len(sg) = rem;
+		} else {
+			sg->offset = rem + size * (i - 1);
+			sg->offset = sg->offset * (*bpw / 8);
+			sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size,
+				    sg->offset);
+			sg_dma_len(sg) = size;
+		}
+		sg_dma_address(sg) = dma->rx_buf_dma + sg->offset;
+	}
+	sg = dma->sg_rx_p;
+	desc_rx = dma->chan_rx->device->device_prep_slave_sg(dma->chan_rx, sg,
+					num, DMA_FROM_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc_rx) {
+		dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
+			__func__);
+		return;
+	}
+	dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_FROM_DEVICE);
+	desc_rx->callback = pch_dma_rx_complete;
+	desc_rx->callback_param = data;
+	dma->nent = num;
+	dma->desc_rx = desc_rx;
+
+	/* TX */
+	dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+	sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */
+	/* offset, length setting */
+	sg = dma->sg_tx_p;
+	for (i = 0; i < num; i++, sg++) {
+		if (i == 0) {
+			sg->offset = 0;
+			sg_set_page(sg, virt_to_page(dma->tx_buf_virt), rem,
+				    sg->offset);
+			sg_dma_len(sg) = rem;
+		} else {
+			sg->offset = rem + size * (i - 1);
+			sg->offset = sg->offset * (*bpw / 8);
+			sg_set_page(sg, virt_to_page(dma->tx_buf_virt), size,
+				    sg->offset);
+			sg_dma_len(sg) = size;
+		}
+		sg_dma_address(sg) = dma->tx_buf_dma + sg->offset;
+	}
+	sg = dma->sg_tx_p;
+	desc_tx = dma->chan_tx->device->device_prep_slave_sg(dma->chan_tx,
+					sg, num, DMA_TO_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc_tx) {
+		dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
+			__func__);
+		return;
+	}
+	dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_TO_DEVICE);
+	desc_tx->callback = NULL;
+	desc_tx->callback_param = data;
+	dma->nent = num;
+	dma->desc_tx = desc_tx;
+
+	dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
+		"0x2 to SSNXCR\n", __func__);
+
+	spin_lock_irqsave(&data->lock, flags);
+	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
+	desc_rx->tx_submit(desc_rx);
+	desc_tx->tx_submit(desc_tx);
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* reset transfer complete flag */
+	data->transfer_complete = false;
+}
 
 static void pch_spi_process_messages(struct work_struct *pwork)
 {
@@ -753,13 +1122,10 @@ static void pch_spi_process_messages(struct work_struct *pwork)
 	dev_dbg(&data->master->dev, "%s data initialized\n", __func__);
 
 	spin_lock(&data->lock);
-
 	/* check if suspend has been initiated;if yes flush queue */
 	if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
-		dev_dbg(&data->master->dev,
-			"%s suspend/remove initiated,flushing queue\n",
-			__func__);
-
+		dev_dbg(&data->master->dev, "%s suspend/remove initiated,"
+			"flushing queue\n", __func__);
 		list_for_each_entry(pmsg, data->queue.next, queue) {
 			pmsg->status = -EIO;
 
@@ -793,53 +1159,42 @@ static void pch_spi_process_messages(struct work_struct *pwork)
 
 	spin_unlock(&data->lock);
 
+	if (data->use_dma)
+		pch_spi_request_dma(data,
+				    data->current_msg->spi->bits_per_word);
 	do {
 		/* If we are already processing a message get the next
 		transfer structure from the message otherwise retrieve
 		the 1st transfer request from the message. */
 		spin_lock(&data->lock);
-
 		if (data->cur_trans == NULL) {
 			data->cur_trans =
-			    list_entry(data->current_msg->transfers.
-				       next, struct spi_transfer,
-				       transfer_list);
-			dev_dbg(&data->master->dev,
-				"%s :Getting 1st transfer message\n", __func__);
+				list_entry(data->current_msg->transfers.next,
+					   struct spi_transfer, transfer_list);
+			dev_dbg(&data->master->dev, "%s "
+				":Getting 1st transfer message\n", __func__);
 		} else {
 			data->cur_trans =
-			    list_entry(data->cur_trans->transfer_list.next,
-				       struct spi_transfer,
-				       transfer_list);
-			dev_dbg(&data->master->dev,
-				"%s :Getting next transfer message\n",
-				__func__);
+				list_entry(data->cur_trans->transfer_list.next,
+					   struct spi_transfer, transfer_list);
+			dev_dbg(&data->master->dev, "%s "
+				":Getting next transfer message\n", __func__);
 		}
-
 		spin_unlock(&data->lock);
 
-		pch_spi_set_tx(data, &bpw, &pmsg);
-
-		/* Control interrupt*/
-		pch_spi_set_ir(data);
-
-		/* Disable SPI transfer */
-		pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, 0,
-				   SPCR_SPE_BIT);
-
-		/* clear FIFO */
-		pch_spi_clear_fifo(data->master);
-
-		/* copy Rx Data */
-		pch_spi_copy_rx_data(data, bpw);
-
-		/* free memory */
-		kfree(data->pkt_rx_buff);
-		data->pkt_rx_buff = NULL;
-
-		kfree(data->pkt_tx_buff);
-		data->pkt_tx_buff = NULL;
-
+		if (data->use_dma) {
+			pch_spi_handle_dma(data, &bpw);
+			pch_spi_start_transfer(data);
+			pch_spi_copy_rx_data_for_dma(data, bpw);
+		} else {
+			pch_spi_set_tx(data, &bpw);
+			pch_spi_set_ir(data);
+			pch_spi_copy_rx_data(data, bpw);
+			kfree(data->pkt_rx_buff);
+			data->pkt_rx_buff = NULL;
+			kfree(data->pkt_tx_buff);
+			data->pkt_tx_buff = NULL;
+		}
 		/* increment message count */
 		data->current_msg->actual_length += data->cur_trans->len;
 
@@ -860,125 +1215,60 @@ static void pch_spi_process_messages(struct work_struct *pwork)
 		/* No more transfer in this message. */
 		if ((data->cur_trans->transfer_list.next) ==
 		    &(data->current_msg->transfers)) {
-			pch_spi_nomore_transfer(data, pmsg);
+			pch_spi_nomore_transfer(data);
 		}
 
 		spin_unlock(&data->lock);
 
 	} while (data->cur_trans != NULL);
+
+	if (data->use_dma)
+		pch_spi_release_dma(data);
 }
 
-static void pch_spi_free_resources(struct pch_spi_board_data *board_dat)
+static void pch_spi_free_resources(struct pch_spi_board_data *board_dat,
+				   struct pch_spi_data *data)
 {
 	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
 
 	/* free workqueue */
-	if (board_dat->data->wk != NULL) {
-		destroy_workqueue(board_dat->data->wk);
-		board_dat->data->wk = NULL;
+	if (data->wk != NULL) {
+		destroy_workqueue(data->wk);
+		data->wk = NULL;
 		dev_dbg(&board_dat->pdev->dev,
 			"%s destroy_workqueue invoked successfully\n",
 			__func__);
 	}
-
-	/* disable interrupts & free IRQ */
-	if (board_dat->irq_reg_sts) {
-		/* disable interrupts */
-		pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
-				   PCH_ALL);
-
-		/* free IRQ */
-		free_irq(board_dat->pdev->irq, board_dat);
-
-		dev_dbg(&board_dat->pdev->dev,
-			"%s free_irq invoked successfully\n", __func__);
-
-		board_dat->irq_reg_sts = false;
-	}
-
-	/* unmap PCI base address */
-	if (board_dat->data->io_remap_addr != 0) {
-		pci_iounmap(board_dat->pdev, board_dat->data->io_remap_addr);
-
-		board_dat->data->io_remap_addr = 0;
-
-		dev_dbg(&board_dat->pdev->dev,
-			"%s pci_iounmap invoked successfully\n", __func__);
-	}
-
-	/* release PCI region */
-	if (board_dat->pci_req_sts) {
-		pci_release_regions(board_dat->pdev);
-		dev_dbg(&board_dat->pdev->dev,
-			"%s pci_release_regions invoked successfully\n",
-			__func__);
-		board_dat->pci_req_sts = false;
-	}
 }
 
-static int pch_spi_get_resources(struct pch_spi_board_data *board_dat)
+static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
+				 struct pch_spi_data *data)
 {
-	void __iomem *io_remap_addr;
-	int retval;
+	int retval = 0;
+
 	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
 
 	/* create workqueue */
-	board_dat->data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
-	if (!board_dat->data->wk) {
+	data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
+	if (!data->wk) {
 		dev_err(&board_dat->pdev->dev,
 			"%s create_singlet hread_workqueue failed\n", __func__);
 		retval = -EBUSY;
 		goto err_return;
 	}
 
-	dev_dbg(&board_dat->pdev->dev,
-		"%s create_singlethread_workqueue success\n", __func__);
-
-	retval = pci_request_regions(board_dat->pdev, KBUILD_MODNAME);
-	if (retval != 0) {
-		dev_err(&board_dat->pdev->dev,
-			"%s request_region failed\n", __func__);
-		goto err_return;
-	}
-
-	board_dat->pci_req_sts = true;
-
-	io_remap_addr = pci_iomap(board_dat->pdev, 1, 0);
-	if (io_remap_addr == 0) {
-		dev_err(&board_dat->pdev->dev,
-			"%s pci_iomap failed\n", __func__);
-		retval = -ENOMEM;
-		goto err_return;
-	}
-
-	/* calculate base address for all channels */
-	board_dat->data->io_remap_addr = io_remap_addr;
-
 	/* reset PCH SPI h/w */
-	pch_spi_reset(board_dat->data->master);
+	pch_spi_reset(data->master);
 	dev_dbg(&board_dat->pdev->dev,
 		"%s pch_spi_reset invoked successfully\n", __func__);
 
-	/* register IRQ */
-	retval = request_irq(board_dat->pdev->irq, pch_spi_handler,
-			     IRQF_SHARED, KBUILD_MODNAME, board_dat);
-	if (retval != 0) {
-		dev_err(&board_dat->pdev->dev,
-			"%s request_irq failed\n", __func__);
-		goto err_return;
-	}
-
-	dev_dbg(&board_dat->pdev->dev, "%s request_irq returned=%d\n",
-		__func__, retval);
-
-	board_dat->irq_reg_sts = true;
 	dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
 
 err_return:
 	if (retval != 0) {
 		dev_err(&board_dat->pdev->dev,
 			"%s FAIL:invoking pch_spi_free_resources\n", __func__);
-		pch_spi_free_resources(board_dat);
+		pch_spi_free_resources(board_dat, data);
 	}
 
 	dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval);
@@ -986,255 +1276,387 @@ err_return:
 	return retval;
 }
 
-static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static void pch_free_dma_buf(struct pch_spi_board_data *board_dat,
+			     struct pch_spi_data *data)
 {
+	struct pch_spi_dma_ctrl *dma;
+
+	dma = &data->dma;
+	if (dma->tx_buf_dma)
+		dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE,
+				  dma->tx_buf_virt, dma->tx_buf_dma);
+	if (dma->rx_buf_dma)
+		dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE,
+				  dma->rx_buf_virt, dma->rx_buf_dma);
+	return;
+}
 
-	struct spi_master *master;
-
-	struct pch_spi_board_data *board_dat;
-	int retval;
-
-	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
-
-	/* allocate memory for private data */
-	board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
-	if (board_dat == NULL) {
-		dev_err(&pdev->dev,
-			" %s memory allocation for private data failed\n",
-			__func__);
-		retval = -ENOMEM;
-		goto err_kmalloc;
-	}
+static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat,
+			      struct pch_spi_data *data)
+{
+	struct pch_spi_dma_ctrl *dma;
+
+	dma = &data->dma;
+	/* Get Consistent memory for Tx DMA */
+	dma->tx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
+				PCH_BUF_SIZE, &dma->tx_buf_dma, GFP_KERNEL);
+	/* Get Consistent memory for Rx DMA */
+	dma->rx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
+				PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL);
+}
 
-	dev_dbg(&pdev->dev,
-		"%s memory allocation for private data success\n", __func__);
+static int __devinit pch_spi_pd_probe(struct platform_device *plat_dev)
+{
+	int ret;
+	struct spi_master *master;
+	struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev);
+	struct pch_spi_data *data;
 
-	/* enable PCI device */
-	retval = pci_enable_device(pdev);
-	if (retval != 0) {
-		dev_err(&pdev->dev, "%s pci_enable_device FAILED\n", __func__);
+	dev_dbg(&plat_dev->dev, "%s:debug\n", __func__);
 
-		goto err_pci_en_device;
+	master = spi_alloc_master(&board_dat->pdev->dev,
+				  sizeof(struct pch_spi_data));
+	if (!master) {
+		dev_err(&plat_dev->dev, "spi_alloc_master[%d] failed.\n",
+			plat_dev->id);
+		return -ENOMEM;
 	}
 
-	dev_dbg(&pdev->dev, "%s pci_enable_device returned=%d\n",
-		__func__, retval);
+	data = spi_master_get_devdata(master);
+	data->master = master;
 
-	board_dat->pdev = pdev;
+	platform_set_drvdata(plat_dev, data);
 
-	/* alllocate memory for SPI master */
-	master = spi_alloc_master(&pdev->dev, sizeof(struct pch_spi_data));
-	if (master == NULL) {
-		retval = -ENOMEM;
-		dev_err(&pdev->dev, "%s Fail.\n", __func__);
-		goto err_spi_alloc_master;
+	/* baseaddress + address offset) */
+	data->io_base_addr = pci_resource_start(board_dat->pdev, 1) +
+					 PCH_ADDRESS_SIZE * plat_dev->id;
+	data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0) +
+					 PCH_ADDRESS_SIZE * plat_dev->id;
+	if (!data->io_remap_addr) {
+		dev_err(&plat_dev->dev, "%s pci_iomap failed\n", __func__);
+		ret = -ENOMEM;
+		goto err_pci_iomap;
 	}
 
-	dev_dbg(&pdev->dev,
-		"%s spi_alloc_master returned non NULL\n", __func__);
+	dev_dbg(&plat_dev->dev, "[ch%d] remap_addr=%p\n",
+		plat_dev->id, data->io_remap_addr);
 
 	/* initialize members of SPI master */
 	master->bus_num = -1;
 	master->num_chipselect = PCH_MAX_CS;
 	master->setup = pch_spi_setup;
 	master->transfer = pch_spi_transfer;
-	dev_dbg(&pdev->dev,
-		"%s transfer member of SPI master initialized\n", __func__);
-
-	board_dat->data = spi_master_get_devdata(master);
-
-	board_dat->data->master = master;
-	board_dat->data->n_curnt_chip = 255;
-	board_dat->data->board_dat = board_dat;
-	board_dat->data->status = STATUS_RUNNING;
-
-	INIT_LIST_HEAD(&board_dat->data->queue);
-	spin_lock_init(&board_dat->data->lock);
-	INIT_WORK(&board_dat->data->work, pch_spi_process_messages);
-	init_waitqueue_head(&board_dat->data->wait);
 
-	/* allocate resources for PCH SPI */
-	retval = pch_spi_get_resources(board_dat);
-	if (retval) {
-		dev_err(&pdev->dev, "%s fail(retval=%d)\n", __func__, retval);
+	data->board_dat = board_dat;
+	data->plat_dev = plat_dev;
+	data->n_curnt_chip = 255;
+	data->status = STATUS_RUNNING;
+	data->ch = plat_dev->id;
+	data->use_dma = use_dma;
+
+	INIT_LIST_HEAD(&data->queue);
+	spin_lock_init(&data->lock);
+	INIT_WORK(&data->work, pch_spi_process_messages);
+	init_waitqueue_head(&data->wait);
+
+	ret = pch_spi_get_resources(board_dat, data);
+	if (ret) {
+		dev_err(&plat_dev->dev, "%s fail(retval=%d)\n", __func__, ret);
 		goto err_spi_get_resources;
 	}
 
-	dev_dbg(&pdev->dev, "%s pch_spi_get_resources returned=%d\n",
-		__func__, retval);
-
-	/* save private data in dev */
-	pci_set_drvdata(pdev, board_dat);
-	dev_dbg(&pdev->dev, "%s invoked pci_set_drvdata\n", __func__);
+	ret = request_irq(board_dat->pdev->irq, pch_spi_handler,
+			  IRQF_SHARED, KBUILD_MODNAME, data);
+	if (ret) {
+		dev_err(&plat_dev->dev,
+			"%s request_irq failed\n", __func__);
+		goto err_request_irq;
+	}
+	data->irq_reg_sts = true;
 
-	/* set master mode */
 	pch_spi_set_master_mode(master);
-	dev_dbg(&pdev->dev,
-		"%s invoked pch_spi_set_master_mode\n", __func__);
 
-	/* Register the controller with the SPI core. */
-	retval = spi_register_master(master);
-	if (retval != 0) {
-		dev_err(&pdev->dev,
+	ret = spi_register_master(master);
+	if (ret != 0) {
+		dev_err(&plat_dev->dev,
 			"%s spi_register_master FAILED\n", __func__);
-		goto err_spi_reg_master;
+		goto err_spi_register_master;
 	}
 
-	dev_dbg(&pdev->dev, "%s spi_register_master returned=%d\n",
-		__func__, retval);
-
+	if (use_dma) {
+		dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
+		pch_alloc_dma_buf(board_dat, data);
+	}
 
 	return 0;
 
-err_spi_reg_master:
-	spi_unregister_master(master);
+err_spi_register_master:
+	free_irq(board_dat->pdev->irq, board_dat);
+err_request_irq:
+	pch_spi_free_resources(board_dat, data);
 err_spi_get_resources:
-err_spi_alloc_master:
+	pci_iounmap(board_dat->pdev, data->io_remap_addr);
+err_pci_iomap:
 	spi_master_put(master);
-	pci_disable_device(pdev);
-err_pci_en_device:
-	kfree(board_dat);
-err_kmalloc:
-	return retval;
+
+	return ret;
 }
 
-static void pch_spi_remove(struct pci_dev *pdev)
+static int __devexit pch_spi_pd_remove(struct platform_device *plat_dev)
 {
-	struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
+	struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev);
+	struct pch_spi_data *data = platform_get_drvdata(plat_dev);
 	int count;
+	unsigned long flags;
 
-	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+	dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n",
+		__func__, plat_dev->id, board_dat->pdev->irq);
 
-	if (!board_dat) {
-		dev_err(&pdev->dev,
-			"%s pci_get_drvdata returned NULL\n", __func__);
-		return;
-	}
+	if (use_dma)
+		pch_free_dma_buf(board_dat, data);
 
 	/* check for any pending messages; no action is taken if the queue
 	 * is still full; but at least we tried.  Unload anyway */
 	count = 500;
-	spin_lock(&board_dat->data->lock);
-	board_dat->data->status = STATUS_EXITING;
-	while ((list_empty(&board_dat->data->queue) == 0) && --count) {
+	spin_lock_irqsave(&data->lock, flags);
+	data->status = STATUS_EXITING;
+	while ((list_empty(&data->queue) == 0) && --count) {
 		dev_dbg(&board_dat->pdev->dev, "%s :queue not empty\n",
 			__func__);
-		spin_unlock(&board_dat->data->lock);
+		spin_unlock_irqrestore(&data->lock, flags);
 		msleep(PCH_SLEEP_TIME);
-		spin_lock(&board_dat->data->lock);
+		spin_lock_irqsave(&data->lock, flags);
 	}
-	spin_unlock(&board_dat->data->lock);
-
-	/* Free resources allocated for PCH SPI */
-	pch_spi_free_resources(board_dat);
-
-	spi_unregister_master(board_dat->data->master);
-
-	/* free memory for private data */
-	kfree(board_dat);
+	spin_unlock_irqrestore(&data->lock, flags);
 
-	pci_set_drvdata(pdev, NULL);
+	pch_spi_free_resources(board_dat, data);
+	/* disable interrupts & free IRQ */
+	if (data->irq_reg_sts) {
+		/* disable interrupts */
+		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+		data->irq_reg_sts = false;
+		free_irq(board_dat->pdev->irq, data);
+	}
 
-	/* disable PCI device */
-	pci_disable_device(pdev);
+	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);
 
-	dev_dbg(&pdev->dev, "%s invoked pci_disable_device\n", __func__);
+	return 0;
 }
-
 #ifdef CONFIG_PM
-static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state)
+static int pch_spi_pd_suspend(struct platform_device *pd_dev,
+			      pm_message_t state)
 {
 	u8 count;
-	int retval;
-
-	struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
+	struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev);
+	struct pch_spi_data *data = platform_get_drvdata(pd_dev);
 
-	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+	dev_dbg(&pd_dev->dev, "%s ENTRY\n", __func__);
 
 	if (!board_dat) {
-		dev_err(&pdev->dev,
+		dev_err(&pd_dev->dev,
 			"%s pci_get_drvdata returned NULL\n", __func__);
 		return -EFAULT;
 	}
 
-	retval = 0;
-	board_dat->suspend_sts = true;
-
 	/* check if the current message is processed:
 	   Only after thats done the transfer will be suspended */
 	count = 255;
 	while ((--count) > 0) {
-		if (!(board_dat->data->bcurrent_msg_processing)) {
-			dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_"
-				"msg_processing = false\n", __func__);
+		if (!(data->bcurrent_msg_processing))
 			break;
-		} else {
-			dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_msg_"
-				"processing = true\n", __func__);
-		}
 		msleep(PCH_SLEEP_TIME);
 	}
 
 	/* Free IRQ */
-	if (board_dat->irq_reg_sts) {
+	if (data->irq_reg_sts) {
 		/* disable all interrupts */
-		pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
-				   PCH_ALL);
-		pch_spi_reset(board_dat->data->master);
-
-		free_irq(board_dat->pdev->irq, board_dat);
+		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+		pch_spi_reset(data->master);
+		free_irq(board_dat->pdev->irq, data);
 
-		board_dat->irq_reg_sts = false;
-		dev_dbg(&pdev->dev,
+		data->irq_reg_sts = false;
+		dev_dbg(&pd_dev->dev,
 			"%s free_irq invoked successfully.\n", __func__);
 	}
 
+	return 0;
+}
+
+static int pch_spi_pd_resume(struct platform_device *pd_dev)
+{
+	struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev);
+	struct pch_spi_data *data = platform_get_drvdata(pd_dev);
+	int retval;
+
+	if (!board_dat) {
+		dev_err(&pd_dev->dev,
+			"%s pci_get_drvdata returned NULL\n", __func__);
+		return -EFAULT;
+	}
+
+	if (!data->irq_reg_sts) {
+		/* register IRQ */
+		retval = request_irq(board_dat->pdev->irq, pch_spi_handler,
+				     IRQF_SHARED, KBUILD_MODNAME, data);
+		if (retval < 0) {
+			dev_err(&pd_dev->dev,
+				"%s request_irq failed\n", __func__);
+			return retval;
+		}
+
+		/* reset PCH SPI h/w */
+		pch_spi_reset(data->master);
+		pch_spi_set_master_mode(data->master);
+		data->irq_reg_sts = true;
+	}
+	return 0;
+}
+#else
+#define pch_spi_pd_suspend NULL
+#define pch_spi_pd_resume NULL
+#endif
+
+static struct platform_driver pch_spi_pd_driver = {
+	.driver = {
+		.name = "pch-spi",
+		.owner = THIS_MODULE,
+	},
+	.probe = pch_spi_pd_probe,
+	.remove = __devexit_p(pch_spi_pd_remove),
+	.suspend = pch_spi_pd_suspend,
+	.resume = pch_spi_pd_resume
+};
+
+static int __devinit pch_spi_probe(struct pci_dev *pdev,
+				   const struct pci_device_id *id)
+{
+	struct pch_spi_board_data *board_dat;
+	struct platform_device *pd_dev = NULL;
+	int retval;
+	int i;
+	struct pch_pd_dev_save *pd_dev_save;
+
+	pd_dev_save = kzalloc(sizeof(struct pch_pd_dev_save), GFP_KERNEL);
+	if (!pd_dev_save) {
+		dev_err(&pdev->dev, "%s Can't allocate pd_dev_sav\n", __func__);
+		return -ENOMEM;
+	}
+
+	board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
+	if (!board_dat) {
+		dev_err(&pdev->dev, "%s Can't allocate board_dat\n", __func__);
+		retval = -ENOMEM;
+		goto err_no_mem;
+	}
+
+	retval = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (retval) {
+		dev_err(&pdev->dev, "%s request_region failed\n", __func__);
+		goto pci_request_regions;
+	}
+
+	board_dat->pdev = pdev;
+	board_dat->num = id->driver_data;
+	pd_dev_save->num = id->driver_data;
+	pd_dev_save->board_dat = board_dat;
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "%s pci_enable_device failed\n", __func__);
+		goto pci_enable_device;
+	}
+
+	for (i = 0; i < board_dat->num; i++) {
+		pd_dev = platform_device_alloc("pch-spi", i);
+		if (!pd_dev) {
+			dev_err(&pdev->dev, "platform_device_alloc failed\n");
+			goto err_platform_device;
+		}
+		pd_dev_save->pd_save[i] = pd_dev;
+		pd_dev->dev.parent = &pdev->dev;
+
+		retval = platform_device_add_data(pd_dev, board_dat,
+						  sizeof(*board_dat));
+		if (retval) {
+			dev_err(&pdev->dev,
+				"platform_device_add_data failed\n");
+			platform_device_put(pd_dev);
+			goto err_platform_device;
+		}
+
+		retval = platform_device_add(pd_dev);
+		if (retval) {
+			dev_err(&pdev->dev, "platform_device_add failed\n");
+			platform_device_put(pd_dev);
+			goto err_platform_device;
+		}
+	}
+
+	pci_set_drvdata(pdev, pd_dev_save);
+
+	return 0;
+
+err_platform_device:
+	pci_disable_device(pdev);
+pci_enable_device:
+	pci_release_regions(pdev);
+pci_request_regions:
+	kfree(board_dat);
+err_no_mem:
+	kfree(pd_dev_save);
+
+	return retval;
+}
+
+static void __devexit pch_spi_remove(struct pci_dev *pdev)
+{
+	int i;
+	struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
+
+	dev_dbg(&pdev->dev, "%s ENTRY:pdev=%p\n", __func__, pdev);
+
+	for (i = 0; i < pd_dev_save->num; i++)
+		platform_device_unregister(pd_dev_save->pd_save[i]);
+
+	pci_disable_device(pdev);
+	pci_release_regions(pdev);
+	kfree(pd_dev_save->board_dat);
+	kfree(pd_dev_save);
+}
+
+#ifdef CONFIG_PM
+static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int retval;
+	struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
+
+	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+	pd_dev_save->board_dat->suspend_sts = true;
+
 	/* save config space */
 	retval = pci_save_state(pdev);
-
 	if (retval == 0) {
-		dev_dbg(&pdev->dev, "%s pci_save_state returned=%d\n",
-			__func__, retval);
-		/* disable PM notifications */
 		pci_enable_wake(pdev, PCI_D3hot, 0);
-		dev_dbg(&pdev->dev,
-			"%s pci_enable_wake invoked successfully\n", __func__);
-		/* disable PCI device */
 		pci_disable_device(pdev);
-		dev_dbg(&pdev->dev,
-			"%s pci_disable_device invoked successfully\n",
-			__func__);
-		/* move device to D3hot  state */
 		pci_set_power_state(pdev, PCI_D3hot);
-		dev_dbg(&pdev->dev,
-			"%s pci_set_power_state invoked successfully\n",
-			__func__);
 	} else {
 		dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__);
 	}
 
-	dev_dbg(&pdev->dev, "%s return=%d\n", __func__, retval);
-
 	return retval;
 }
 
 static int pch_spi_resume(struct pci_dev *pdev)
 {
 	int retval;
-
-	struct pch_spi_board_data *board = pci_get_drvdata(pdev);
+	struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
 	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
 
-	if (!board) {
-		dev_err(&pdev->dev,
-			"%s pci_get_drvdata returned NULL\n", __func__);
-		return -EFAULT;
-	}
-
-	/* move device to DO power state */
 	pci_set_power_state(pdev, PCI_D0);
-
-	/* restore state */
 	pci_restore_state(pdev);
 
 	retval = pci_enable_device(pdev);
@@ -1242,34 +1664,12 @@ static int pch_spi_resume(struct pci_dev *pdev)
 		dev_err(&pdev->dev,
 			"%s pci_enable_device failed\n", __func__);
 	} else {
-		/* disable PM notifications */
 		pci_enable_wake(pdev, PCI_D3hot, 0);
 
-		/* register IRQ handler */
-		if (!board->irq_reg_sts) {
-			/* register IRQ */
-			retval = request_irq(board->pdev->irq, pch_spi_handler,
-					     IRQF_SHARED, KBUILD_MODNAME,
-					     board);
-			if (retval < 0) {
-				dev_err(&pdev->dev,
-					"%s request_irq failed\n", __func__);
-				return retval;
-			}
-			board->irq_reg_sts = true;
-
-			/* reset PCH SPI h/w */
-			pch_spi_reset(board->data->master);
-			pch_spi_set_master_mode(board->data->master);
-
-			/* set suspend status to false */
-			board->suspend_sts = false;
-
-		}
+		/* set suspend status to false */
+		pd_dev_save->board_dat->suspend_sts = false;
 	}
 
-	dev_dbg(&pdev->dev, "%s returning=%d\n", __func__, retval);
-
 	return retval;
 }
 #else
@@ -1289,15 +1689,29 @@ static struct pci_driver pch_spi_pcidev = {
 
 static int __init pch_spi_init(void)
 {
-	return pci_register_driver(&pch_spi_pcidev);
+	int ret;
+	ret = platform_driver_register(&pch_spi_pd_driver);
+	if (ret)
+		return ret;
+
+	ret = pci_register_driver(&pch_spi_pcidev);
+	if (ret)
+		return ret;
+
+	return 0;
 }
 module_init(pch_spi_init);
 
 static void __exit pch_spi_exit(void)
 {
 	pci_unregister_driver(&pch_spi_pcidev);
+	platform_driver_unregister(&pch_spi_pd_driver);
 }
 module_exit(pch_spi_exit);
 
+module_param(use_dma, int, 0644);
+MODULE_PARM_DESC(use_dma,
+		 "to use DMA for data transfers pass 1 else 0; default 1");
+
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Topcliff PCH SPI PCI Driver");
+MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7xxx IOH SPI Driver");
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi-txx9.c
index dfa024b633e1..f0a2ab0428a3 100644
--- a/drivers/spi/spi_txx9.c
+++ b/drivers/spi/spi-txx9.c
@@ -1,5 +1,5 @@
 /*
- * spi_txx9.c - TXx9 SPI controller driver.
+ * TXx9 SPI controller driver.
  *
  * Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
  * Copyright (C) 2000-2001 Toshiba Corporation
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/spi-xilinx.c
index 4d2c75df886c..4d2c75df886c 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/spi-xilinx.c
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 2e13a14bba3f..4d1b9f517ce8 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1,5 +1,5 @@
 /*
- * spi.c - SPI init/core code
+ * SPI init/core code
  *
  * Copyright (C) 2005 David Brownell
  *
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
deleted file mode 100644
index be991359bf92..000000000000
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* linux/drivers/spi/spi_s3c24xx_gpio.c
- *
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- *
- * S3C24XX GPIO based SPI driver
- *
- * 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.
- *
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/spi-gpio.h>
-#include <mach/hardware.h>
-
-struct s3c2410_spigpio {
-	struct spi_bitbang		 bitbang;
-
-	struct s3c2410_spigpio_info	*info;
-	struct platform_device		*dev;
-};
-
-static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi)
-{
-	return spi_master_get_devdata(spi->master);
-}
-
-static inline void setsck(struct spi_device *dev, int on)
-{
-	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-	s3c2410_gpio_setpin(sg->info->pin_clk, on ? 1 : 0);
-}
-
-static inline void setmosi(struct spi_device *dev, int on)
-{
-	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-	s3c2410_gpio_setpin(sg->info->pin_mosi, on ? 1 : 0);
-}
-
-static inline u32 getmiso(struct spi_device *dev)
-{
-	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-	return s3c2410_gpio_getpin(sg->info->pin_miso) ? 1 : 0;
-}
-
-#define spidelay(x) ndelay(x)
-
-#include "spi_bitbang_txrx.h"
-
-
-static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
-}
-
-static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
-}
-
-
-static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
-{
-	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-
-	if (sg->info && sg->info->chip_select)
-		(sg->info->chip_select)(sg->info, value);
-}
-
-static int s3c2410_spigpio_probe(struct platform_device *dev)
-{
-	struct s3c2410_spigpio_info *info;
-	struct spi_master	*master;
-	struct s3c2410_spigpio  *sp;
-	int ret;
-
-	master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));
-	if (master == NULL) {
-		dev_err(&dev->dev, "failed to allocate spi master\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	sp = spi_master_get_devdata(master);
-
-	platform_set_drvdata(dev, sp);
-
-	/* copy in the plkatform data */
-	info = sp->info = dev->dev.platform_data;
-
-	/* setup spi bitbang adaptor */
-	sp->bitbang.master = spi_master_get(master);
-	sp->bitbang.master->bus_num = info->bus_num;
-	sp->bitbang.master->num_chipselect = info->num_chipselect;
-	sp->bitbang.chipselect = s3c2410_spigpio_chipselect;
-
-	sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
-	sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
-	sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2;
-	sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3;
-
-	/* set state of spi pins, always assume that the clock is
-	 * available, but do check the MOSI and MISO. */
-	s3c2410_gpio_setpin(info->pin_clk, 0);
-	s3c2410_gpio_cfgpin(info->pin_clk, S3C2410_GPIO_OUTPUT);
-
-	if (info->pin_mosi < S3C2410_GPH10) {
-		s3c2410_gpio_setpin(info->pin_mosi, 0);
-		s3c2410_gpio_cfgpin(info->pin_mosi, S3C2410_GPIO_OUTPUT);
-	}
-
-	if (info->pin_miso != S3C2410_GPA0 && info->pin_miso < S3C2410_GPH10)
-		s3c2410_gpio_cfgpin(info->pin_miso, S3C2410_GPIO_INPUT);
-
-	ret = spi_bitbang_start(&sp->bitbang);
-	if (ret)
-		goto err_no_bitbang;
-
-	return 0;
-
- err_no_bitbang:
-	spi_master_put(sp->bitbang.master);
- err:
-	return ret;
-
-}
-
-static int s3c2410_spigpio_remove(struct platform_device *dev)
-{
-	struct s3c2410_spigpio *sp = platform_get_drvdata(dev);
-
-	spi_bitbang_stop(&sp->bitbang);
-	spi_master_put(sp->bitbang.master);
-
-	return 0;
-}
-
-/* all gpio should be held over suspend/resume, so we should
- * not need to deal with this
-*/
-
-#define s3c2410_spigpio_suspend NULL
-#define s3c2410_spigpio_resume NULL
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:spi_s3c24xx_gpio");
-
-static struct platform_driver s3c2410_spigpio_drv = {
-	.probe		= s3c2410_spigpio_probe,
-        .remove		= s3c2410_spigpio_remove,
-        .suspend	= s3c2410_spigpio_suspend,
-        .resume		= s3c2410_spigpio_resume,
-        .driver		= {
-		.name	= "spi_s3c24xx_gpio",
-		.owner	= THIS_MODULE,
-        },
-};
-
-static int __init s3c2410_spigpio_init(void)
-{
-        return platform_driver_register(&s3c2410_spigpio_drv);
-}
-
-static void __exit s3c2410_spigpio_exit(void)
-{
-        platform_driver_unregister(&s3c2410_spigpio_drv);
-}
-
-module_init(s3c2410_spigpio_init);
-module_exit(s3c2410_spigpio_exit);
-
-MODULE_DESCRIPTION("S3C24XX SPI Driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index d9fd86211365..830adbed1d7a 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -1,5 +1,5 @@
 /*
- * spidev.c -- simple synchronous userspace interface to SPI devices
+ * Simple synchronous userspace interface to SPI devices
  *
  * Copyright (C) 2006 SWAPP
  *	Andrea Paterniani <a.paterniani@swapp-eng.it>