[linux-yocto] [PATCH 1/2] valleyisland-io: add patch for Baytrail SPI support

Darren Hart dvhart at linux.intel.com
Tue Dec 10 11:13:49 PST 2013


On Tue, 2013-12-10 at 12:55 -0500, Bruce Ashfield wrote:
> On 13-12-10 01:10 AM, Chang, Rebecca Swee Fun wrote:
> > Hi Bruce,
> >
> > Regarding the issue to pointed out, it came from Kernel version 3.10. See following:
> >
> > author	Kees Cook <keescook at chromium.org>	2013-01-17 02:53:55 (GMT)
> > committer	 Greg Kroah-Hartman <gregkh at linuxfoundation.org>	2013-01-21 22:52:45 (GMT)
> > commit	6d1f56aa5149082bb0ce6dd8d47e51a1013a206d (patch)
> > tree	25fb9f459880f31e893d6938e937ad41c952ca75
> > parent	2a570a4917cca818bc69d0789483e0a9ace79477 (diff)
> >
> > drivers/spi: remove depends on CONFIG_EXPERIMENTAL
> > The CONFIG_EXPERIMENTAL config item has not carried much meaning for a
> > while now and is almost always enabled by default. As agreed during the
> > Linux kernel summit, remove it from any "depends on" lines in Kconfigs.
> >
> > CC: Grant Likely <grant.likely at secretlab.ca>
> > Signed-off-by: Kees Cook <keescook at chromium.org>
> > Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
> >
> > Can we proceed by pulling in all the pull requests that I submitted? Or do I need to
> > resubmit this specific pull request by segregate this piece of code out?
> 
> We are really taking a lot of shortcuts with this series, and really,
> we have to have some standards.
> 
> This is a clear cut commit from the upstream kernel, and it should not
> be combined with the addition of the new driver.

Hi Rebecca,

When you are working with a backport, it is necessary backport each
dependent patch individually. This preserves history, attribution, and
bisection ability, as well as simplifying future backports which may
have similar dependencies.

What I do here is attempt to "git cherry-pick" the patch I want. If it
fails, I use "git status" to see which files the commit conflicted with,
then use "git log -- file" for each conflicting file *in mainline* and
compare that with "git log -- file" in your local tree. Consider each
missing patch in your local tree as a dependent patch for the desired
backport. Use "git cherry-pick" for each of these until your desired
patch applies with minimal changes. Often this can be done without any
manual merges at all.

This is the required approach for working with linux-stable as well as
linux-ltsi, it also applies here to linux-yocto. If you would like some
help with a particular patch, please let me know, I'll be happy to walk
you through it.

Thanks,

Darren

> 
> So in this case, I can process the other requests, but this series needs
> to be split into separate patches and resent.
> 
> Bruce
> 
> >
> > Thanks.
> >
> > Rebecca
> >
> >> -----Original Message-----
> >> From: Bruce Ashfield [mailto:bruce.ashfield at windriver.com]
> >> Sent: 09 December, 2013 10:27 PM
> >> To: Chang, Rebecca Swee Fun; linux-yocto at yoctoproject.org; Darren Hart
> >> Subject: Re: [linux-yocto] [PATCH 1/2] valleyisland-io: add patch for Baytrail
> >> SPI support
> >>
> >> On 13-12-09 05:08 AM, rebecca.swee.fun.chang at intel.com wrote:
> >>> From: "Chang, Rebecca Swee Fun" <rebecca.swee.fun.chang at intel.com>
> >>>
> >>> spi-pxa2xx: Baytrail has 1 SPI controller which can be PCI and ACPI
> >>> enumerated.
> >>>
> >>> Signed-off-by: Chang, Rebecca Swee Fun
> >> <rebecca.swee.fun.chang at intel.com>
> >>> ---
> >>>    ...add-support-for-Intel-Baytrail-SPI-contro.patch | 3278
> >> ++++++++++++++++++++
> >>>    1 file changed, 3278 insertions(+)
> >>>    create mode 100644 meta/cfg/kernel-cache/features/valleyisland-
> >> io/0007-spi-pxa2xx-add-support-for-Intel-Baytrail-SPI-contro.patch
> >>>
> >>> diff --git a/meta/cfg/kernel-cache/features/valleyisland-io/0007-spi-
> >> pxa2xx-add-support-for-Intel-Baytrail-SPI-contro.patch b/meta/cfg/kernel-
> >> cache/features/valleyisland-io/0007-spi-pxa2xx-add-support-for-Intel-
> >> Baytrail-SPI-contro.patch
> >>> new file mode 100644
> >>> index 0000000..46902fb
> >>> --- /dev/null
> >>> +++ b/meta/cfg/kernel-cache/features/valleyisland-io/0007-spi-pxa2xx-
> >> add-support-for-Intel-Baytrail-SPI-contro.patch
> >>> @@ -0,0 +1,3278 @@
> >>> +spi-pxa2xx: add support for Intel Valley Island SPI controller
> >>> +
> >>> +Intel Valley Island has 1 SPI controller which can be PCI or ACPI
> >> enumerated.
> >>> +
> >>> +Signed-off-by: Chang, Rebecca Swee Fun
> >> <rebecca.swee.fun.chang at intel.com>
> >>> +---
> >>> + drivers/spi/Kconfig             |   35 +-
> >>> + drivers/spi/Makefile            |    5 +-
> >>> + drivers/spi/spi-pxa2xx-dma.c    |  392 ++++++++++++++
> >>> + drivers/spi/spi-pxa2xx-pci.c    |  210 +++-----
> >>> + drivers/spi/spi-pxa2xx-pxadma.c |  490 +++++++++++++++++
> >>> + drivers/spi/spi-pxa2xx.c        | 1118 +++++++++++++--------------------------
> >>> + drivers/spi/spi-pxa2xx.h        |  221 ++++++++
> >>> + include/linux/pxa2xx_ssp.h      |   18 +
> >>> + include/linux/spi/pxa2xx_spi.h  |  108 +---
> >>> + 9 files changed, 1604 insertions(+), 993 deletions(-)
> >>> + create mode 100644 drivers/spi/spi-pxa2xx-dma.c
> >>> + create mode 100644 drivers/spi/spi-pxa2xx-pxadma.c
> >>> + create mode 100644 drivers/spi/spi-pxa2xx.h
> >>> +
> >>> +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> >>> +index 2e188e1..bc1445e 100644
> >>> +--- a/drivers/spi/Kconfig
> >>> ++++ b/drivers/spi/Kconfig
> >>> +@@ -88,7 +88,7 @@ config SPI_BFIN_SPORT
> >>> +
> >>> + config SPI_AU1550
> >>> + 	tristate "Au1550/Au1200/Au1300 SPI Controller"
> >>> +-	depends on MIPS_ALCHEMY && EXPERIMENTAL
> >>> ++	depends on MIPS_ALCHEMY
> >>
> >> This is the problem with these sort of backports. Clearly the source of
> >> this patch is from a tree without the EXPERIMENTAL Kconfig, hence why
> >> it is being removed from all of the SPI drivers. But that isn't something
> >> a patch that is *adding* support for a particular platform should do.
> >>
> >> Temporary/transition/in progress or not, we need to get these patches
> >> to at least indicate what development tree / upstream kernel they
> >> come from, so I can sort out what is new, versus the development intent
> >> of the patch.
> >>
> >> Bruce
> >>
> >>> + 	select SPI_BITBANG
> >>> + 	help
> >>> + 	  If you say yes to this option, support will be included for the
> >>> +@@ -188,7 +188,7 @@ config SPI_IMX
> >>> +
> >>> + config SPI_LM70_LLP
> >>> + 	tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
> >>> +-	depends on PARPORT && EXPERIMENTAL
> >>> ++	depends on PARPORT
> >>> + 	select SPI_BITBANG
> >>> + 	help
> >>> + 	  This driver supports the NS LM70 LLP Evaluation Board,
> >>> +@@ -204,7 +204,7 @@ config SPI_MPC52xx
> >>> +
> >>> + config SPI_MPC52xx_PSC
> >>> + 	tristate "Freescale MPC52xx PSC SPI controller"
> >>> +-	depends on PPC_MPC52xx && EXPERIMENTAL
> >>> ++	depends on PPC_MPC52xx
> >>> + 	help
> >>> + 	  This enables using the Freescale MPC52xx Programmable Serial
> >>> + 	  Controller in master SPI mode.
> >>> +@@ -273,8 +273,8 @@ config SPI_OMAP_100K
> >>> + 	  OMAP SPI 100K master controller for omap7xx boards.
> >>> +
> >>> + config SPI_ORION
> >>> +-	tristate "Orion SPI master (EXPERIMENTAL)"
> >>> +-	depends on PLAT_ORION && EXPERIMENTAL
> >>> ++	tristate "Orion SPI master"
> >>> ++	depends on PLAT_ORION
> >>> + 	help
> >>> + 	  This enables using the SPI master controller on the Orion chips.
> >>> +
> >>> +@@ -297,9 +297,20 @@ config SPI_PPC4xx
> >>> + 	help
> >>> + 	  This selects a driver for the PPC4xx SPI Controller.
> >>> +
> >>> ++config SPI_PXA2XX_PXADMA
> >>> ++	bool "PXA2xx SSP legacy PXA DMA API support"
> >>> ++	depends on SPI_PXA2XX && ARCH_PXA
> >>> ++	help
> >>> ++	  Enable PXA private legacy DMA API support. Note that this is
> >>> ++	  deprecated in favor of generic DMA engine API.
> >>> ++
> >>> ++config SPI_PXA2XX_DMA
> >>> ++	def_bool y
> >>> ++	depends on SPI_PXA2XX && !SPI_PXA2XX_PXADMA
> >>> ++
> >>> + config SPI_PXA2XX
> >>> + 	tristate "PXA2xx SSP SPI master"
> >>> +-	depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
> >>> ++	depends on ARCH_PXA || PCI || ACPI
> >>> + 	select PXA_SSP if ARCH_PXA
> >>> + 	help
> >>> + 	  This enables using a PXA2xx or Sodaville SSP port as a SPI master
> >>> +@@ -307,7 +318,10 @@ config SPI_PXA2XX
> >>> + 	  additional documentation can be found a
> >> Documentation/spi/pxa2xx.
> >>> +
> >>> + config SPI_PXA2XX_PCI
> >>> +-	def_bool SPI_PXA2XX && X86_32 && PCI
> >>> ++	tristate "PCI glue for PXA2xx SSP SPI master"
> >>> ++	depends on SPI_PXA2XX && PCI
> >>> ++	help
> >>> ++	  This enables using PXA2xx SPI controller via PCI interface.
> >>> +
> >>> + config SPI_RSPI
> >>> + 	tristate "Renesas RSPI controller"
> >>> +@@ -317,7 +331,7 @@ config SPI_RSPI
> >>> +
> >>> + config SPI_S3C24XX
> >>> + 	tristate "Samsung S3C24XX series SPI"
> >>> +-	depends on ARCH_S3C24XX && EXPERIMENTAL
> >>> ++	depends on ARCH_S3C24XX
> >>> + 	select SPI_BITBANG
> >>> + 	help
> >>> + 	  SPI driver for Samsung S3C24XX series ARM SoCs
> >>> +@@ -432,7 +446,7 @@ config SPI_XCOMM
> >>> +
> >>> + config SPI_XILINX
> >>> + 	tristate "Xilinx SPI controller common module"
> >>> +-	depends on HAS_IOMEM && EXPERIMENTAL
> >>> ++	depends on HAS_IOMEM
> >>> + 	select SPI_BITBANG
> >>> + 	help
> >>> + 	  This exposes the SPI controller IP from the Xilinx EDK.
> >>> +@@ -444,7 +458,7 @@ config SPI_XILINX
> >>> +
> >>> + config SPI_NUC900
> >>> + 	tristate "Nuvoton NUC900 series SPI"
> >>> +-	depends on ARCH_W90X900 && EXPERIMENTAL
> >>> ++	depends on ARCH_W90X900
> >>> + 	select SPI_BITBANG
> >>> + 	help
> >>> + 	  SPI driver for Nuvoton NUC900 series ARM SoCs
> >>> +@@ -478,7 +492,6 @@ comment "SPI Protocol Masters"
> >>> +
> >>> + config SPI_SPIDEV
> >>> + 	tristate "User mode SPI device driver support"
> >>> +-	depends on EXPERIMENTAL
> >>> + 	help
> >>> + 	  This supports user mode SPI protocol drivers.
> >>> +
> >>> +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> >>> +index 64e970b..e53c309 100644
> >>> +--- a/drivers/spi/Makefile
> >>> ++++ b/drivers/spi/Makefile
> >>> +@@ -47,7 +47,10 @@ 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
> >>> ++spi-pxa2xx-platform-objs		:= spi-pxa2xx.o
> >>> ++spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA)	+= spi-
> >> pxa2xx-pxadma.o
> >>> ++spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA)	+= spi-
> >> pxa2xx-dma.o
> >>> ++obj-$(CONFIG_SPI_PXA2XX)		+= spi-pxa2xx-platform.o
> >>> + obj-$(CONFIG_SPI_PXA2XX_PCI)		+= spi-pxa2xx-pci.o
> >>> + obj-$(CONFIG_SPI_RSPI)			+= spi-rspi.o
> >>> + obj-$(CONFIG_SPI_S3C24XX)		+= spi-s3c24xx-hw.o
> >>> +diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c
> >>> +new file mode 100644
> >>> +index 0000000..03478c2
> >>> +--- /dev/null
> >>> ++++ b/drivers/spi/spi-pxa2xx-dma.c
> >>> +@@ -0,0 +1,392 @@
> >>> ++/*
> >>> ++ * PXA2xx SPI DMA engine support.
> >>> ++ *
> >>> ++ * Copyright (C) 2013, Intel Corporation
> >>> ++ * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
> >>> ++ *
> >>> ++ * 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/init.h>
> >>> ++#include <linux/device.h>
> >>> ++#include <linux/dma-mapping.h>
> >>> ++#include <linux/dmaengine.h>
> >>> ++#include <linux/pxa2xx_ssp.h>
> >>> ++#include <linux/scatterlist.h>
> >>> ++#include <linux/sizes.h>
> >>> ++#include <linux/spi/spi.h>
> >>> ++#include <linux/spi/pxa2xx_spi.h>
> >>> ++
> >>> ++#include "spi-pxa2xx.h"
> >>> ++
> >>> ++static int pxa2xx_spi_map_dma_buffer(struct driver_data *drv_data,
> >>> ++				     enum dma_data_direction dir)
> >>> ++{
> >>> ++	int i, nents, len = drv_data->len;
> >>> ++	struct scatterlist *sg;
> >>> ++	struct device *dmadev;
> >>> ++	struct sg_table *sgt;
> >>> ++	void *buf, *pbuf;
> >>> ++
> >>> ++	/*
> >>> ++	 * Some DMA controllers have problems transferring buffers that are
> >>> ++	 * not multiple of 4 bytes. So we truncate the transfer so that it
> >>> ++	 * is suitable for such controllers, and handle the trailing bytes
> >>> ++	 * manually after the DMA completes.
> >>> ++	 *
> >>> ++	 * REVISIT: It would be better if this information could be
> >>> ++	 * retrieved directly from the DMA device in a similar way than
> >>> ++	 * ->copy_align etc. is done.
> >>> ++	 */
> >>> ++	len = ALIGN(drv_data->len, 4);
> >>> ++
> >>> ++	if (dir == DMA_TO_DEVICE) {
> >>> ++		dmadev = drv_data->tx_chan->device->dev;
> >>> ++		sgt = &drv_data->tx_sgt;
> >>> ++		buf = drv_data->tx;
> >>> ++		drv_data->tx_map_len = len;
> >>> ++	} else {
> >>> ++		dmadev = drv_data->rx_chan->device->dev;
> >>> ++		sgt = &drv_data->rx_sgt;
> >>> ++		buf = drv_data->rx;
> >>> ++		drv_data->rx_map_len = len;
> >>> ++	}
> >>> ++
> >>> ++	nents = DIV_ROUND_UP(len, SZ_2K);
> >>> ++	if (nents != sgt->nents) {
> >>> ++		int ret;
> >>> ++
> >>> ++		sg_free_table(sgt);
> >>> ++		ret = sg_alloc_table(sgt, nents, GFP_ATOMIC);
> >>> ++		if (ret)
> >>> ++			return ret;
> >>> ++	}
> >>> ++
> >>> ++	pbuf = buf;
> >>> ++	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
> >>> ++		size_t bytes = min_t(size_t, len, SZ_2K);
> >>> ++
> >>> ++		if (buf)
> >>> ++			sg_set_buf(sg, pbuf, bytes);
> >>> ++		else
> >>> ++			sg_set_buf(sg, drv_data->dummy, bytes);
> >>> ++
> >>> ++		pbuf += bytes;
> >>> ++		len -= bytes;
> >>> ++	}
> >>> ++
> >>> ++	nents = dma_map_sg(dmadev, sgt->sgl, sgt->nents, dir);
> >>> ++	if (!nents)
> >>> ++		return -ENOMEM;
> >>> ++
> >>> ++	return nents;
> >>> ++}
> >>> ++
> >>> ++static void pxa2xx_spi_unmap_dma_buffer(struct driver_data
> >> *drv_data,
> >>> ++					enum dma_data_direction dir)
> >>> ++{
> >>> ++	struct device *dmadev;
> >>> ++	struct sg_table *sgt;
> >>> ++
> >>> ++	if (dir == DMA_TO_DEVICE) {
> >>> ++		dmadev = drv_data->tx_chan->device->dev;
> >>> ++		sgt = &drv_data->tx_sgt;
> >>> ++	} else {
> >>> ++		dmadev = drv_data->rx_chan->device->dev;
> >>> ++		sgt = &drv_data->rx_sgt;
> >>> ++	}
> >>> ++
> >>> ++	dma_unmap_sg(dmadev, sgt->sgl, sgt->nents, dir);
> >>> ++}
> >>> ++
> >>> ++static void pxa2xx_spi_unmap_dma_buffers(struct driver_data
> >> *drv_data)
> >>> ++{
> >>> ++	if (!drv_data->dma_mapped)
> >>> ++		return;
> >>> ++
> >>> ++	pxa2xx_spi_unmap_dma_buffer(drv_data, DMA_FROM_DEVICE);
> >>> ++	pxa2xx_spi_unmap_dma_buffer(drv_data, DMA_TO_DEVICE);
> >>> ++
> >>> ++	drv_data->dma_mapped = 0;
> >>> ++}
> >>> ++
> >>> ++static void pxa2xx_spi_dma_transfer_complete(struct driver_data
> >> *drv_data,
> >>> ++					     bool error)
> >>> ++{
> >>> ++	struct spi_message *msg = drv_data->cur_msg;
> >>> ++
> >>> ++	/*
> >>> ++	 * It is possible that one CPU is handling ROR interrupt and other
> >>> ++	 * just gets DMA completion. Calling pump_transfers() twice for the
> >>> ++	 * same transfer leads to problems thus we prevent concurrent calls
> >>> ++	 * by using ->dma_running.
> >>> ++	 */
> >>> ++	if (atomic_dec_and_test(&drv_data->dma_running)) {
> >>> ++		void __iomem *reg = drv_data->ioaddr;
> >>> ++
> >>> ++		/*
> >>> ++		 * If the other CPU is still handling the ROR interrupt we
> >>> ++		 * might not know about the error yet. So we re-check the
> >>> ++		 * ROR bit here before we clear the status register.
> >>> ++		 */
> >>> ++		if (!error) {
> >>> ++			u32 status = read_SSSR(reg) & drv_data->mask_sr;
> >>> ++			error = status & SSSR_ROR;
> >>> ++		}
> >>> ++
> >>> ++		/* Clear status & disable interrupts */
> >>> ++		write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
> >>> ++		write_SSSR_CS(drv_data, drv_data->clear_sr);
> >>> ++		if (!pxa25x_ssp_comp(drv_data))
> >>> ++			write_SSTO(0, reg);
> >>> ++
> >>> ++		if (!error) {
> >>> ++			pxa2xx_spi_unmap_dma_buffers(drv_data);
> >>> ++
> >>> ++			/* Handle the last bytes of unaligned transfer */
> >>> ++			drv_data->tx += drv_data->tx_map_len;
> >>> ++			drv_data->write(drv_data);
> >>> ++
> >>> ++			drv_data->rx += drv_data->rx_map_len;
> >>> ++			drv_data->read(drv_data);
> >>> ++
> >>> ++			msg->actual_length += drv_data->len;
> >>> ++			msg->state = pxa2xx_spi_next_transfer(drv_data);
> >>> ++		} else {
> >>> ++			/* In case we got an error we disable the SSP now */
> >>> ++			write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
> >>> ++
> >>> ++			msg->state = ERROR_STATE;
> >>> ++		}
> >>> ++
> >>> ++		tasklet_schedule(&drv_data->pump_transfers);
> >>> ++	}
> >>> ++}
> >>> ++
> >>> ++static void pxa2xx_spi_dma_callback(void *data)
> >>> ++{
> >>> ++	pxa2xx_spi_dma_transfer_complete(data, false);
> >>> ++}
> >>> ++
> >>> ++static struct dma_async_tx_descriptor *
> >>> ++pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
> >>> ++			   enum dma_transfer_direction dir)
> >>> ++{
> >>> ++	struct pxa2xx_spi_master *pdata = drv_data->master_info;
> >>> ++	struct chip_data *chip = drv_data->cur_chip;
> >>> ++	enum dma_slave_buswidth width;
> >>> ++	struct dma_slave_config cfg;
> >>> ++	struct dma_chan *chan;
> >>> ++	struct sg_table *sgt;
> >>> ++	int nents, ret;
> >>> ++
> >>> ++	switch (drv_data->n_bytes) {
> >>> ++	case 1:
> >>> ++		width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> >>> ++		break;
> >>> ++	case 2:
> >>> ++		width = DMA_SLAVE_BUSWIDTH_2_BYTES;
> >>> ++		break;
> >>> ++	default:
> >>> ++		width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> >>> ++		break;
> >>> ++	}
> >>> ++
> >>> ++	memset(&cfg, 0, sizeof(cfg));
> >>> ++	cfg.direction = dir;
> >>> ++
> >>> ++	if (dir == DMA_MEM_TO_DEV) {
> >>> ++		cfg.dst_addr = drv_data->ssdr_physical;
> >>> ++		cfg.dst_addr_width = width;
> >>> ++		cfg.dst_maxburst = chip->dma_burst_size;
> >>> ++		cfg.slave_id = pdata->tx_slave_id;
> >>> ++
> >>> ++		sgt = &drv_data->tx_sgt;
> >>> ++		nents = drv_data->tx_nents;
> >>> ++		chan = drv_data->tx_chan;
> >>> ++	} else {
> >>> ++		cfg.src_addr = drv_data->ssdr_physical;
> >>> ++		cfg.src_addr_width = width;
> >>> ++		cfg.src_maxburst = chip->dma_burst_size;
> >>> ++		cfg.slave_id = pdata->rx_slave_id;
> >>> ++
> >>> ++		sgt = &drv_data->rx_sgt;
> >>> ++		nents = drv_data->rx_nents;
> >>> ++		chan = drv_data->rx_chan;
> >>> ++	}
> >>> ++
> >>> ++	ret = dmaengine_slave_config(chan, &cfg);
> >>> ++	if (ret) {
> >>> ++		dev_warn(&drv_data->pdev->dev, "DMA slave config
> >> failed\n");
> >>> ++		return NULL;
> >>> ++	}
> >>> ++
> >>> ++	return dmaengine_prep_slave_sg(chan, sgt->sgl, nents, dir,
> >>> ++				       DMA_PREP_INTERRUPT |
> >> DMA_CTRL_ACK);
> >>> ++}
> >>> ++
> >>> ++static bool pxa2xx_spi_dma_filter(struct dma_chan *chan, void *param)
> >>> ++{
> >>> ++	const struct pxa2xx_spi_master *pdata = param;
> >>> ++
> >>> ++	return chan->chan_id == pdata->tx_chan_id ||
> >>> ++	       chan->chan_id == pdata->rx_chan_id;
> >>> ++}
> >>> ++
> >>> ++bool pxa2xx_spi_dma_is_possible(size_t len)
> >>> ++{
> >>> ++	return len <= MAX_DMA_LEN;
> >>> ++}
> >>> ++
> >>> ++int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
> >>> ++{
> >>> ++	const struct chip_data *chip = drv_data->cur_chip;
> >>> ++	int ret;
> >>> ++
> >>> ++	if (!chip->enable_dma)
> >>> ++		return 0;
> >>> ++
> >>> ++	/* Don't bother with DMA if we can't do even a single burst */
> >>> ++	if (drv_data->len < chip->dma_burst_size)
> >>> ++		return 0;
> >>> ++
> >>> ++	ret = pxa2xx_spi_map_dma_buffer(drv_data, DMA_TO_DEVICE);
> >>> ++	if (ret <= 0) {
> >>> ++		dev_warn(&drv_data->pdev->dev, "failed to DMA map
> >> TX\n");
> >>> ++		return 0;
> >>> ++	}
> >>> ++
> >>> ++	drv_data->tx_nents = ret;
> >>> ++
> >>> ++	ret = pxa2xx_spi_map_dma_buffer(drv_data, DMA_FROM_DEVICE);
> >>> ++	if (ret <= 0) {
> >>> ++		pxa2xx_spi_unmap_dma_buffer(drv_data,
> >> DMA_TO_DEVICE);
> >>> ++		dev_warn(&drv_data->pdev->dev, "failed to DMA map
> >> RX\n");
> >>> ++		return 0;
> >>> ++	}
> >>> ++
> >>> ++	drv_data->rx_nents = ret;
> >>> ++	return 1;
> >>> ++}
> >>> ++
> >>> ++irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
> >>> ++{
> >>> ++	u32 status;
> >>> ++
> >>> ++	status = read_SSSR(drv_data->ioaddr) & drv_data->mask_sr;
> >>> ++	if (status & SSSR_ROR) {
> >>> ++		dev_err(&drv_data->pdev->dev, "FIFO overrun\n");
> >>> ++
> >>> ++		dmaengine_terminate_all(drv_data->rx_chan);
> >>> ++		dmaengine_terminate_all(drv_data->tx_chan);
> >>> ++
> >>> ++		pxa2xx_spi_dma_transfer_complete(drv_data, true);
> >>> ++		return IRQ_HANDLED;
> >>> ++	}
> >>> ++
> >>> ++	return IRQ_NONE;
> >>> ++}
> >>> ++
> >>> ++int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32
> >> dma_burst)
> >>> ++{
> >>> ++	struct dma_async_tx_descriptor *tx_desc, *rx_desc;
> >>> ++
> >>> ++	tx_desc = pxa2xx_spi_dma_prepare_one(drv_data,
> >> DMA_MEM_TO_DEV);
> >>> ++	if (!tx_desc) {
> >>> ++		dev_err(&drv_data->pdev->dev,
> >>> ++			"failed to get DMA TX descriptor\n");
> >>> ++		return -EBUSY;
> >>> ++	}
> >>> ++
> >>> ++	rx_desc = pxa2xx_spi_dma_prepare_one(drv_data,
> >> DMA_DEV_TO_MEM);
> >>> ++	if (!rx_desc) {
> >>> ++		dev_err(&drv_data->pdev->dev,
> >>> ++			"failed to get DMA RX descriptor\n");
> >>> ++		return -EBUSY;
> >>> ++	}
> >>> ++
> >>> ++	/* We are ready when RX completes */
> >>> ++	rx_desc->callback = pxa2xx_spi_dma_callback;
> >>> ++	rx_desc->callback_param = drv_data;
> >>> ++
> >>> ++	dmaengine_submit(rx_desc);
> >>> ++	dmaengine_submit(tx_desc);
> >>> ++	return 0;
> >>> ++}
> >>> ++
> >>> ++void pxa2xx_spi_dma_start(struct driver_data *drv_data)
> >>> ++{
> >>> ++	dma_async_issue_pending(drv_data->rx_chan);
> >>> ++	dma_async_issue_pending(drv_data->tx_chan);
> >>> ++
> >>> ++	atomic_set(&drv_data->dma_running, 1);
> >>> ++}
> >>> ++
> >>> ++int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
> >>> ++{
> >>> ++	struct pxa2xx_spi_master *pdata = drv_data->master_info;
> >>> ++	dma_cap_mask_t mask;
> >>> ++
> >>> ++	dma_cap_zero(mask);
> >>> ++	dma_cap_set(DMA_SLAVE, mask);
> >>> ++
> >>> ++	drv_data->dummy = devm_kzalloc(&drv_data->pdev->dev, SZ_2K,
> >> GFP_KERNEL);
> >>> ++	if (!drv_data->dummy)
> >>> ++		return -ENOMEM;
> >>> ++
> >>> ++	drv_data->tx_chan = dma_request_channel(mask,
> >> pxa2xx_spi_dma_filter,
> >>> ++						pdata);
> >>> ++	if (!drv_data->tx_chan)
> >>> ++		return -ENODEV;
> >>> ++
> >>> ++	drv_data->rx_chan = dma_request_channel(mask,
> >> pxa2xx_spi_dma_filter,
> >>> ++						pdata);
> >>> ++	if (!drv_data->rx_chan) {
> >>> ++		dma_release_channel(drv_data->tx_chan);
> >>> ++		drv_data->tx_chan = NULL;
> >>> ++		return -ENODEV;
> >>> ++	}
> >>> ++
> >>> ++	return 0;
> >>> ++}
> >>> ++
> >>> ++void pxa2xx_spi_dma_release(struct driver_data *drv_data)
> >>> ++{
> >>> ++	if (drv_data->rx_chan) {
> >>> ++		dmaengine_terminate_all(drv_data->rx_chan);
> >>> ++		dma_release_channel(drv_data->rx_chan);
> >>> ++		sg_free_table(&drv_data->rx_sgt);
> >>> ++		drv_data->rx_chan = NULL;
> >>> ++	}
> >>> ++	if (drv_data->tx_chan) {
> >>> ++		dmaengine_terminate_all(drv_data->tx_chan);
> >>> ++		dma_release_channel(drv_data->tx_chan);
> >>> ++		sg_free_table(&drv_data->tx_sgt);
> >>> ++		drv_data->tx_chan = NULL;
> >>> ++	}
> >>> ++}
> >>> ++
> >>> ++void pxa2xx_spi_dma_resume(struct driver_data *drv_data)
> >>> ++{
> >>> ++}
> >>> ++
> >>> ++int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
> >>> ++					   struct spi_device *spi,
> >>> ++					   u8 bits_per_word, u32 *burst_code,
> >>> ++					   u32 *threshold)
> >>> ++{
> >>> ++	struct pxa2xx_spi_chip *chip_info = spi->controller_data;
> >>> ++
> >>> ++	/*
> >>> ++	 * If the DMA burst size is given in chip_info we use that,
> >>> ++	 * otherwise we use the default. Also we use the default FIFO
> >>> ++	 * thresholds for now.
> >>> ++	 */
> >>> ++	*burst_code = chip_info ? chip_info->dma_burst_size : 32;
> >>> ++	*threshold = SSCR1_RxTresh(RX_THRESH_DFLT)
> >>> ++		   | SSCR1_TxTresh(TX_THRESH_DFLT);
> >>> ++
> >>> ++	return 0;
> >>> ++}
> >>> +diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
> >>> +index cf95587..a64d54e 100644
> >>> +--- a/drivers/spi/spi-pxa2xx-pci.c
> >>> ++++ b/drivers/spi/spi-pxa2xx-pci.c
> >>> +@@ -7,165 +7,131 @@
> >>> + #include <linux/of_device.h>
> >>> + #include <linux/module.h>
> >>> + #include <linux/spi/pxa2xx_spi.h>
> >>> ++#include <linux/clk.h>
> >>> +
> >>> +-struct ce4100_info {
> >>> +-	struct ssp_device ssp;
> >>> +-	struct platform_device *spi_pdev;
> >>> +-};
> >>> +-
> >>> +-static DEFINE_MUTEX(ssp_lock);
> >>> +-static LIST_HEAD(ssp_list);
> >>> +-
> >>> +-struct ssp_device *pxa_ssp_request(int port, const char *label)
> >>> +-{
> >>> +-	struct ssp_device *ssp = NULL;
> >>> +-
> >>> +-	mutex_lock(&ssp_lock);
> >>> +-
> >>> +-	list_for_each_entry(ssp, &ssp_list, node) {
> >>> +-		if (ssp->port_id == port && ssp->use_count == 0) {
> >>> +-			ssp->use_count++;
> >>> +-			ssp->label = label;
> >>> +-			break;
> >>> +-		}
> >>> +-	}
> >>> ++static bool use_dma = 1;
> >>> ++module_param(use_dma, bool, 0);
> >>> ++MODULE_PARM_DESC(use_dma, "use_dma=1 (enable
> >> DMA)/use_dma=0(disable DMA)");
> >>> +
> >>> +-	mutex_unlock(&ssp_lock);
> >>> +-
> >>> +-	if (&ssp->node == &ssp_list)
> >>> +-		return NULL;
> >>> ++enum {
> >>> ++        PORT_CE4100,
> >>> ++        PORT_BYT,
> >>> ++};
> >>> +
> >>> +-	return ssp;
> >>> +-}
> >>> +-EXPORT_SYMBOL_GPL(pxa_ssp_request);
> >>> ++struct pxa2xx_spi_pci_config {
> >>> ++        enum pxa_ssp_type type;
> >>> ++        int num_cs;
> >>> ++        int bus_num;
> >>> ++        int tx_slave_id;
> >>> ++        int tx_chan_id;
> >>> ++        int rx_slave_id;
> >>> ++        int rx_chan_id;
> >>> ++};
> >>> +
> >>> +-void pxa_ssp_free(struct ssp_device *ssp)
> >>> +-{
> >>> +-	mutex_lock(&ssp_lock);
> >>> +-	if (ssp->use_count) {
> >>> +-		ssp->use_count--;
> >>> +-		ssp->label = NULL;
> >>> +-	} else
> >>> +-		dev_err(&ssp->pdev->dev, "device already free\n");
> >>> +-	mutex_unlock(&ssp_lock);
> >>> +-}
> >>> +-EXPORT_SYMBOL_GPL(pxa_ssp_free);
> >>> ++static struct pxa2xx_spi_pci_config spi_pci_configs[] = {
> >>> ++        [PORT_CE4100] = {
> >>> ++                .type = PXA25x_SSP,
> >>> ++                .num_cs =  -1,
> >>> ++                .bus_num = -1,
> >>> ++		.tx_slave_id = -1,
> >>> ++		.tx_chan_id = -1,
> >>> ++		.rx_slave_id = -1,
> >>> ++		.rx_chan_id = -1,
> >>> ++        },
> >>> ++        [PORT_BYT] = {
> >>> ++                .type = LPSS_SSP,
> >>> ++                .num_cs = 1,
> >>> ++		.bus_num = 0,
> >>> ++		.tx_slave_id = 0,
> >>> ++		.tx_chan_id = 0,
> >>> ++		.rx_slave_id = 1,
> >>> ++		.rx_chan_id = 1,
> >>> ++        },
> >>> ++};
> >>> +
> >>> +-static int ce4100_spi_probe(struct pci_dev *dev,
> >>> ++static int pxa2xx_spi_probe(struct pci_dev *dev,
> >>> + 		const struct pci_device_id *ent)
> >>> + {
> >>> ++	struct pxa2xx_spi_pci_config *c;
> >>> ++	struct platform_device_info pi;
> >>> + 	int ret;
> >>> +-	resource_size_t phys_beg;
> >>> +-	resource_size_t phys_len;
> >>> +-	struct ce4100_info *spi_info;
> >>> + 	struct platform_device *pdev;
> >>> + 	struct pxa2xx_spi_master spi_pdata;
> >>> + 	struct ssp_device *ssp;
> >>> +
> >>> +-	ret = pci_enable_device(dev);
> >>> ++	ret = pcim_enable_device(dev);
> >>> + 	if (ret)
> >>> + 		return ret;
> >>> +
> >>> +-	phys_beg = pci_resource_start(dev, 0);
> >>> +-	phys_len = pci_resource_len(dev, 0);
> >>> +-
> >>> +-	if (!request_mem_region(phys_beg, phys_len,
> >>> +-				"CE4100 SPI")) {
> >>> +-		dev_err(&dev->dev, "Can't request register space.\n");
> >>> +-		ret = -EBUSY;
> >>> ++	ret = pcim_iomap_regions(dev, 1 << 0, "PXA2xx SPI");
> >>> ++	if (ret)
> >>> + 		return ret;
> >>> +-	}
> >>> +
> >>> +-	pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
> >>> +-	spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
> >>> +-	if (!pdev || !spi_info ) {
> >>> +-		ret = -ENOMEM;
> >>> +-		goto err_nomem;
> >>> +-	}
> >>> +-	memset(&spi_pdata, 0, sizeof(spi_pdata));
> >>> +-	spi_pdata.num_chipselect = dev->devfn;
> >>> +
> >>> +-	ret = platform_device_add_data(pdev, &spi_pdata,
> >> sizeof(spi_pdata));
> >>> +-	if (ret)
> >>> +-		goto err_nomem;
> >>> ++	c = &spi_pci_configs[ent->driver_data];
> >>> +
> >>> +-	pdev->dev.parent = &dev->dev;
> >>> +-	pdev->dev.of_node = dev->dev.of_node;
> >>> +-	ssp = &spi_info->ssp;
> >>> ++	memset(&spi_pdata, 0, sizeof(spi_pdata));
> >>> ++	spi_pdata.num_chipselect = (c->num_cs >= 0) ? c->num_cs : dev-
> >>> devfn;
> >>> ++	spi_pdata.tx_slave_id = c->tx_slave_id;
> >>> ++	spi_pdata.tx_chan_id = c->tx_chan_id;
> >>> ++	spi_pdata.rx_slave_id = c->rx_slave_id;
> >>> ++	spi_pdata.rx_chan_id = c->rx_chan_id;
> >>> ++	if (use_dma)
> >>> ++		spi_pdata.enable_dma = c->rx_slave_id >= 0 && c-
> >>> tx_slave_id >= 0;
> >>> ++
> >>> ++	ssp = &spi_pdata.ssp;
> >>> + 	ssp->phys_base = pci_resource_start(dev, 0);
> >>> +-	ssp->mmio_base = ioremap(phys_beg, phys_len);
> >>> ++	ssp->mmio_base = pcim_iomap_table(dev)[0];
> >>> + 	if (!ssp->mmio_base) {
> >>> +-		dev_err(&pdev->dev, "failed to ioremap() registers\n");
> >>> +-		ret = -EIO;
> >>> +-		goto err_nomem;
> >>> ++		dev_err(&dev->dev, "failed to ioremap() registers\n");
> >>> ++		return -EIO;
> >>> + 	}
> >>> ++	ssp->clk =  devm_clk_get(&dev->dev, NULL);
> >>> + 	ssp->irq = dev->irq;
> >>> +-	ssp->port_id = pdev->id;
> >>> +-	ssp->type = PXA25x_SSP;
> >>> ++	ssp->port_id = (c->bus_num >= 0) ? c->bus_num : dev->devfn;
> >>> ++	ssp->type = c->type;
> >>> +
> >>> +-	mutex_lock(&ssp_lock);
> >>> +-	list_add(&ssp->node, &ssp_list);
> >>> +-	mutex_unlock(&ssp_lock);
> >>> ++	memset(&pi, 0, sizeof(pi));
> >>> ++	pi.parent = &dev->dev;
> >>> ++	pi.name = "pxa2xx-spi";
> >>> ++	pi.id = ssp->port_id;
> >>> ++	pi.data = &spi_pdata;
> >>> ++	pi.size_data = sizeof(spi_pdata);
> >>> +
> >>> +-	pci_set_drvdata(dev, spi_info);
> >>> ++	pdev = platform_device_register_full(&pi);
> >>> ++	if (!pdev)
> >>> ++		return -ENOMEM;
> >>> +
> >>> +-	ret = platform_device_add(pdev);
> >>> +-	if (ret)
> >>> +-		goto err_dev_add;
> >>> +-
> >>> +-	return ret;
> >>> +-
> >>> +-err_dev_add:
> >>> +-	pci_set_drvdata(dev, NULL);
> >>> +-	mutex_lock(&ssp_lock);
> >>> +-	list_del(&ssp->node);
> >>> +-	mutex_unlock(&ssp_lock);
> >>> +-	iounmap(ssp->mmio_base);
> >>> +-
> >>> +-err_nomem:
> >>> +-	release_mem_region(phys_beg, phys_len);
> >>> +-	platform_device_put(pdev);
> >>> +-	kfree(spi_info);
> >>> +-	return ret;
> >>> ++	pci_set_drvdata(dev, pdev);
> >>> ++
> >>> ++	return 0;
> >>> + }
> >>> +
> >>> +-static void ce4100_spi_remove(struct pci_dev *dev)
> >>> ++static void pxa2xx_spi_remove(struct pci_dev *dev)
> >>> + {
> >>> +-	struct ce4100_info *spi_info;
> >>> +-	struct ssp_device *ssp;
> >>> +-
> >>> +-	spi_info = pci_get_drvdata(dev);
> >>> +-	ssp = &spi_info->ssp;
> >>> +-	platform_device_unregister(spi_info->spi_pdev);
> >>> +-
> >>> +-	iounmap(ssp->mmio_base);
> >>> +-	release_mem_region(pci_resource_start(dev, 0),
> >>> +-			pci_resource_len(dev, 0));
> >>> +-
> >>> +-	mutex_lock(&ssp_lock);
> >>> +-	list_del(&ssp->node);
> >>> +-	mutex_unlock(&ssp_lock);
> >>> ++	struct platform_device *pdev = pci_get_drvdata(dev);
> >>> +
> >>> +-	pci_set_drvdata(dev, NULL);
> >>> +-	pci_disable_device(dev);
> >>> +-	kfree(spi_info);
> >>> ++	platform_device_unregister(pdev);
> >>> + }
> >>> +
> >>> +-static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
> >>> +-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
> >>> ++static DEFINE_PCI_DEVICE_TABLE(pxa2xx_spi_devices) = {
> >>> ++	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a),
> >>> ++	  .driver_data =  PORT_CE4100 },
> >>> ++	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f0e),
> >>> ++	  .driver_data = PORT_BYT },
> >>> + 	{ },
> >>> + };
> >>> +-MODULE_DEVICE_TABLE(pci, ce4100_spi_devices);
> >>> ++MODULE_DEVICE_TABLE(pci, pxa2xx_spi_devices);
> >>> +
> >>> +-static struct pci_driver ce4100_spi_driver = {
> >>> +-	.name           = "ce4100_spi",
> >>> +-	.id_table       = ce4100_spi_devices,
> >>> +-	.probe          = ce4100_spi_probe,
> >>> +-	.remove         = ce4100_spi_remove,
> >>> ++static struct pci_driver pxa2xx_spi_driver = {
> >>> ++	.name           = "pxa2xx_spi",
> >>> ++	.id_table       = pxa2xx_spi_devices,
> >>> ++	.probe          = pxa2xx_spi_probe,
> >>> ++	.remove         = pxa2xx_spi_remove,
> >>> + };
> >>> +
> >>> +-module_pci_driver(ce4100_spi_driver);
> >>> ++module_pci_driver(pxa2xx_spi_driver);
> >>> +
> >>> +-MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver");
> >>> ++MODULE_DESCRIPTION("PCI-SPI glue code for PXA's driver");
> >>> + MODULE_LICENSE("GPL v2");
> >>> + MODULE_AUTHOR("Sebastian Andrzej Siewior
> >> <bigeasy at linutronix.de>");
> >>> +diff --git a/drivers/spi/spi-pxa2xx-pxadma.c b/drivers/spi/spi-pxa2xx-
> >> pxadma.c
> >>> +new file mode 100644
> >>> +index 0000000..2916efc
> >>> +--- /dev/null
> >>> ++++ b/drivers/spi/spi-pxa2xx-pxadma.c
> >>> +@@ -0,0 +1,490 @@
> >>> ++/*
> >>> ++ * PXA2xx SPI private DMA support.
> >>> ++ *
> >>> ++ * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
> >>> ++ *
> >>> ++ * This program is free software; you can redistribute it and/or modify
> >>> ++ * it under the terms of the GNU General Public License as published by
> >>> ++ * the Free Software Foundation; either version 2 of the License, or
> >>> ++ * (at your option) any later version.
> >>> ++ *
> >>> ++ * This program is distributed in the hope that it will be useful,
> >>> ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >>> ++ * GNU General Public License for more details.
> >>> ++ *
> >>> ++ * You should have received a copy of the GNU General Public License
> >>> ++ * along with this program; if not, write to the Free Software
> >>> ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> >>> ++ */
> >>> ++
> >>> ++#include <linux/init.h>
> >>> ++#include <linux/delay.h>
> >>> ++#include <linux/device.h>
> >>> ++#include <linux/dma-mapping.h>
> >>> ++#include <linux/pxa2xx_ssp.h>
> >>> ++#include <linux/spi/spi.h>
> >>> ++#include <linux/spi/pxa2xx_spi.h>
> >>> ++
> >>> ++#include "spi-pxa2xx.h"
> >>> ++
> >>> ++#define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR |
> >> DCSR_BUSERR)
> >>> ++#define RESET_DMA_CHANNEL	(DCSR_NODESC | DMA_INT_MASK)
> >>> ++
> >>> ++bool pxa2xx_spi_dma_is_possible(size_t len)
> >>> ++{
> >>> ++	/* Try to map dma buffer and do a dma transfer if successful, but
> >>> ++	 * only if the length is non-zero and less than MAX_DMA_LEN.
> >>> ++	 *
> >>> ++	 * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
> >>> ++	 * of PIO instead.  Care is needed above because the transfer may
> >>> ++	 * have have been passed with buffers that are already dma mapped.
> >>> ++	 * A zero-length transfer in PIO mode will not try to write/read
> >>> ++	 * to/from the buffers
> >>> ++	 *
> >>> ++	 * REVISIT large transfers are exactly where we most want to be
> >>> ++	 * using DMA.  If this happens much, split those transfers into
> >>> ++	 * multiple DMA segments rather than forcing PIO.
> >>> ++	 */
> >>> ++	return len > 0 && len <= MAX_DMA_LEN;
> >>> ++}
> >>> ++
> >>> ++int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
> >>> ++{
> >>> ++	struct spi_message *msg = drv_data->cur_msg;
> >>> ++	struct device *dev = &msg->spi->dev;
> >>> ++
> >>> ++	if (!drv_data->cur_chip->enable_dma)
> >>> ++		return 0;
> >>> ++
> >>> ++	if (msg->is_dma_mapped)
> >>> ++		return  drv_data->rx_dma && drv_data->tx_dma;
> >>> ++
> >>> ++	if (!IS_DMA_ALIGNED(drv_data->rx)
> >> || !IS_DMA_ALIGNED(drv_data->tx))
> >>> ++		return 0;
> >>> ++
> >>> ++	/* Modify setup if rx buffer is null */
> >>> ++	if (drv_data->rx == NULL) {
> >>> ++		*drv_data->null_dma_buf = 0;
> >>> ++		drv_data->rx = drv_data->null_dma_buf;
> >>> ++		drv_data->rx_map_len = 4;
> >>> ++	} else
> >>> ++		drv_data->rx_map_len = drv_data->len;
> >>> ++
> >>> ++
> >>> ++	/* Modify setup if tx buffer is null */
> >>> ++	if (drv_data->tx == NULL) {
> >>> ++		*drv_data->null_dma_buf = 0;
> >>> ++		drv_data->tx = drv_data->null_dma_buf;
> >>> ++		drv_data->tx_map_len = 4;
> >>> ++	} else
> >>> ++		drv_data->tx_map_len = drv_data->len;
> >>> ++
> >>> ++	/* Stream map the tx buffer. Always do DMA_TO_DEVICE first
> >>> ++	 * so we flush the cache *before* invalidating it, in case
> >>> ++	 * the tx and rx buffers overlap.
> >>> ++	 */
> >>> ++	drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
> >>> ++					drv_data->tx_map_len,
> >> DMA_TO_DEVICE);
> >>> ++	if (dma_mapping_error(dev, drv_data->tx_dma))
> >>> ++		return 0;
> >>> ++
> >>> ++	/* Stream map the rx buffer */
> >>> ++	drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
> >>> ++					drv_data->rx_map_len,
> >> DMA_FROM_DEVICE);
> >>> ++	if (dma_mapping_error(dev, drv_data->rx_dma)) {
> >>> ++		dma_unmap_single(dev, drv_data->tx_dma,
> >>> ++					drv_data->tx_map_len,
> >> DMA_TO_DEVICE);
> >>> ++		return 0;
> >>> ++	}
> >>> ++
> >>> ++	return 1;
> >>> ++}
> >>> ++
> >>> ++static void pxa2xx_spi_unmap_dma_buffers(struct driver_data
> >> *drv_data)
> >>> ++{
> >>> ++	struct device *dev;
> >>> ++
> >>> ++	if (!drv_data->dma_mapped)
> >>> ++		return;
> >>> ++
> >>> ++	if (!drv_data->cur_msg->is_dma_mapped) {
> >>> ++		dev = &drv_data->cur_msg->spi->dev;
> >>> ++		dma_unmap_single(dev, drv_data->rx_dma,
> >>> ++					drv_data->rx_map_len,
> >> DMA_FROM_DEVICE);
> >>> ++		dma_unmap_single(dev, drv_data->tx_dma,
> >>> ++					drv_data->tx_map_len,
> >> DMA_TO_DEVICE);
> >>> ++	}
> >>> ++
> >>> ++	drv_data->dma_mapped = 0;
> >>> ++}
> >>> ++
> >>> ++static int wait_ssp_rx_stall(void const __iomem *ioaddr)
> >>> ++{
> >>> ++	unsigned long limit = loops_per_jiffy << 1;
> >>> ++
> >>> ++	while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
> >>> ++		cpu_relax();
> >>> ++
> >>> ++	return limit;
> >>> ++}
> >>> ++
> >>> ++static int wait_dma_channel_stop(int channel)
> >>> ++{
> >>> ++	unsigned long limit = loops_per_jiffy << 1;
> >>> ++
> >>> ++	while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
> >>> ++		cpu_relax();
> >>> ++
> >>> ++	return limit;
> >>> ++}
> >>> ++
> >>> ++static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data,
> >>> ++				      const char *msg)
> >>> ++{
> >>> ++	void __iomem *reg = drv_data->ioaddr;
> >>> ++
> >>> ++	/* Stop and reset */
> >>> ++	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
> >>> ++	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
> >>> ++	write_SSSR_CS(drv_data, drv_data->clear_sr);
> >>> ++	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
> >>> ++	if (!pxa25x_ssp_comp(drv_data))
> >>> ++		write_SSTO(0, reg);
> >>> ++	pxa2xx_spi_flush(drv_data);
> >>> ++	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
> >>> ++
> >>> ++	pxa2xx_spi_unmap_dma_buffers(drv_data);
> >>> ++
> >>> ++	dev_err(&drv_data->pdev->dev, "%s\n", msg);
> >>> ++
> >>> ++	drv_data->cur_msg->state = ERROR_STATE;
> >>> ++	tasklet_schedule(&drv_data->pump_transfers);
> >>> ++}
> >>> ++
> >>> ++static void pxa2xx_spi_dma_transfer_complete(struct driver_data
> >> *drv_data)
> >>> ++{
> >>> ++	void __iomem *reg = drv_data->ioaddr;
> >>> ++	struct spi_message *msg = drv_data->cur_msg;
> >>> ++
> >>> ++	/* Clear and disable interrupts on SSP and DMA channels*/
> >>> ++	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
> >>> ++	write_SSSR_CS(drv_data, drv_data->clear_sr);
> >>> ++	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
> >>> ++	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
> >>> ++
> >>> ++	if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
> >>> ++		dev_err(&drv_data->pdev->dev,
> >>> ++			"dma_handler: dma rx channel stop failed\n");
> >>> ++
> >>> ++	if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
> >>> ++		dev_err(&drv_data->pdev->dev,
> >>> ++			"dma_transfer: ssp rx stall failed\n");
> >>> ++
> >>> ++	pxa2xx_spi_unmap_dma_buffers(drv_data);
> >>> ++
> >>> ++	/* update the buffer pointer for the amount completed in dma */
> >>> ++	drv_data->rx += drv_data->len -
> >>> ++			(DCMD(drv_data->rx_channel) & DCMD_LENGTH);
> >>> ++
> >>> ++	/* read trailing data from fifo, it does not matter how many
> >>> ++	 * bytes are in the fifo just read until buffer is full
> >>> ++	 * or fifo is empty, which ever occurs first */
> >>> ++	drv_data->read(drv_data);
> >>> ++
> >>> ++	/* return count of what was actually read */
> >>> ++	msg->actual_length += drv_data->len -
> >>> ++				(drv_data->rx_end - drv_data->rx);
> >>> ++
> >>> ++	/* Transfer delays and chip select release are
> >>> ++	 * handled in pump_transfers or giveback
> >>> ++	 */
> >>> ++
> >>> ++	/* Move to next transfer */
> >>> ++	msg->state = pxa2xx_spi_next_transfer(drv_data);
> >>> ++
> >>> ++	/* Schedule transfer tasklet */
> >>> ++	tasklet_schedule(&drv_data->pump_transfers);
> >>> ++}
> >>> ++
> >>> ++void pxa2xx_spi_dma_handler(int channel, void *data)
> >>> ++{
> >>> ++	struct driver_data *drv_data = data;
> >>> ++	u32 irq_status = DCSR(channel) & DMA_INT_MASK;
> >>> ++
> >>> ++	if (irq_status & DCSR_BUSERR) {
> >>> ++
> >>> ++		if (channel == drv_data->tx_channel)
> >>> ++			pxa2xx_spi_dma_error_stop(drv_data,
> >>> ++				"dma_handler: bad bus address on tx
> >> channel");
> >>> ++		else
> >>> ++			pxa2xx_spi_dma_error_stop(drv_data,
> >>> ++				"dma_handler: bad bus address on rx
> >> channel");
> >>> ++		return;
> >>> ++	}
> >>> ++
> >>> ++	/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
> >>> ++	if ((channel == drv_data->tx_channel)
> >>> ++		&& (irq_status & DCSR_ENDINTR)
> >>> ++		&& (drv_data->ssp_type == PXA25x_SSP)) {
> >>> ++
> >>> ++		/* Wait for rx to stall */
> >>> ++		if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
> >>> ++			dev_err(&drv_data->pdev->dev,
> >>> ++				"dma_handler: ssp rx stall failed\n");
> >>> ++
> >>> ++		/* finish this transfer, start the next */
> >>> ++		pxa2xx_spi_dma_transfer_complete(drv_data);
> >>> ++	}
> >>> ++}
> >>> ++
> >>> ++irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
> >>> ++{
> >>> ++	u32 irq_status;
> >>> ++	void __iomem *reg = drv_data->ioaddr;
> >>> ++
> >>> ++	irq_status = read_SSSR(reg) & drv_data->mask_sr;
> >>> ++	if (irq_status & SSSR_ROR) {
> >>> ++		pxa2xx_spi_dma_error_stop(drv_data,
> >>> ++					  "dma_transfer: fifo overrun");
> >>> ++		return IRQ_HANDLED;
> >>> ++	}
> >>> ++
> >>> ++	/* Check for false positive timeout */
> >>> ++	if ((irq_status & SSSR_TINT)
> >>> ++		&& (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
> >>> ++		write_SSSR(SSSR_TINT, reg);
> >>> ++		return IRQ_HANDLED;
> >>> ++	}
> >>> ++
> >>> ++	if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
> >>> ++
> >>> ++		/* Clear and disable timeout interrupt, do the rest in
> >>> ++		 * dma_transfer_complete */
> >>> ++		if (!pxa25x_ssp_comp(drv_data))
> >>> ++			write_SSTO(0, reg);
> >>> ++
> >>> ++		/* finish this transfer, start the next */
> >>> ++		pxa2xx_spi_dma_transfer_complete(drv_data);
> >>> ++
> >>> ++		return IRQ_HANDLED;
> >>> ++	}
> >>> ++
> >>> ++	/* Opps problem detected */
> >>> ++	return IRQ_NONE;
> >>> ++}
> >>> ++
> >>> ++int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32
> >> dma_burst)
> >>> ++{
> >>> ++	u32 dma_width;
> >>> ++
> >>> ++	switch (drv_data->n_bytes) {
> >>> ++	case 1:
> >>> ++		dma_width = DCMD_WIDTH1;
> >>> ++		break;
> >>> ++	case 2:
> >>> ++		dma_width = DCMD_WIDTH2;
> >>> ++		break;
> >>> ++	default:
> >>> ++		dma_width = DCMD_WIDTH4;
> >>> ++		break;
> >>> ++	}
> >>> ++
> >>> ++	/* Setup rx DMA Channel */
> >>> ++	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
> >>> ++	DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
> >>> ++	DTADR(drv_data->rx_channel) = drv_data->rx_dma;
> >>> ++	if (drv_data->rx == drv_data->null_dma_buf)
> >>> ++		/* No target address increment */
> >>> ++		DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
> >>> ++						| dma_width
> >>> ++						| dma_burst
> >>> ++						| drv_data->len;
> >>> ++	else
> >>> ++		DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
> >>> ++						| DCMD_FLOWSRC
> >>> ++						| dma_width
> >>> ++						| dma_burst
> >>> ++						| drv_data->len;
> >>> ++
> >>> ++	/* Setup tx DMA Channel */
> >>> ++	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
> >>> ++	DSADR(drv_data->tx_channel) = drv_data->tx_dma;
> >>> ++	DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
> >>> ++	if (drv_data->tx == drv_data->null_dma_buf)
> >>> ++		/* No source address increment */
> >>> ++		DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
> >>> ++						| dma_width
> >>> ++						| dma_burst
> >>> ++						| drv_data->len;
> >>> ++	else
> >>> ++		DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
> >>> ++						| DCMD_FLOWTRG
> >>> ++						| dma_width
> >>> ++						| dma_burst
> >>> ++						| drv_data->len;
> >>> ++
> >>> ++	/* Enable dma end irqs on SSP to detect end of transfer */
> >>> ++	if (drv_data->ssp_type == PXA25x_SSP)
> >>> ++		DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
> >>> ++
> >>> ++	return 0;
> >>> ++}
> >>> ++
> >>> ++void pxa2xx_spi_dma_start(struct driver_data *drv_data)
> >>> ++{
> >>> ++	DCSR(drv_data->rx_channel) |= DCSR_RUN;
> >>> ++	DCSR(drv_data->tx_channel) |= DCSR_RUN;
> >>> ++}
> >>> ++
> >>> ++int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
> >>> ++{
> >>> ++	struct device *dev = &drv_data->pdev->dev;
> >>> ++	struct ssp_device *ssp = drv_data->ssp;
> >>> ++
> >>> ++	/* Get two DMA channels	(rx and tx) */
> >>> ++	drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
> >>> ++						DMA_PRIO_HIGH,
> >>> ++						pxa2xx_spi_dma_handler,
> >>> ++						drv_data);
> >>> ++	if (drv_data->rx_channel < 0) {
> >>> ++		dev_err(dev, "problem (%d) requesting rx channel\n",
> >>> ++			drv_data->rx_channel);
> >>> ++		return -ENODEV;
> >>> ++	}
> >>> ++	drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
> >>> ++						DMA_PRIO_MEDIUM,
> >>> ++						pxa2xx_spi_dma_handler,
> >>> ++						drv_data);
> >>> ++	if (drv_data->tx_channel < 0) {
> >>> ++		dev_err(dev, "problem (%d) requesting tx channel\n",
> >>> ++			drv_data->tx_channel);
> >>> ++		pxa_free_dma(drv_data->rx_channel);
> >>> ++		return -ENODEV;
> >>> ++	}
> >>> ++
> >>> ++	DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
> >>> ++	DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;
> >>> ++
> >>> ++	return 0;
> >>> ++}
> >>> ++
> >>> ++void pxa2xx_spi_dma_release(struct driver_data *drv_data)
> >>> ++{
> >>> ++	struct ssp_device *ssp = drv_data->ssp;
> >>> ++
> >>> ++	DRCMR(ssp->drcmr_rx) = 0;
> >>> ++	DRCMR(ssp->drcmr_tx) = 0;
> >>> ++
> >>> ++	if (drv_data->tx_channel != 0)
> >>> ++		pxa_free_dma(drv_data->tx_channel);
> >>> ++	if (drv_data->rx_channel != 0)
> >>> ++		pxa_free_dma(drv_data->rx_channel);
> >>> ++}
> >>> ++
> >>> ++void pxa2xx_spi_dma_resume(struct driver_data *drv_data)
> >>> ++{
> >>> ++	if (drv_data->rx_channel != -1)
> >>> ++		DRCMR(drv_data->ssp->drcmr_rx) =
> >>> ++			DRCMR_MAPVLD | drv_data->rx_channel;
> >>> ++	if (drv_data->tx_channel != -1)
> >>> ++		DRCMR(drv_data->ssp->drcmr_tx) =
> >>> ++			DRCMR_MAPVLD | drv_data->tx_channel;
> >>> ++}
> >>> ++
> >>> ++int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
> >>> ++					   struct spi_device *spi,
> >>> ++					   u8 bits_per_word, u32 *burst_code,
> >>> ++					   u32 *threshold)
> >>> ++{
> >>> ++	struct pxa2xx_spi_chip *chip_info =
> >>> ++			(struct pxa2xx_spi_chip *)spi->controller_data;
> >>> ++	int bytes_per_word;
> >>> ++	int burst_bytes;
> >>> ++	int thresh_words;
> >>> ++	int req_burst_size;
> >>> ++	int retval = 0;
> >>> ++
> >>> ++	/* Set the threshold (in registers) to equal the same amount of data
> >>> ++	 * as represented by burst size (in bytes).  The computation below
> >>> ++	 * is (burst_size rounded up to nearest 8 byte, word or long word)
> >>> ++	 * divided by (bytes/register); the tx threshold is the inverse of
> >>> ++	 * the rx, so that there will always be enough data in the rx fifo
> >>> ++	 * to satisfy a burst, and there will always be enough space in the
> >>> ++	 * tx fifo to accept a burst (a tx burst will overwrite the fifo if
> >>> ++	 * there is not enough space), there must always remain enough
> >> empty
> >>> ++	 * space in the rx fifo for any data loaded to the tx fifo.
> >>> ++	 * Whenever burst_size (in bytes) equals bits/word, the fifo
> >> threshold
> >>> ++	 * will be 8, or half the fifo;
> >>> ++	 * The threshold can only be set to 2, 4 or 8, but not 16, because
> >>> ++	 * to burst 16 to the tx fifo, the fifo would have to be empty;
> >>> ++	 * however, the minimum fifo trigger level is 1, and the tx will
> >>> ++	 * request service when the fifo is at this level, with only 15 spaces.
> >>> ++	 */
> >>> ++
> >>> ++	/* find bytes/word */
> >>> ++	if (bits_per_word <= 8)
> >>> ++		bytes_per_word = 1;
> >>> ++	else if (bits_per_word <= 16)
> >>> ++		bytes_per_word = 2;
> >>> ++	else
> >>> ++		bytes_per_word = 4;
> >>> ++
> >>> ++	/* use struct pxa2xx_spi_chip->dma_burst_size if available */
> >>> ++	if (chip_info)
> >>> ++		req_burst_size = chip_info->dma_burst_size;
> >>> ++	else {
> >>> ++		switch (chip->dma_burst_size) {
> >>> ++		default:
> >>> ++			/* if the default burst size is not set,
> >>> ++			 * do it now */
> >>> ++			chip->dma_burst_size = DCMD_BURST8;
> >>> ++		case DCMD_BURST8:
> >>> ++			req_burst_size = 8;
> >>> ++			break;
> >>> ++		case DCMD_BURST16:
> >>> ++			req_burst_size = 16;
> >>> ++			break;
> >>> ++		case DCMD_BURST32:
> >>> ++			req_burst_size = 32;
> >>> ++			break;
> >>> ++		}
> >>> ++	}
> >>> ++	if (req_burst_size <= 8) {
> >>> ++		*burst_code = DCMD_BURST8;
> >>> ++		burst_bytes = 8;
> >>> ++	} else if (req_burst_size <= 16) {
> >>> ++		if (bytes_per_word == 1) {
> >>> ++			/* don't burst more than 1/2 the fifo */
> >>> ++			*burst_code = DCMD_BURST8;
> >>> ++			burst_bytes = 8;
> >>> ++			retval = 1;
> >>> ++		} else {
> >>> ++			*burst_code = DCMD_BURST16;
> >>> ++			burst_bytes = 16;
> >>> ++		}
> >>> ++	} else {
> >>> ++		if (bytes_per_word == 1) {
> >>> ++			/* don't burst more than 1/2 the fifo */
> >>> ++			*burst_code = DCMD_BURST8;
> >>> ++			burst_bytes = 8;
> >>> ++			retval = 1;
> >>> ++		} else if (bytes_per_word == 2) {
> >>> ++			/* don't burst more than 1/2 the fifo */
> >>> ++			*burst_code = DCMD_BURST16;
> >>> ++			burst_bytes = 16;
> >>> ++			retval = 1;
> >>> ++		} else {
> >>> ++			*burst_code = DCMD_BURST32;
> >>> ++			burst_bytes = 32;
> >>> ++		}
> >>> ++	}
> >>> ++
> >>> ++	thresh_words = burst_bytes / bytes_per_word;
> >>> ++
> >>> ++	/* thresh_words will be between 2 and 8 */
> >>> ++	*threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
> >>> ++			| (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
> >>> ++
> >>> ++	return retval;
> >>> ++}
> >>> +diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
> >>> +index 5c8c4f5..b4651b8 100644
> >>> +--- a/drivers/spi/spi-pxa2xx.c
> >>> ++++ b/drivers/spi/spi-pxa2xx.c
> >>> +@@ -1,5 +1,6 @@
> >>> + /*
> >>> +  * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
> >>> ++ * Copyright (C) 2013, Intel Corporation
> >>> +  *
> >>> +  * This program is free software; you can redistribute it and/or modify
> >>> +  * it under the terms of the GNU General Public License as published by
> >>> +@@ -24,17 +25,24 @@
> >>> + #include <linux/interrupt.h>
> >>> + #include <linux/platform_device.h>
> >>> + #include <linux/spi/pxa2xx_spi.h>
> >>> +-#include <linux/dma-mapping.h>
> >>> + #include <linux/spi/spi.h>
> >>> + #include <linux/workqueue.h>
> >>> + #include <linux/delay.h>
> >>> + #include <linux/gpio.h>
> >>> + #include <linux/slab.h>
> >>> ++#include <linux/clk.h>
> >>> ++#include <linux/pm_runtime.h>
> >>> ++#include <linux/acpi.h>
> >>> +
> >>> + #include <asm/io.h>
> >>> + #include <asm/irq.h>
> >>> + #include <asm/delay.h>
> >>> +
> >>> ++#include "spi-pxa2xx.h"
> >>> ++
> >>> ++static bool use_dma = 1;
> >>> ++module_param(use_dma, bool, 0);
> >>> ++MODULE_PARM_DESC(use_dma, "use_dma=1 (enable
> >> DMA)/use_dma=0(disable DMA)");
> >>> +
> >>> + MODULE_AUTHOR("Stephen Street");
> >>> + MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
> >>> +@@ -45,12 +53,6 @@ MODULE_ALIAS("platform:pxa2xx-spi");
> >>> +
> >>> + #define TIMOUT_DFLT		1000
> >>> +
> >>> +-#define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR |
> >> DCSR_BUSERR)
> >>> +-#define RESET_DMA_CHANNEL	(DCSR_NODESC | DMA_INT_MASK)
> >>> +-#define IS_DMA_ALIGNED(x)	((((u32)(x)) & 0x07) == 0)
> >>> +-#define MAX_DMA_LEN		8191
> >>> +-#define DMA_ALIGNMENT		8
> >>> +-
> >>> + /*
> >>> +  * for testing SSCR1 changes that require SSP restart, basically
> >>> +  * everything except the service and interrupt enables, the pxa270
> >> developer
> >>> +@@ -65,115 +67,107 @@ MODULE_ALIAS("platform:pxa2xx-spi");
> >>> + 				| SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
> >>> + 				| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
> >>> +
> >>> +-#define DEFINE_SSP_REG(reg, off) \
> >>> +-static inline u32 read_##reg(void const __iomem *p) \
> >>> +-{ return __raw_readl(p + (off)); } \
> >>> +-\
> >>> +-static inline void write_##reg(u32 v, void __iomem *p) \
> >>> +-{ __raw_writel(v, p + (off)); }
> >>> +-
> >>> +-DEFINE_SSP_REG(SSCR0, 0x00)
> >>> +-DEFINE_SSP_REG(SSCR1, 0x04)
> >>> +-DEFINE_SSP_REG(SSSR, 0x08)
> >>> +-DEFINE_SSP_REG(SSITR, 0x0c)
> >>> +-DEFINE_SSP_REG(SSDR, 0x10)
> >>> +-DEFINE_SSP_REG(SSTO, 0x28)
> >>> +-DEFINE_SSP_REG(SSPSP, 0x2c)
> >>> +-
> >>> +-#define START_STATE ((void*)0)
> >>> +-#define RUNNING_STATE ((void*)1)
> >>> +-#define DONE_STATE ((void*)2)
> >>> +-#define ERROR_STATE ((void*)-1)
> >>> +-
> >>> +-#define QUEUE_RUNNING 0
> >>> +-#define QUEUE_STOPPED 1
> >>> +-
> >>> +-struct driver_data {
> >>> +-	/* Driver model hookup */
> >>> +-	struct platform_device *pdev;
> >>> +-
> >>> +-	/* SSP Info */
> >>> +-	struct ssp_device *ssp;
> >>> ++#define LPSS_RX_THRESH_DFLT	64
> >>> ++#define LPSS_TX_LOTHRESH_DFLT	160
> >>> ++#define LPSS_TX_HITHRESH_DFLT	224
> >>> +
> >>> +-	/* SPI framework hookup */
> >>> +-	enum pxa_ssp_type ssp_type;
> >>> +-	struct spi_master *master;
> >>> ++/* Offset from drv_data->lpss_base */
> >>> ++#define SSP_REG			0x0c
> >>> ++#define GENERAL_REG		0x08
> >>> ++#define SPI_CS_CONTROL		0x18
> >>> ++#define SPI_CS_CONTROL_SW_MODE	BIT(0)
> >>> ++#define SPI_CS_CONTROL_CS_HIGH	BIT(1)
> >>> +
> >>> +-	/* PXA hookup */
> >>> +-	struct pxa2xx_spi_master *master_info;
> >>> +-
> >>> +-	/* DMA setup stuff */
> >>> +-	int rx_channel;
> >>> +-	int tx_channel;
> >>> +-	u32 *null_dma_buf;
> >>> +-
> >>> +-	/* SSP register addresses */
> >>> +-	void __iomem *ioaddr;
> >>> +-	u32 ssdr_physical;
> >>> +-
> >>> +-	/* SSP masks*/
> >>> +-	u32 dma_cr1;
> >>> +-	u32 int_cr1;
> >>> +-	u32 clear_sr;
> >>> +-	u32 mask_sr;
> >>> +-
> >>> +-	/* Driver message queue */
> >>> +-	struct workqueue_struct	*workqueue;
> >>> +-	struct work_struct pump_messages;
> >>> +-	spinlock_t lock;
> >>> +-	struct list_head queue;
> >>> +-	int busy;
> >>> +-	int run;
> >>> +-
> >>> +-	/* Message Transfer pump */
> >>> +-	struct tasklet_struct pump_transfers;
> >>> +-
> >>> +-	/* Current message transfer state info */
> >>> +-	struct spi_message* cur_msg;
> >>> +-	struct spi_transfer* cur_transfer;
> >>> +-	struct chip_data *cur_chip;
> >>> +-	size_t len;
> >>> +-	void *tx;
> >>> +-	void *tx_end;
> >>> +-	void *rx;
> >>> +-	void *rx_end;
> >>> +-	int dma_mapped;
> >>> +-	dma_addr_t rx_dma;
> >>> +-	dma_addr_t tx_dma;
> >>> +-	size_t rx_map_len;
> >>> +-	size_t tx_map_len;
> >>> +-	u8 n_bytes;
> >>> +-	u32 dma_width;
> >>> +-	int (*write)(struct driver_data *drv_data);
> >>> +-	int (*read)(struct driver_data *drv_data);
> >>> +-	irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
> >>> +-	void (*cs_control)(u32 command);
> >>> +-};
> >>> ++static bool is_lpss_ssp(const struct driver_data *drv_data)
> >>> ++{
> >>> ++	return drv_data->ssp_type == LPSS_SSP;
> >>> ++}
> >>> +
> >>> +-struct chip_data {
> >>> +-	u32 cr0;
> >>> +-	u32 cr1;
> >>> +-	u32 psp;
> >>> +-	u32 timeout;
> >>> +-	u8 n_bytes;
> >>> +-	u32 dma_width;
> >>> +-	u32 dma_burst_size;
> >>> +-	u32 threshold;
> >>> +-	u32 dma_threshold;
> >>> +-	u8 enable_dma;
> >>> +-	u8 bits_per_word;
> >>> +-	u32 speed_hz;
> >>> +-	union {
> >>> +-		int gpio_cs;
> >>> +-		unsigned int frm;
> >>> +-	};
> >>> +-	int gpio_cs_inverted;
> >>> +-	int (*write)(struct driver_data *drv_data);
> >>> +-	int (*read)(struct driver_data *drv_data);
> >>> +-	void (*cs_control)(u32 command);
> >>> +-};
> >>> ++/*
> >>> ++ * Read and write LPSS SSP private registers. Caller must first check that
> >>> ++ * is_lpss_ssp() returns true before these can be called.
> >>> ++ */
> >>> ++static u32 __lpss_ssp_read_priv(struct driver_data *drv_data, unsigned
> >> offset)
> >>> ++{
> >>> ++	WARN_ON(!drv_data->lpss_base);
> >>> ++	return readl(drv_data->lpss_base + offset);
> >>> ++}
> >>> ++
> >>> ++static void __lpss_ssp_write_priv(struct driver_data *drv_data,
> >>> ++				  unsigned offset, u32 value)
> >>> ++{
> >>> ++	WARN_ON(!drv_data->lpss_base);
> >>> ++	writel(value, drv_data->lpss_base + offset);
> >>> ++}
> >>> ++
> >>> ++/*
> >>> ++ * lpss_ssp_setup - perform LPSS SSP specific setup
> >>> ++ * @drv_data: pointer to the driver private data
> >>> ++ *
> >>> ++ * Perform LPSS SSP specific setup. This function must be called first if
> >>> ++ * one is going to use LPSS SSP private registers.
> >>> ++ */
> >>> ++static void lpss_ssp_setup(struct driver_data *drv_data)
> >>> ++{
> >>> ++	unsigned offset = 0x400;
> >>> ++	u32 value, orig;
> >>> ++
> >>> ++	if (!is_lpss_ssp(drv_data))
> >>> ++		return;
> >>> ++
> >>> ++	/*
> >>> ++	 * Perform auto-detection of the LPSS SSP private registers. They
> >>> ++	 * can be either at 1k or 2k offset from the base address.
> >>> ++	 */
> >>> ++	orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
> >>> ++
> >>> ++	value = orig | SPI_CS_CONTROL_SW_MODE;
> >>> ++	writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
> >>> ++	value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
> >>> ++	if (value != (orig | SPI_CS_CONTROL_SW_MODE)) {
> >>> ++		offset = 0x800;
> >>> ++		goto detection_done;
> >>> ++	}
> >>> ++
> >>> ++	value &= ~SPI_CS_CONTROL_SW_MODE;
> >>> ++	writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
> >>> ++	value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
> >>> ++	if (value != orig) {
> >>> ++		offset = 0x800;
> >>> ++		goto detection_done;
> >>> ++	}
> >>> ++
> >>> ++detection_done:
> >>> ++	/* Now set the LPSS base */
> >>> ++	drv_data->lpss_base = drv_data->ioaddr + offset;
> >>> ++
> >>> ++	/* Enable software chip select control */
> >>> ++	value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH;
> >>> ++	__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
> >>> ++
> >>> ++	/* Enable multiblock DMA transfers */
> >>> ++	if (drv_data->master_info->enable_dma){
> >>> ++		__lpss_ssp_write_priv(drv_data, SSP_REG, 1);
> >>> ++		value = readl(drv_data->ioaddr + offset + GENERAL_REG);
> >>> ++		value |= BIT(24);
> >>> ++		__lpss_ssp_write_priv(drv_data, GENERAL_REG, value);
> >>> ++	}
> >>> ++}
> >>> ++
> >>> ++static void lpss_ssp_cs_control(struct driver_data *drv_data, bool
> >> enable)
> >>> ++{
> >>> ++	u32 value;
> >>> ++
> >>> ++	if (!is_lpss_ssp(drv_data))
> >>> ++		return;
> >>> +
> >>> +-static void pump_messages(struct work_struct *work);
> >>> ++	value = __lpss_ssp_read_priv(drv_data, SPI_CS_CONTROL);
> >>> ++	if (enable)
> >>> ++		value &= ~SPI_CS_CONTROL_CS_HIGH;
> >>> ++	else
> >>> ++		value |= SPI_CS_CONTROL_CS_HIGH;
> >>> ++	__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
> >>> ++}
> >>> +
> >>> + static void cs_assert(struct driver_data *drv_data)
> >>> + {
> >>> +@@ -189,8 +183,12 @@ static void cs_assert(struct driver_data *drv_data)
> >>> + 		return;
> >>> + 	}
> >>> +
> >>> +-	if (gpio_is_valid(chip->gpio_cs))
> >>> ++	if (gpio_is_valid(chip->gpio_cs)) {
> >>> + 		gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted);
> >>> ++		return;
> >>> ++	}
> >>> ++
> >>> ++	lpss_ssp_cs_control(drv_data, true);
> >>> + }
> >>> +
> >>> + static void cs_deassert(struct driver_data *drv_data)
> >>> +@@ -205,30 +203,15 @@ static void cs_deassert(struct driver_data
> >> *drv_data)
> >>> + 		return;
> >>> + 	}
> >>> +
> >>> +-	if (gpio_is_valid(chip->gpio_cs))
> >>> ++	if (gpio_is_valid(chip->gpio_cs)) {
> >>> + 		gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
> >>> +-}
> >>> +-
> >>> +-static void write_SSSR_CS(struct driver_data *drv_data, u32 val)
> >>> +-{
> >>> +-	void __iomem *reg = drv_data->ioaddr;
> >>> +-
> >>> +-	if (drv_data->ssp_type == CE4100_SSP)
> >>> +-		val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
> >>> ++		return;
> >>> ++	}
> >>> +
> >>> +-	write_SSSR(val, reg);
> >>> ++	lpss_ssp_cs_control(drv_data, false);
> >>> + }
> >>> +
> >>> +-static int pxa25x_ssp_comp(struct driver_data *drv_data)
> >>> +-{
> >>> +-	if (drv_data->ssp_type == PXA25x_SSP)
> >>> +-		return 1;
> >>> +-	if (drv_data->ssp_type == CE4100_SSP)
> >>> +-		return 1;
> >>> +-	return 0;
> >>> +-}
> >>> +-
> >>> +-static int flush(struct driver_data *drv_data)
> >>> ++int pxa2xx_spi_flush(struct driver_data *drv_data)
> >>> + {
> >>> + 	unsigned long limit = loops_per_jiffy << 1;
> >>> +
> >>> +@@ -354,7 +337,7 @@ static int u32_reader(struct driver_data *drv_data)
> >>> + 	return drv_data->rx == drv_data->rx_end;
> >>> + }
> >>> +
> >>> +-static void *next_transfer(struct driver_data *drv_data)
> >>> ++void *pxa2xx_spi_next_transfer(struct driver_data *drv_data)
> >>> + {
> >>> + 	struct spi_message *msg = drv_data->cur_msg;
> >>> + 	struct spi_transfer *trans = drv_data->cur_transfer;
> >>> +@@ -370,89 +353,15 @@ static void *next_transfer(struct driver_data
> >> *drv_data)
> >>> + 		return DONE_STATE;
> >>> + }
> >>> +
> >>> +-static int map_dma_buffers(struct driver_data *drv_data)
> >>> +-{
> >>> +-	struct spi_message *msg = drv_data->cur_msg;
> >>> +-	struct device *dev = &msg->spi->dev;
> >>> +-
> >>> +-	if (!drv_data->cur_chip->enable_dma)
> >>> +-		return 0;
> >>> +-
> >>> +-	if (msg->is_dma_mapped)
> >>> +-		return  drv_data->rx_dma && drv_data->tx_dma;
> >>> +-
> >>> +-	if (!IS_DMA_ALIGNED(drv_data->rx)
> >> || !IS_DMA_ALIGNED(drv_data->tx))
> >>> +-		return 0;
> >>> +-
> >>> +-	/* Modify setup if rx buffer is null */
> >>> +-	if (drv_data->rx == NULL) {
> >>> +-		*drv_data->null_dma_buf = 0;
> >>> +-		drv_data->rx = drv_data->null_dma_buf;
> >>> +-		drv_data->rx_map_len = 4;
> >>> +-	} else
> >>> +-		drv_data->rx_map_len = drv_data->len;
> >>> +-
> >>> +-
> >>> +-	/* Modify setup if tx buffer is null */
> >>> +-	if (drv_data->tx == NULL) {
> >>> +-		*drv_data->null_dma_buf = 0;
> >>> +-		drv_data->tx = drv_data->null_dma_buf;
> >>> +-		drv_data->tx_map_len = 4;
> >>> +-	} else
> >>> +-		drv_data->tx_map_len = drv_data->len;
> >>> +-
> >>> +-	/* Stream map the tx buffer. Always do DMA_TO_DEVICE first
> >>> +-	 * so we flush the cache *before* invalidating it, in case
> >>> +-	 * the tx and rx buffers overlap.
> >>> +-	 */
> >>> +-	drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
> >>> +-					drv_data->tx_map_len,
> >> DMA_TO_DEVICE);
> >>> +-	if (dma_mapping_error(dev, drv_data->tx_dma))
> >>> +-		return 0;
> >>> +-
> >>> +-	/* Stream map the rx buffer */
> >>> +-	drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
> >>> +-					drv_data->rx_map_len,
> >> DMA_FROM_DEVICE);
> >>> +-	if (dma_mapping_error(dev, drv_data->rx_dma)) {
> >>> +-		dma_unmap_single(dev, drv_data->tx_dma,
> >>> +-					drv_data->tx_map_len,
> >> DMA_TO_DEVICE);
> >>> +-		return 0;
> >>> +-	}
> >>> +-
> >>> +-	return 1;
> >>> +-}
> >>> +-
> >>> +-static void unmap_dma_buffers(struct driver_data *drv_data)
> >>> +-{
> >>> +-	struct device *dev;
> >>> +-
> >>> +-	if (!drv_data->dma_mapped)
> >>> +-		return;
> >>> +-
> >>> +-	if (!drv_data->cur_msg->is_dma_mapped) {
> >>> +-		dev = &drv_data->cur_msg->spi->dev;
> >>> +-		dma_unmap_single(dev, drv_data->rx_dma,
> >>> +-					drv_data->rx_map_len,
> >> DMA_FROM_DEVICE);
> >>> +-		dma_unmap_single(dev, drv_data->tx_dma,
> >>> +-					drv_data->tx_map_len,
> >> DMA_TO_DEVICE);
> >>> +-	}
> >>> +-
> >>> +-	drv_data->dma_mapped = 0;
> >>> +-}
> >>> +-
> >>> + /* caller already set message->status; dma and pio irqs are blocked */
> >>> + static void giveback(struct driver_data *drv_data)
> >>> + {
> >>> + 	struct spi_transfer* last_transfer;
> >>> +-	unsigned long flags;
> >>> + 	struct spi_message *msg;
> >>> +
> >>> +-	spin_lock_irqsave(&drv_data->lock, flags);
> >>> + 	msg = drv_data->cur_msg;
> >>> + 	drv_data->cur_msg = NULL;
> >>> + 	drv_data->cur_transfer = NULL;
> >>> +-	queue_work(drv_data->workqueue, &drv_data->pump_messages);
> >>> +-	spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> +
> >>> + 	last_transfer = list_entry(msg->transfers.prev,
> >>> + 					struct spi_transfer,
> >>> +@@ -481,13 +390,7 @@ static void giveback(struct driver_data *drv_data)
> >>> + 		 */
> >>> +
> >>> + 		/* get a pointer to the next message, if any */
> >>> +-		spin_lock_irqsave(&drv_data->lock, flags);
> >>> +-		if (list_empty(&drv_data->queue))
> >>> +-			next_msg = NULL;
> >>> +-		else
> >>> +-			next_msg = list_entry(drv_data->queue.next,
> >>> +-					struct spi_message, queue);
> >>> +-		spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> ++		next_msg = spi_get_next_queued_message(drv_data-
> >>> master);
> >>> +
> >>> + 		/* see if the next and current messages point
> >>> + 		 * to the same chip
> >>> +@@ -498,168 +401,10 @@ static void giveback(struct driver_data
> >> *drv_data)
> >>> + 			cs_deassert(drv_data);
> >>> + 	}
> >>> +
> >>> +-	msg->state = NULL;
> >>> +-	if (msg->complete)
> >>> +-		msg->complete(msg->context);
> >>> +-
> >>> ++	spi_finalize_current_message(drv_data->master);
> >>> + 	drv_data->cur_chip = NULL;
> >>> + }
> >>> +
> >>> +-static int wait_ssp_rx_stall(void const __iomem *ioaddr)
> >>> +-{
> >>> +-	unsigned long limit = loops_per_jiffy << 1;
> >>> +-
> >>> +-	while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
> >>> +-		cpu_relax();
> >>> +-
> >>> +-	return limit;
> >>> +-}
> >>> +-
> >>> +-static int wait_dma_channel_stop(int channel)
> >>> +-{
> >>> +-	unsigned long limit = loops_per_jiffy << 1;
> >>> +-
> >>> +-	while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
> >>> +-		cpu_relax();
> >>> +-
> >>> +-	return limit;
> >>> +-}
> >>> +-
> >>> +-static void dma_error_stop(struct driver_data *drv_data, const char
> >> *msg)
> >>> +-{
> >>> +-	void __iomem *reg = drv_data->ioaddr;
> >>> +-
> >>> +-	/* Stop and reset */
> >>> +-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
> >>> +-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
> >>> +-	write_SSSR_CS(drv_data, drv_data->clear_sr);
> >>> +-	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
> >>> +-	if (!pxa25x_ssp_comp(drv_data))
> >>> +-		write_SSTO(0, reg);
> >>> +-	flush(drv_data);
> >>> +-	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
> >>> +-
> >>> +-	unmap_dma_buffers(drv_data);
> >>> +-
> >>> +-	dev_err(&drv_data->pdev->dev, "%s\n", msg);
> >>> +-
> >>> +-	drv_data->cur_msg->state = ERROR_STATE;
> >>> +-	tasklet_schedule(&drv_data->pump_transfers);
> >>> +-}
> >>> +-
> >>> +-static void dma_transfer_complete(struct driver_data *drv_data)
> >>> +-{
> >>> +-	void __iomem *reg = drv_data->ioaddr;
> >>> +-	struct spi_message *msg = drv_data->cur_msg;
> >>> +-
> >>> +-	/* Clear and disable interrupts on SSP and DMA channels*/
> >>> +-	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
> >>> +-	write_SSSR_CS(drv_data, drv_data->clear_sr);
> >>> +-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
> >>> +-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
> >>> +-
> >>> +-	if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
> >>> +-		dev_err(&drv_data->pdev->dev,
> >>> +-			"dma_handler: dma rx channel stop failed\n");
> >>> +-
> >>> +-	if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
> >>> +-		dev_err(&drv_data->pdev->dev,
> >>> +-			"dma_transfer: ssp rx stall failed\n");
> >>> +-
> >>> +-	unmap_dma_buffers(drv_data);
> >>> +-
> >>> +-	/* update the buffer pointer for the amount completed in dma */
> >>> +-	drv_data->rx += drv_data->len -
> >>> +-			(DCMD(drv_data->rx_channel) & DCMD_LENGTH);
> >>> +-
> >>> +-	/* read trailing data from fifo, it does not matter how many
> >>> +-	 * bytes are in the fifo just read until buffer is full
> >>> +-	 * or fifo is empty, which ever occurs first */
> >>> +-	drv_data->read(drv_data);
> >>> +-
> >>> +-	/* return count of what was actually read */
> >>> +-	msg->actual_length += drv_data->len -
> >>> +-				(drv_data->rx_end - drv_data->rx);
> >>> +-
> >>> +-	/* Transfer delays and chip select release are
> >>> +-	 * handled in pump_transfers or giveback
> >>> +-	 */
> >>> +-
> >>> +-	/* Move to next transfer */
> >>> +-	msg->state = next_transfer(drv_data);
> >>> +-
> >>> +-	/* Schedule transfer tasklet */
> >>> +-	tasklet_schedule(&drv_data->pump_transfers);
> >>> +-}
> >>> +-
> >>> +-static void dma_handler(int channel, void *data)
> >>> +-{
> >>> +-	struct driver_data *drv_data = data;
> >>> +-	u32 irq_status = DCSR(channel) & DMA_INT_MASK;
> >>> +-
> >>> +-	if (irq_status & DCSR_BUSERR) {
> >>> +-
> >>> +-		if (channel == drv_data->tx_channel)
> >>> +-			dma_error_stop(drv_data,
> >>> +-					"dma_handler: "
> >>> +-					"bad bus address on tx channel");
> >>> +-		else
> >>> +-			dma_error_stop(drv_data,
> >>> +-					"dma_handler: "
> >>> +-					"bad bus address on rx channel");
> >>> +-		return;
> >>> +-	}
> >>> +-
> >>> +-	/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
> >>> +-	if ((channel == drv_data->tx_channel)
> >>> +-		&& (irq_status & DCSR_ENDINTR)
> >>> +-		&& (drv_data->ssp_type == PXA25x_SSP)) {
> >>> +-
> >>> +-		/* Wait for rx to stall */
> >>> +-		if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
> >>> +-			dev_err(&drv_data->pdev->dev,
> >>> +-				"dma_handler: ssp rx stall failed\n");
> >>> +-
> >>> +-		/* finish this transfer, start the next */
> >>> +-		dma_transfer_complete(drv_data);
> >>> +-	}
> >>> +-}
> >>> +-
> >>> +-static irqreturn_t dma_transfer(struct driver_data *drv_data)
> >>> +-{
> >>> +-	u32 irq_status;
> >>> +-	void __iomem *reg = drv_data->ioaddr;
> >>> +-
> >>> +-	irq_status = read_SSSR(reg) & drv_data->mask_sr;
> >>> +-	if (irq_status & SSSR_ROR) {
> >>> +-		dma_error_stop(drv_data, "dma_transfer: fifo overrun");
> >>> +-		return IRQ_HANDLED;
> >>> +-	}
> >>> +-
> >>> +-	/* Check for false positive timeout */
> >>> +-	if ((irq_status & SSSR_TINT)
> >>> +-		&& (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
> >>> +-		write_SSSR(SSSR_TINT, reg);
> >>> +-		return IRQ_HANDLED;
> >>> +-	}
> >>> +-
> >>> +-	if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
> >>> +-
> >>> +-		/* Clear and disable timeout interrupt, do the rest in
> >>> +-		 * dma_transfer_complete */
> >>> +-		if (!pxa25x_ssp_comp(drv_data))
> >>> +-			write_SSTO(0, reg);
> >>> +-
> >>> +-		/* finish this transfer, start the next */
> >>> +-		dma_transfer_complete(drv_data);
> >>> +-
> >>> +-		return IRQ_HANDLED;
> >>> +-	}
> >>> +-
> >>> +-	/* Opps problem detected */
> >>> +-	return IRQ_NONE;
> >>> +-}
> >>> +-
> >>> + static void reset_sccr1(struct driver_data *drv_data)
> >>> + {
> >>> + 	void __iomem *reg = drv_data->ioaddr;
> >>> +@@ -681,7 +426,7 @@ static void int_error_stop(struct driver_data
> >> *drv_data, const char* msg)
> >>> + 	reset_sccr1(drv_data);
> >>> + 	if (!pxa25x_ssp_comp(drv_data))
> >>> + 		write_SSTO(0, reg);
> >>> +-	flush(drv_data);
> >>> ++	pxa2xx_spi_flush(drv_data);
> >>> + 	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
> >>> +
> >>> + 	dev_err(&drv_data->pdev->dev, "%s\n", msg);
> >>> +@@ -709,7 +454,7 @@ static void int_transfer_complete(struct
> >> driver_data *drv_data)
> >>> + 	 */
> >>> +
> >>> + 	/* Move to next transfer */
> >>> +-	drv_data->cur_msg->state = next_transfer(drv_data);
> >>> ++	drv_data->cur_msg->state = pxa2xx_spi_next_transfer(drv_data);
> >>> +
> >>> + 	/* Schedule transfer tasklet */
> >>> + 	tasklet_schedule(&drv_data->pump_transfers);
> >>> +@@ -789,10 +534,20 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
> >>> + {
> >>> + 	struct driver_data *drv_data = dev_id;
> >>> + 	void __iomem *reg = drv_data->ioaddr;
> >>> +-	u32 sccr1_reg = read_SSCR1(reg);
> >>> ++	u32 sccr1_reg;
> >>> + 	u32 mask = drv_data->mask_sr;
> >>> + 	u32 status;
> >>> +
> >>> ++	/*
> >>> ++	 * The IRQ might be shared with other peripherals so we must first
> >>> ++	 * check that are we RPM suspended or not. If we are we assume
> >> that
> >>> ++	 * the IRQ was not for us (we shouldn't be RPM suspended when the
> >>> ++	 * interrupt is enabled).
> >>> ++	 */
> >>> ++	if (pm_runtime_suspended(&drv_data->pdev->dev))
> >>> ++		return IRQ_NONE;
> >>> ++
> >>> ++	sccr1_reg = read_SSCR1(reg);
> >>> + 	status = read_SSSR(reg);
> >>> +
> >>> + 	/* Ignore possible writes if we don't need to write */
> >>> +@@ -820,106 +575,12 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
> >>> + 	return drv_data->transfer_handler(drv_data);
> >>> + }
> >>> +
> >>> +-static int set_dma_burst_and_threshold(struct chip_data *chip,
> >>> +-				struct spi_device *spi,
> >>> +-				u8 bits_per_word, u32 *burst_code,
> >>> +-				u32 *threshold)
> >>> ++static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
> >>> + {
> >>> +-	struct pxa2xx_spi_chip *chip_info =
> >>> +-			(struct pxa2xx_spi_chip *)spi->controller_data;
> >>> +-	int bytes_per_word;
> >>> +-	int burst_bytes;
> >>> +-	int thresh_words;
> >>> +-	int req_burst_size;
> >>> +-	int retval = 0;
> >>> +-
> >>> +-	/* Set the threshold (in registers) to equal the same amount of data
> >>> +-	 * as represented by burst size (in bytes).  The computation below
> >>> +-	 * is (burst_size rounded up to nearest 8 byte, word or long word)
> >>> +-	 * divided by (bytes/register); the tx threshold is the inverse of
> >>> +-	 * the rx, so that there will always be enough data in the rx fifo
> >>> +-	 * to satisfy a burst, and there will always be enough space in the
> >>> +-	 * tx fifo to accept a burst (a tx burst will overwrite the fifo if
> >>> +-	 * there is not enough space), there must always remain enough
> >> empty
> >>> +-	 * space in the rx fifo for any data loaded to the tx fifo.
> >>> +-	 * Whenever burst_size (in bytes) equals bits/word, the fifo
> >> threshold
> >>> +-	 * will be 8, or half the fifo;
> >>> +-	 * The threshold can only be set to 2, 4 or 8, but not 16, because
> >>> +-	 * to burst 16 to the tx fifo, the fifo would have to be empty;
> >>> +-	 * however, the minimum fifo trigger level is 1, and the tx will
> >>> +-	 * request service when the fifo is at this level, with only 15 spaces.
> >>> +-	 */
> >>> +-
> >>> +-	/* find bytes/word */
> >>> +-	if (bits_per_word <= 8)
> >>> +-		bytes_per_word = 1;
> >>> +-	else if (bits_per_word <= 16)
> >>> +-		bytes_per_word = 2;
> >>> +-	else
> >>> +-		bytes_per_word = 4;
> >>> +-
> >>> +-	/* use struct pxa2xx_spi_chip->dma_burst_size if available */
> >>> +-	if (chip_info)
> >>> +-		req_burst_size = chip_info->dma_burst_size;
> >>> +-	else {
> >>> +-		switch (chip->dma_burst_size) {
> >>> +-		default:
> >>> +-			/* if the default burst size is not set,
> >>> +-			 * do it now */
> >>> +-			chip->dma_burst_size = DCMD_BURST8;
> >>> +-		case DCMD_BURST8:
> >>> +-			req_burst_size = 8;
> >>> +-			break;
> >>> +-		case DCMD_BURST16:
> >>> +-			req_burst_size = 16;
> >>> +-			break;
> >>> +-		case DCMD_BURST32:
> >>> +-			req_burst_size = 32;
> >>> +-			break;
> >>> +-		}
> >>> +-	}
> >>> +-	if (req_burst_size <= 8) {
> >>> +-		*burst_code = DCMD_BURST8;
> >>> +-		burst_bytes = 8;
> >>> +-	} else if (req_burst_size <= 16) {
> >>> +-		if (bytes_per_word == 1) {
> >>> +-			/* don't burst more than 1/2 the fifo */
> >>> +-			*burst_code = DCMD_BURST8;
> >>> +-			burst_bytes = 8;
> >>> +-			retval = 1;
> >>> +-		} else {
> >>> +-			*burst_code = DCMD_BURST16;
> >>> +-			burst_bytes = 16;
> >>> +-		}
> >>> +-	} else {
> >>> +-		if (bytes_per_word == 1) {
> >>> +-			/* don't burst more than 1/2 the fifo */
> >>> +-			*burst_code = DCMD_BURST8;
> >>> +-			burst_bytes = 8;
> >>> +-			retval = 1;
> >>> +-		} else if (bytes_per_word == 2) {
> >>> +-			/* don't burst more than 1/2 the fifo */
> >>> +-			*burst_code = DCMD_BURST16;
> >>> +-			burst_bytes = 16;
> >>> +-			retval = 1;
> >>> +-		} else {
> >>> +-			*burst_code = DCMD_BURST32;
> >>> +-			burst_bytes = 32;
> >>> +-		}
> >>> +-	}
> >>> +-
> >>> +-	thresh_words = burst_bytes / bytes_per_word;
> >>> ++	unsigned long ssp_clk = drv_data->max_clk_rate;
> >>> ++	const struct ssp_device *ssp = drv_data->ssp;
> >>> +
> >>> +-	/* thresh_words will be between 2 and 8 */
> >>> +-	*threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
> >>> +-			| (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
> >>> +-
> >>> +-	return retval;
> >>> +-}
> >>> +-
> >>> +-static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
> >>> +-{
> >>> +-	unsigned long ssp_clk = clk_get_rate(ssp->clk);
> >>> ++	rate = min_t(int, ssp_clk, rate);
> >>> +
> >>> + 	if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
> >>> + 		return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
> >>> +@@ -934,7 +595,6 @@ static void pump_transfers(unsigned long data)
> >>> + 	struct spi_transfer *transfer = NULL;
> >>> + 	struct spi_transfer *previous = NULL;
> >>> + 	struct chip_data *chip = NULL;
> >>> +-	struct ssp_device *ssp = drv_data->ssp;
> >>> + 	void __iomem *reg = drv_data->ioaddr;
> >>> + 	u32 clk_div = 0;
> >>> + 	u8 bits = 0;
> >>> +@@ -976,8 +636,8 @@ static void pump_transfers(unsigned long data)
> >>> + 			cs_deassert(drv_data);
> >>> + 	}
> >>> +
> >>> +-	/* Check for transfers that need multiple DMA segments */
> >>> +-	if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
> >>> ++	/* Check if we can DMA this transfer */
> >>> ++	if (!pxa2xx_spi_dma_is_possible(transfer->len) && chip-
> >>> enable_dma) {
> >>> +
> >>> + 		/* reject already-mapped transfers; PIO won't always work
> >> */
> >>> + 		if (message->is_dma_mapped
> >>> +@@ -1000,21 +660,20 @@ static void pump_transfers(unsigned long data)
> >>> + 	}
> >>> +
> >>> + 	/* Setup the transfer state based on the type of transfer */
> >>> +-	if (flush(drv_data) == 0) {
> >>> ++	if (pxa2xx_spi_flush(drv_data) == 0) {
> >>> + 		dev_err(&drv_data->pdev->dev, "pump_transfers: flush
> >> failed\n");
> >>> + 		message->status = -EIO;
> >>> + 		giveback(drv_data);
> >>> + 		return;
> >>> + 	}
> >>> + 	drv_data->n_bytes = chip->n_bytes;
> >>> +-	drv_data->dma_width = chip->dma_width;
> >>> + 	drv_data->tx = (void *)transfer->tx_buf;
> >>> + 	drv_data->tx_end = drv_data->tx + transfer->len;
> >>> + 	drv_data->rx = transfer->rx_buf;
> >>> + 	drv_data->rx_end = drv_data->rx + transfer->len;
> >>> + 	drv_data->rx_dma = transfer->rx_dma;
> >>> + 	drv_data->tx_dma = transfer->tx_dma;
> >>> +-	drv_data->len = transfer->len & DCMD_LENGTH;
> >>> ++	drv_data->len = transfer->len;
> >>> + 	drv_data->write = drv_data->tx ? chip->write : null_writer;
> >>> + 	drv_data->read = drv_data->rx ? chip->read : null_reader;
> >>> +
> >>> +@@ -1031,25 +690,22 @@ static void pump_transfers(unsigned long data)
> >>> + 		if (transfer->bits_per_word)
> >>> + 			bits = transfer->bits_per_word;
> >>> +
> >>> +-		clk_div = ssp_get_clk_div(ssp, speed);
> >>> ++		clk_div = ssp_get_clk_div(drv_data, speed);
> >>> +
> >>> + 		if (bits <= 8) {
> >>> + 			drv_data->n_bytes = 1;
> >>> +-			drv_data->dma_width = DCMD_WIDTH1;
> >>> + 			drv_data->read = drv_data->read != null_reader ?
> >>> + 						u8_reader : null_reader;
> >>> + 			drv_data->write = drv_data->write != null_writer ?
> >>> + 						u8_writer : null_writer;
> >>> + 		} else if (bits <= 16) {
> >>> + 			drv_data->n_bytes = 2;
> >>> +-			drv_data->dma_width = DCMD_WIDTH2;
> >>> + 			drv_data->read = drv_data->read != null_reader ?
> >>> + 						u16_reader : null_reader;
> >>> + 			drv_data->write = drv_data->write != null_writer ?
> >>> + 						u16_writer : null_writer;
> >>> + 		} else if (bits <= 32) {
> >>> + 			drv_data->n_bytes = 4;
> >>> +-			drv_data->dma_width = DCMD_WIDTH4;
> >>> + 			drv_data->read = drv_data->read != null_reader ?
> >>> + 						u32_reader : null_reader;
> >>> + 			drv_data->write = drv_data->write != null_writer ?
> >>> +@@ -1058,7 +714,8 @@ static void pump_transfers(unsigned long data)
> >>> + 		/* if bits/word is changed in dma mode, then must check the
> >>> + 		 * thresholds and burst also */
> >>> + 		if (chip->enable_dma) {
> >>> +-			if (set_dma_burst_and_threshold(chip, message-
> >>> spi,
> >>> ++			if (pxa2xx_spi_set_dma_burst_and_threshold(chip,
> >>> ++							message->spi,
> >>> + 							bits, &dma_burst,
> >>> + 							&dma_thresh))
> >>> + 				if (printk_ratelimit())
> >>> +@@ -1077,70 +734,21 @@ static void pump_transfers(unsigned long data)
> >>> +
> >>> + 	message->state = RUNNING_STATE;
> >>> +
> >>> +-	/* Try to map dma buffer and do a dma transfer if successful, but
> >>> +-	 * only if the length is non-zero and less than MAX_DMA_LEN.
> >>> +-	 *
> >>> +-	 * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
> >>> +-	 * of PIO instead.  Care is needed above because the transfer may
> >>> +-	 * have have been passed with buffers that are already dma mapped.
> >>> +-	 * A zero-length transfer in PIO mode will not try to write/read
> >>> +-	 * to/from the buffers
> >>> +-	 *
> >>> +-	 * REVISIT large transfers are exactly where we most want to be
> >>> +-	 * using DMA.  If this happens much, split those transfers into
> >>> +-	 * multiple DMA segments rather than forcing PIO.
> >>> +-	 */
> >>> + 	drv_data->dma_mapped = 0;
> >>> +-	if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN)
> >>> +-		drv_data->dma_mapped = map_dma_buffers(drv_data);
> >>> ++	if (pxa2xx_spi_dma_is_possible(drv_data->len))
> >>> ++		drv_data->dma_mapped =
> >> pxa2xx_spi_map_dma_buffers(drv_data);
> >>> + 	if (drv_data->dma_mapped) {
> >>> +
> >>> + 		/* Ensure we have the correct interrupt handler */
> >>> +-		drv_data->transfer_handler = dma_transfer;
> >>> +-
> >>> +-		/* Setup rx DMA Channel */
> >>> +-		DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
> >>> +-		DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
> >>> +-		DTADR(drv_data->rx_channel) = drv_data->rx_dma;
> >>> +-		if (drv_data->rx == drv_data->null_dma_buf)
> >>> +-			/* No target address increment */
> >>> +-			DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
> >>> +-							| drv_data-
> >>> dma_width
> >>> +-							| dma_burst
> >>> +-							| drv_data->len;
> >>> +-		else
> >>> +-			DCMD(drv_data->rx_channel) =
> >> DCMD_INCTRGADDR
> >>> +-							| DCMD_FLOWSRC
> >>> +-							| drv_data-
> >>> dma_width
> >>> +-							| dma_burst
> >>> +-							| drv_data->len;
> >>> +-
> >>> +-		/* Setup tx DMA Channel */
> >>> +-		DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
> >>> +-		DSADR(drv_data->tx_channel) = drv_data->tx_dma;
> >>> +-		DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
> >>> +-		if (drv_data->tx == drv_data->null_dma_buf)
> >>> +-			/* No source address increment */
> >>> +-			DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
> >>> +-							| drv_data-
> >>> dma_width
> >>> +-							| dma_burst
> >>> +-							| drv_data->len;
> >>> +-		else
> >>> +-			DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
> >>> +-							| DCMD_FLOWTRG
> >>> +-							| drv_data-
> >>> dma_width
> >>> +-							| dma_burst
> >>> +-							| drv_data->len;
> >>> +-
> >>> +-		/* Enable dma end irqs on SSP to detect end of transfer */
> >>> +-		if (drv_data->ssp_type == PXA25x_SSP)
> >>> +-			DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
> >>> ++		drv_data->transfer_handler = pxa2xx_spi_dma_transfer;
> >>> ++
> >>> ++		pxa2xx_spi_dma_prepare(drv_data, dma_burst);
> >>> +
> >>> + 		/* Clear status and start DMA engine */
> >>> + 		cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
> >>> + 		write_SSSR(drv_data->clear_sr, reg);
> >>> +-		DCSR(drv_data->rx_channel) |= DCSR_RUN;
> >>> +-		DCSR(drv_data->tx_channel) |= DCSR_RUN;
> >>> ++
> >>> ++		pxa2xx_spi_dma_start(drv_data);
> >>> + 	} else {
> >>> + 		/* Ensure we have the correct interrupt handler	*/
> >>> + 		drv_data->transfer_handler = interrupt_transfer;
> >>> +@@ -1150,6 +758,13 @@ static void pump_transfers(unsigned long data)
> >>> + 		write_SSSR_CS(drv_data, drv_data->clear_sr);
> >>> + 	}
> >>> +
> >>> ++	if (is_lpss_ssp(drv_data)) {
> >>> ++		if ((read_SSIRF(reg) & 0xff) != chip->lpss_rx_threshold)
> >>> ++			write_SSIRF(chip->lpss_rx_threshold, reg);
> >>> ++		if ((read_SSITF(reg) & 0xffff) != chip->lpss_tx_threshold)
> >>> ++			write_SSITF(chip->lpss_tx_threshold, reg);
> >>> ++	}
> >>> ++
> >>> + 	/* see if we need to reload the config registers */
> >>> + 	if ((read_SSCR0(reg) != cr0)
> >>> + 		|| (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
> >>> +@@ -1176,31 +791,12 @@ static void pump_transfers(unsigned long data)
> >>> + 	write_SSCR1(cr1, reg);
> >>> + }
> >>> +
> >>> +-static void pump_messages(struct work_struct *work)
> >>> ++static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
> >>> ++					   struct spi_message *msg)
> >>> + {
> >>> +-	struct driver_data *drv_data =
> >>> +-		container_of(work, struct driver_data, pump_messages);
> >>> +-	unsigned long flags;
> >>> +-
> >>> +-	/* Lock queue and check for queue work */
> >>> +-	spin_lock_irqsave(&drv_data->lock, flags);
> >>> +-	if (list_empty(&drv_data->queue) || drv_data->run ==
> >> QUEUE_STOPPED) {
> >>> +-		drv_data->busy = 0;
> >>> +-		spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> +-		return;
> >>> +-	}
> >>> +-
> >>> +-	/* Make sure we are not already running a message */
> >>> +-	if (drv_data->cur_msg) {
> >>> +-		spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> +-		return;
> >>> +-	}
> >>> +-
> >>> +-	/* Extract head of queue */
> >>> +-	drv_data->cur_msg = list_entry(drv_data->queue.next,
> >>> +-					struct spi_message, queue);
> >>> +-	list_del_init(&drv_data->cur_msg->queue);
> >>> ++	struct driver_data *drv_data = spi_master_get_devdata(master);
> >>> +
> >>> ++	drv_data->cur_msg = msg;
> >>> + 	/* Initial message state*/
> >>> + 	drv_data->cur_msg->state = START_STATE;
> >>> + 	drv_data->cur_transfer = list_entry(drv_data->cur_msg-
> >>> transfers.next,
> >>> +@@ -1213,34 +809,27 @@ static void pump_messages(struct work_struct
> >> *work)
> >>> +
> >>> + 	/* Mark as busy and launch transfers */
> >>> + 	tasklet_schedule(&drv_data->pump_transfers);
> >>> +-
> >>> +-	drv_data->busy = 1;
> >>> +-	spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> ++	return 0;
> >>> + }
> >>> +
> >>> +-static int transfer(struct spi_device *spi, struct spi_message *msg)
> >>> ++static int pxa2xx_spi_prepare_transfer(struct spi_master *master)
> >>> + {
> >>> +-	struct driver_data *drv_data = spi_master_get_devdata(spi-
> >>> master);
> >>> +-	unsigned long flags;
> >>> +-
> >>> +-	spin_lock_irqsave(&drv_data->lock, flags);
> >>> +-
> >>> +-	if (drv_data->run == QUEUE_STOPPED) {
> >>> +-		spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> +-		return -ESHUTDOWN;
> >>> +-	}
> >>> +-
> >>> +-	msg->actual_length = 0;
> >>> +-	msg->status = -EINPROGRESS;
> >>> +-	msg->state = START_STATE;
> >>> ++	struct driver_data *drv_data = spi_master_get_devdata(master);
> >>> +
> >>> +-	list_add_tail(&msg->queue, &drv_data->queue);
> >>> ++	pm_runtime_get_sync(&drv_data->pdev->dev);
> >>> ++	return 0;
> >>> ++}
> >>> +
> >>> +-	if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
> >>> +-		queue_work(drv_data->workqueue, &drv_data-
> >>> pump_messages);
> >>> ++static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
> >>> ++{
> >>> ++	struct driver_data *drv_data = spi_master_get_devdata(master);
> >>> +
> >>> +-	spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> ++	/* Disable the SSP now */
> >>> ++	write_SSCR0(read_SSCR0(drv_data->ioaddr) & ~SSCR0_SSE,
> >>> ++		    drv_data->ioaddr);
> >>> +
> >>> ++	pm_runtime_mark_last_busy(&drv_data->pdev->dev);
> >>> ++	pm_runtime_put_autosuspend(&drv_data->pdev->dev);
> >>> + 	return 0;
> >>> + }
> >>> +
> >>> +@@ -1287,10 +876,18 @@ static int setup(struct spi_device *spi)
> >>> + 	struct pxa2xx_spi_chip *chip_info = NULL;
> >>> + 	struct chip_data *chip;
> >>> + 	struct driver_data *drv_data = spi_master_get_devdata(spi-
> >>> master);
> >>> +-	struct ssp_device *ssp = drv_data->ssp;
> >>> + 	unsigned int clk_div;
> >>> +-	uint tx_thres = TX_THRESH_DFLT;
> >>> +-	uint rx_thres = RX_THRESH_DFLT;
> >>> ++	uint tx_thres, tx_hi_thres, rx_thres;
> >>> ++
> >>> ++	if (is_lpss_ssp(drv_data)) {
> >>> ++		tx_thres = LPSS_TX_LOTHRESH_DFLT;
> >>> ++		tx_hi_thres = LPSS_TX_HITHRESH_DFLT;
> >>> ++		rx_thres = LPSS_RX_THRESH_DFLT;
> >>> ++	} else {
> >>> ++		tx_thres = TX_THRESH_DFLT;
> >>> ++		tx_hi_thres = 0;
> >>> ++		rx_thres = RX_THRESH_DFLT;
> >>> ++	}
> >>> +
> >>> + 	if (!pxa25x_ssp_comp(drv_data)
> >>> + 		&& (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
> >>> +@@ -1330,8 +927,6 @@ static int setup(struct spi_device *spi)
> >>> + 			chip->gpio_cs = -1;
> >>> + 		chip->enable_dma = 0;
> >>> + 		chip->timeout = TIMOUT_DFLT;
> >>> +-		chip->dma_burst_size = drv_data->master_info-
> >>> enable_dma ?
> >>> +-					DCMD_BURST8 : 0;
> >>> + 	}
> >>> +
> >>> + 	/* protocol drivers may change the chip settings, so...
> >>> +@@ -1345,23 +940,37 @@ static int setup(struct spi_device *spi)
> >>> + 			chip->timeout = chip_info->timeout;
> >>> + 		if (chip_info->tx_threshold)
> >>> + 			tx_thres = chip_info->tx_threshold;
> >>> ++		if (chip_info->tx_hi_threshold)
> >>> ++			tx_hi_thres = chip_info->tx_hi_threshold;
> >>> + 		if (chip_info->rx_threshold)
> >>> + 			rx_thres = chip_info->rx_threshold;
> >>> + 		chip->enable_dma = drv_data->master_info->enable_dma;
> >>> + 		chip->dma_threshold = 0;
> >>> + 		if (chip_info->enable_loopback)
> >>> + 			chip->cr1 = SSCR1_LBM;
> >>> ++	} else if (ACPI_HANDLE(&spi->dev)) {
> >>> ++		/*
> >>> ++		 * Slave devices enumerated from ACPI namespace don't
> >>> ++		 * usually have chip_info but we still might want to use
> >>> ++		 * DMA with them.
> >>> ++		 */
> >>> ++		chip->enable_dma = drv_data->master_info->enable_dma;
> >>> + 	}
> >>> +
> >>> + 	chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
> >>> + 			(SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
> >>> +
> >>> ++	chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres);
> >>> ++	chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres)
> >>> ++				| SSITF_TxHiThresh(tx_hi_thres);
> >>> ++
> >>> + 	/* set dma burst and threshold outside of chip_info path so that if
> >>> + 	 * chip_info goes away after setting chip->enable_dma, the
> >>> + 	 * burst and threshold can still respond to changes in bits_per_word
> >> */
> >>> + 	if (chip->enable_dma) {
> >>> + 		/* set up legal burst and threshold for dma */
> >>> +-		if (set_dma_burst_and_threshold(chip, spi, spi-
> >>> bits_per_word,
> >>> ++		if (pxa2xx_spi_set_dma_burst_and_threshold(chip, spi,
> >>> ++						spi->bits_per_word,
> >>> + 						&chip->dma_burst_size,
> >>> + 						&chip->dma_threshold)) {
> >>> + 			dev_warn(&spi->dev, "in setup: DMA burst size
> >> reduced "
> >>> +@@ -1369,7 +978,7 @@ static int setup(struct spi_device *spi)
> >>> + 		}
> >>> + 	}
> >>> +
> >>> +-	clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz);
> >>> ++	clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz);
> >>> + 	chip->speed_hz = spi->max_speed_hz;
> >>> +
> >>> + 	chip->cr0 = clk_div
> >>> +@@ -1382,32 +991,32 @@ static int setup(struct spi_device *spi)
> >>> + 	chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
> >>> + 			| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
> >>> +
> >>> ++	if (spi->mode & SPI_LOOP)
> >>> ++		chip->cr1 |= SSCR1_LBM;
> >>> ++
> >>> + 	/* NOTE:  PXA25x_SSP _could_ use external clocking ... */
> >>> + 	if (!pxa25x_ssp_comp(drv_data))
> >>> + 		dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
> >>> +-			clk_get_rate(ssp->clk)
> >>> ++			drv_data->max_clk_rate
> >>> + 				/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
> >>> + 			chip->enable_dma ? "DMA" : "PIO");
> >>> + 	else
> >>> + 		dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
> >>> +-			clk_get_rate(ssp->clk) / 2
> >>> ++			drv_data->max_clk_rate / 2
> >>> + 				/ (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
> >>> + 			chip->enable_dma ? "DMA" : "PIO");
> >>> +
> >>> + 	if (spi->bits_per_word <= 8) {
> >>> + 		chip->n_bytes = 1;
> >>> +-		chip->dma_width = DCMD_WIDTH1;
> >>> + 		chip->read = u8_reader;
> >>> + 		chip->write = u8_writer;
> >>> + 	} else if (spi->bits_per_word <= 16) {
> >>> + 		chip->n_bytes = 2;
> >>> +-		chip->dma_width = DCMD_WIDTH2;
> >>> + 		chip->read = u16_reader;
> >>> + 		chip->write = u16_writer;
> >>> + 	} else if (spi->bits_per_word <= 32) {
> >>> + 		chip->cr0 |= SSCR0_EDSS;
> >>> + 		chip->n_bytes = 4;
> >>> +-		chip->dma_width = DCMD_WIDTH4;
> >>> + 		chip->read = u32_reader;
> >>> + 		chip->write = u32_writer;
> >>> + 	} else {
> >>> +@@ -1438,93 +1047,100 @@ static void cleanup(struct spi_device *spi)
> >>> + 	kfree(chip);
> >>> + }
> >>> +
> >>> +-static int init_queue(struct driver_data *drv_data)
> >>> ++#ifdef CONFIG_ACPI
> >>> ++static int pxa2xx_spi_acpi_add_dma(struct acpi_resource *res, void
> >> *data)
> >>> + {
> >>> +-	INIT_LIST_HEAD(&drv_data->queue);
> >>> +-	spin_lock_init(&drv_data->lock);
> >>> +-
> >>> +-	drv_data->run = QUEUE_STOPPED;
> >>> +-	drv_data->busy = 0;
> >>> +-
> >>> +-	tasklet_init(&drv_data->pump_transfers,
> >>> +-			pump_transfers,	(unsigned long)drv_data);
> >>> +-
> >>> +-	INIT_WORK(&drv_data->pump_messages, pump_messages);
> >>> +-	drv_data->workqueue = create_singlethread_workqueue(
> >>> +-				dev_name(drv_data->master->dev.parent));
> >>> +-	if (drv_data->workqueue == NULL)
> >>> +-		return -EBUSY;
> >>> ++	struct pxa2xx_spi_master *pdata = data;
> >>> ++
> >>> ++	if (res->type == ACPI_RESOURCE_TYPE_FIXED_DMA) {
> >>> ++		const struct acpi_resource_fixed_dma *dma;
> >>> ++
> >>> ++		dma = &res->data.fixed_dma;
> >>> ++		if (pdata->tx_slave_id < 0) {
> >>> ++			pdata->tx_slave_id = dma->request_lines;
> >>> ++			pdata->tx_chan_id = dma->channels;
> >>> ++		} else if (pdata->rx_slave_id < 0) {
> >>> ++			pdata->rx_slave_id = dma->request_lines;
> >>> ++			pdata->rx_chan_id = dma->channels;
> >>> ++		}
> >>> ++	}
> >>> +
> >>> +-	return 0;
> >>> ++	/* Tell the ACPI core to skip this resource */
> >>> ++	return 1;
> >>> + }
> >>> +
> >>> +-static int start_queue(struct driver_data *drv_data)
> >>> ++static struct pxa2xx_spi_master *
> >>> ++pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
> >>> + {
> >>> +-	unsigned long flags;
> >>> +-
> >>> +-	spin_lock_irqsave(&drv_data->lock, flags);
> >>> +-
> >>> +-	if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
> >>> +-		spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> +-		return -EBUSY;
> >>> ++	struct pxa2xx_spi_master *pdata;
> >>> ++	struct list_head resource_list;
> >>> ++	struct acpi_device *adev;
> >>> ++	struct ssp_device *ssp;
> >>> ++	struct resource *res;
> >>> ++	int devid;
> >>> ++
> >>> ++	if (!ACPI_HANDLE(&pdev->dev) ||
> >>> ++	    acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
> >>> ++		return NULL;
> >>> ++
> >>> ++	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> >>> ++	if (!pdata) {
> >>> ++		dev_err(&pdev->dev,
> >>> ++			"failed to allocate memory for platform data\n");
> >>> ++		return NULL;
> >>> + 	}
> >>> +
> >>> +-	drv_data->run = QUEUE_RUNNING;
> >>> +-	drv_data->cur_msg = NULL;
> >>> +-	drv_data->cur_transfer = NULL;
> >>> +-	drv_data->cur_chip = NULL;
> >>> +-	spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> +-
> >>> +-	queue_work(drv_data->workqueue, &drv_data->pump_messages);
> >>> ++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >>> ++	if (!res)
> >>> ++		return NULL;
> >>> +
> >>> +-	return 0;
> >>> +-}
> >>> ++	ssp = &pdata->ssp;
> >>> +
> >>> +-static int stop_queue(struct driver_data *drv_data)
> >>> +-{
> >>> +-	unsigned long flags;
> >>> +-	unsigned limit = 500;
> >>> +-	int status = 0;
> >>> +-
> >>> +-	spin_lock_irqsave(&drv_data->lock, flags);
> >>> +-
> >>> +-	/* This is a bit lame, but is optimized for the common execution path.
> >>> +-	 * A wait_queue on the drv_data->busy could be used, but then the
> >> common
> >>> +-	 * execution path (pump_messages) would be required to call
> >> wake_up or
> >>> +-	 * friends on every SPI message. Do this instead */
> >>> +-	drv_data->run = QUEUE_STOPPED;
> >>> +-	while ((!list_empty(&drv_data->queue) || drv_data->busy) &&
> >> limit--) {
> >>> +-		spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> +-		msleep(10);
> >>> +-		spin_lock_irqsave(&drv_data->lock, flags);
> >>> ++	ssp->phys_base = res->start;
> >>> ++	ssp->mmio_base = devm_request_and_ioremap(&pdev->dev, res);
> >>> ++	if (!ssp->mmio_base) {
> >>> ++		dev_err(&pdev->dev, "failed to ioremap mmio_base\n");
> >>> ++		return NULL;
> >>> + 	}
> >>> +
> >>> +-	if (!list_empty(&drv_data->queue) || drv_data->busy)
> >>> +-		status = -EBUSY;
> >>> ++	ssp->clk = devm_clk_get(&pdev->dev, NULL);
> >>> ++	ssp->irq = platform_get_irq(pdev, 0);
> >>> ++	ssp->type = LPSS_SSP;
> >>> ++	ssp->pdev = pdev;
> >>> +
> >>> +-	spin_unlock_irqrestore(&drv_data->lock, flags);
> >>> ++	ssp->port_id = -1;
> >>> ++	if (adev->pnp.unique_id && !kstrtoint(adev->pnp.unique_id, 0,
> >> &devid))
> >>> ++		ssp->port_id = devid;
> >>> +
> >>> +-	return status;
> >>> +-}
> >>> ++	pdata->num_chipselect = 1;
> >>> ++	pdata->rx_slave_id = -1;
> >>> ++	pdata->tx_slave_id = -1;
> >>> +
> >>> +-static int destroy_queue(struct driver_data *drv_data)
> >>> +-{
> >>> +-	int status;
> >>> ++	INIT_LIST_HEAD(&resource_list);
> >>> ++	acpi_dev_get_resources(adev, &resource_list,
> >> pxa2xx_spi_acpi_add_dma,
> >>> ++			       pdata);
> >>> ++	acpi_dev_free_resource_list(&resource_list);
> >>> +
> >>> +-	status = stop_queue(drv_data);
> >>> +-	/* we are unloading the module or failing to load (only two calls
> >>> +-	 * to this routine), and neither call can handle a return value.
> >>> +-	 * However, destroy_workqueue calls flush_workqueue, and that
> >> will
> >>> +-	 * block until all work is done.  If the reason that stop_queue
> >>> +-	 * timed out is that the work will never finish, then it does no
> >>> +-	 * good to call destroy_workqueue, so return anyway. */
> >>> +-	if (status != 0)
> >>> +-		return status;
> >>> ++	if (use_dma)
> >>> ++		pdata->enable_dma = pdata->rx_slave_id >= 0 && pdata-
> >>> tx_slave_id >= 0;
> >>> +
> >>> +-	destroy_workqueue(drv_data->workqueue);
> >>> ++	return pdata;
> >>> ++}
> >>> +
> >>> +-	return 0;
> >>> ++static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
> >>> ++	{ "INT33C0", 0 },
> >>> ++	{ "INT33C1", 0 },
> >>> ++	{ "80860F0E", 0 },
> >>> ++	{ },
> >>> ++};
> >>> ++MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
> >>> ++#else
> >>> ++static inline struct pxa2xx_spi_master *
> >>> ++pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
> >>> ++{
> >>> ++	return NULL;
> >>> + }
> >>> ++#endif
> >>> +
> >>> + static int pxa2xx_spi_probe(struct platform_device *pdev)
> >>> + {
> >>> +@@ -1535,11 +1151,21 @@ static int pxa2xx_spi_probe(struct
> >> platform_device *pdev)
> >>> + 	struct ssp_device *ssp;
> >>> + 	int status;
> >>> +
> >>> +-	platform_info = dev->platform_data;
> >>> ++	platform_info = dev_get_platdata(dev);
> >>> ++	if (!platform_info) {
> >>> ++		platform_info = pxa2xx_spi_acpi_get_pdata(pdev);
> >>> ++		if (!platform_info) {
> >>> ++			dev_err(&pdev->dev, "missing platform data\n");
> >>> ++			return -ENODEV;
> >>> ++		}
> >>> ++	}
> >>> +
> >>> + 	ssp = pxa_ssp_request(pdev->id, pdev->name);
> >>> +-	if (ssp == NULL) {
> >>> +-		dev_err(&pdev->dev, "failed to request SSP%d\n", pdev-
> >>> id);
> >>> ++	if (!ssp)
> >>> ++		ssp = &platform_info->ssp;
> >>> ++
> >>> ++	if (!ssp->mmio_base) {
> >>> ++		dev_err(&pdev->dev, "failed to get ssp\n");
> >>> + 		return -ENODEV;
> >>> + 	}
> >>> +
> >>> +@@ -1558,19 +1184,21 @@ static int pxa2xx_spi_probe(struct
> >> platform_device *pdev)
> >>> +
> >>> + 	master->dev.parent = &pdev->dev;
> >>> + 	master->dev.of_node = pdev->dev.of_node;
> >>> ++	ACPI_HANDLE_SET(&master->dev, ACPI_HANDLE(&pdev->dev));
> >>> + 	/* the spi->mode bits understood by this driver: */
> >>> +-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
> >>> ++	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
> >> SPI_LOOP;
> >>> +
> >>> +-	master->bus_num = pdev->id;
> >>> ++	master->bus_num = ssp->port_id;
> >>> + 	master->num_chipselect = platform_info->num_chipselect;
> >>> + 	master->dma_alignment = DMA_ALIGNMENT;
> >>> + 	master->cleanup = cleanup;
> >>> + 	master->setup = setup;
> >>> +-	master->transfer = transfer;
> >>> ++	master->transfer_one_message =
> >> pxa2xx_spi_transfer_one_message;
> >>> ++	master->prepare_transfer_hardware =
> >> pxa2xx_spi_prepare_transfer;
> >>> ++	master->unprepare_transfer_hardware =
> >> pxa2xx_spi_unprepare_transfer;
> >>> +
> >>> + 	drv_data->ssp_type = ssp->type;
> >>> +-	drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data +
> >>> +-						sizeof(struct driver_data)), 8);
> >>> ++	drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1],
> >> DMA_ALIGNMENT);
> >>> +
> >>> + 	drv_data->ioaddr = ssp->mmio_base;
> >>> + 	drv_data->ssdr_physical = ssp->phys_base + SSDR;
> >>> +@@ -1581,7 +1209,7 @@ static int pxa2xx_spi_probe(struct
> >> platform_device *pdev)
> >>> + 		drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
> >>> + 	} else {
> >>> + 		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
> >>> +-		drv_data->dma_cr1 = SSCR1_TSRE | SSCR1_RSRE |
> >> SSCR1_TINTE;
> >>> ++		drv_data->dma_cr1 = DEFAULT_DMA_CR1;
> >>> + 		drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
> >>> + 		drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS |
> >> SSSR_ROR;
> >>> + 	}
> >>> +@@ -1597,35 +1225,17 @@ static int pxa2xx_spi_probe(struct
> >> platform_device *pdev)
> >>> + 	drv_data->tx_channel = -1;
> >>> + 	drv_data->rx_channel = -1;
> >>> + 	if (platform_info->enable_dma) {
> >>> +-
> >>> +-		/* Get two DMA channels	(rx and tx) */
> >>> +-		drv_data->rx_channel =
> >> pxa_request_dma("pxa2xx_spi_ssp_rx",
> >>> +-							DMA_PRIO_HIGH,
> >>> +-							dma_handler,
> >>> +-							drv_data);
> >>> +-		if (drv_data->rx_channel < 0) {
> >>> +-			dev_err(dev, "problem (%d) requesting rx
> >> channel\n",
> >>> +-				drv_data->rx_channel);
> >>> +-			status = -ENODEV;
> >>> +-			goto out_error_irq_alloc;
> >>> ++		status = pxa2xx_spi_dma_setup(drv_data);
> >>> ++		if (status) {
> >>> ++			dev_warn(dev, "failed to setup DMA, using PIO\n");
> >>> ++			platform_info->enable_dma = false;
> >>> + 		}
> >>> +-		drv_data->tx_channel =
> >> pxa_request_dma("pxa2xx_spi_ssp_tx",
> >>> +-							DMA_PRIO_MEDIUM,
> >>> +-							dma_handler,
> >>> +-							drv_data);
> >>> +-		if (drv_data->tx_channel < 0) {
> >>> +-			dev_err(dev, "problem (%d) requesting tx
> >> channel\n",
> >>> +-				drv_data->tx_channel);
> >>> +-			status = -ENODEV;
> >>> +-			goto out_error_dma_alloc;
> >>> +-		}
> >>> +-
> >>> +-		DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data-
> >>> rx_channel;
> >>> +-		DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data-
> >>> tx_channel;
> >>> + 	}
> >>> +
> >>> + 	/* Enable SOC clock */
> >>> +-	clk_enable(ssp->clk);
> >>> ++	clk_prepare_enable(ssp->clk);
> >>> ++
> >>> ++	drv_data->max_clk_rate = clk_get_rate(ssp->clk);
> >>> +
> >>> + 	/* Load default SSP configuration */
> >>> + 	write_SSCR0(0, drv_data->ioaddr);
> >>> +@@ -1640,41 +1250,26 @@ static int pxa2xx_spi_probe(struct
> >> platform_device *pdev)
> >>> + 		write_SSTO(0, drv_data->ioaddr);
> >>> + 	write_SSPSP(0, drv_data->ioaddr);
> >>> +
> >>> +-	/* Initial and start queue */
> >>> +-	status = init_queue(drv_data);
> >>> +-	if (status != 0) {
> >>> +-		dev_err(&pdev->dev, "problem initializing queue\n");
> >>> +-		goto out_error_clock_enabled;
> >>> +-	}
> >>> +-	status = start_queue(drv_data);
> >>> +-	if (status != 0) {
> >>> +-		dev_err(&pdev->dev, "problem starting queue\n");
> >>> +-		goto out_error_clock_enabled;
> >>> +-	}
> >>> ++	lpss_ssp_setup(drv_data);
> >>> ++
> >>> ++	tasklet_init(&drv_data->pump_transfers, pump_transfers,
> >>> ++		     (unsigned long)drv_data);
> >>> +
> >>> + 	/* Register with the SPI framework */
> >>> + 	platform_set_drvdata(pdev, drv_data);
> >>> + 	status = spi_register_master(master);
> >>> + 	if (status != 0) {
> >>> + 		dev_err(&pdev->dev, "problem registering spi master\n");
> >>> +-		goto out_error_queue_alloc;
> >>> ++		goto out_error_clock_enabled;
> >>> + 	}
> >>> +
> >>> +-	return status;
> >>> ++	pm_runtime_forbid(&pdev->dev);
> >>> +
> >>> +-out_error_queue_alloc:
> >>> +-	destroy_queue(drv_data);
> >>> ++	return status;
> >>> +
> >>> + out_error_clock_enabled:
> >>> +-	clk_disable(ssp->clk);
> >>> +-
> >>> +-out_error_dma_alloc:
> >>> +-	if (drv_data->tx_channel != -1)
> >>> +-		pxa_free_dma(drv_data->tx_channel);
> >>> +-	if (drv_data->rx_channel != -1)
> >>> +-		pxa_free_dma(drv_data->rx_channel);
> >>> +-
> >>> +-out_error_irq_alloc:
> >>> ++	clk_disable_unprepare(ssp->clk);
> >>> ++	pxa2xx_spi_dma_release(drv_data);
> >>> + 	free_irq(ssp->irq, drv_data);
> >>> +
> >>> + out_error_master_alloc:
> >>> +@@ -1687,37 +1282,23 @@ static int pxa2xx_spi_remove(struct
> >> platform_device *pdev)
> >>> + {
> >>> + 	struct driver_data *drv_data = platform_get_drvdata(pdev);
> >>> + 	struct ssp_device *ssp;
> >>> +-	int status = 0;
> >>> +
> >>> + 	if (!drv_data)
> >>> + 		return 0;
> >>> + 	ssp = drv_data->ssp;
> >>> +
> >>> +-	/* Remove the queue */
> >>> +-	status = destroy_queue(drv_data);
> >>> +-	if (status != 0)
> >>> +-		/* the kernel does not check the return status of this
> >>> +-		 * this routine (mod->exit, within the kernel).  Therefore
> >>> +-		 * nothing is gained by returning from here, the module is
> >>> +-		 * going away regardless, and we should not leave any more
> >>> +-		 * resources allocated than necessary.  We cannot free the
> >>> +-		 * message memory in drv_data->queue, but we can release
> >> the
> >>> +-		 * resources below.  I think the kernel should honor -EBUSY
> >>> +-		 * returns but... */
> >>> +-		dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will
> >> not "
> >>> +-			"complete, message memory not freed\n");
> >>> ++	pm_runtime_get_sync(&pdev->dev);
> >>> +
> >>> + 	/* Disable the SSP at the peripheral and SOC level */
> >>> + 	write_SSCR0(0, drv_data->ioaddr);
> >>> +-	clk_disable(ssp->clk);
> >>> ++	clk_disable_unprepare(ssp->clk);
> >>> +
> >>> + 	/* Release DMA */
> >>> +-	if (drv_data->master_info->enable_dma) {
> >>> +-		DRCMR(ssp->drcmr_rx) = 0;
> >>> +-		DRCMR(ssp->drcmr_tx) = 0;
> >>> +-		pxa_free_dma(drv_data->tx_channel);
> >>> +-		pxa_free_dma(drv_data->rx_channel);
> >>> +-	}
> >>> ++	if (drv_data->master_info->enable_dma)
> >>> ++		pxa2xx_spi_dma_release(drv_data);
> >>> ++
> >>> ++	pm_runtime_put_noidle(&pdev->dev);
> >>> ++	pm_runtime_disable(&pdev->dev);
> >>> +
> >>> + 	/* Release IRQ */
> >>> + 	free_irq(ssp->irq, drv_data);
> >>> +@@ -1749,11 +1330,11 @@ static int pxa2xx_spi_suspend(struct device
> >> *dev)
> >>> + 	struct ssp_device *ssp = drv_data->ssp;
> >>> + 	int status = 0;
> >>> +
> >>> +-	status = stop_queue(drv_data);
> >>> ++	status = spi_master_suspend(drv_data->master);
> >>> + 	if (status != 0)
> >>> + 		return status;
> >>> + 	write_SSCR0(0, drv_data->ioaddr);
> >>> +-	clk_disable(ssp->clk);
> >>> ++	clk_disable_unprepare(ssp->clk);
> >>> +
> >>> + 	return 0;
> >>> + }
> >>> +@@ -1764,18 +1345,15 @@ static int pxa2xx_spi_resume(struct device
> >> *dev)
> >>> + 	struct ssp_device *ssp = drv_data->ssp;
> >>> + 	int status = 0;
> >>> +
> >>> +-	if (drv_data->rx_channel != -1)
> >>> +-		DRCMR(drv_data->ssp->drcmr_rx) =
> >>> +-			DRCMR_MAPVLD | drv_data->rx_channel;
> >>> +-	if (drv_data->tx_channel != -1)
> >>> +-		DRCMR(drv_data->ssp->drcmr_tx) =
> >>> +-			DRCMR_MAPVLD | drv_data->tx_channel;
> >>> ++	pxa2xx_spi_dma_resume(drv_data);
> >>> +
> >>> + 	/* Enable the SSP clock */
> >>> +-	clk_enable(ssp->clk);
> >>> ++	clk_prepare_enable(ssp->clk);
> >>> ++
> >>> ++	lpss_ssp_setup(drv_data);
> >>> +
> >>> + 	/* Start the queue running */
> >>> +-	status = start_queue(drv_data);
> >>> ++	status = spi_master_resume(drv_data->master);
> >>> + 	if (status != 0) {
> >>> + 		dev_err(dev, "problem starting queue (%d)\n", status);
> >>> + 		return status;
> >>> +@@ -1783,20 +1361,38 @@ static int pxa2xx_spi_resume(struct device
> >> *dev)
> >>> +
> >>> + 	return 0;
> >>> + }
> >>> ++#endif
> >>> ++
> >>> ++#ifdef CONFIG_PM_RUNTIME
> >>> ++static int pxa2xx_spi_runtime_suspend(struct device *dev)
> >>> ++{
> >>> ++	struct driver_data *drv_data = dev_get_drvdata(dev);
> >>> ++
> >>> ++	clk_disable_unprepare(drv_data->ssp->clk);
> >>> ++	return 0;
> >>> ++}
> >>> ++
> >>> ++static int pxa2xx_spi_runtime_resume(struct device *dev)
> >>> ++{
> >>> ++	struct driver_data *drv_data = dev_get_drvdata(dev);
> >>> ++
> >>> ++	clk_prepare_enable(drv_data->ssp->clk);
> >>> ++	return 0;
> >>> ++}
> >>> ++#endif
> >>> +
> >>> + static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
> >>> +-	.suspend	= pxa2xx_spi_suspend,
> >>> +-	.resume		= pxa2xx_spi_resume,
> >>> ++	SET_SYSTEM_SLEEP_PM_OPS(pxa2xx_spi_suspend,
> >> pxa2xx_spi_resume)
> >>> ++	SET_RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend,
> >>> ++			   pxa2xx_spi_runtime_resume, NULL)
> >>> + };
> >>> +-#endif
> >>> +
> >>> + static struct platform_driver driver = {
> >>> + 	.driver = {
> >>> + 		.name	= "pxa2xx-spi",
> >>> + 		.owner	= THIS_MODULE,
> >>> +-#ifdef CONFIG_PM
> >>> + 		.pm	= &pxa2xx_spi_pm_ops,
> >>> +-#endif
> >>> ++		.acpi_match_table = ACPI_PTR(pxa2xx_spi_acpi_match),
> >>> + 	},
> >>> + 	.probe = pxa2xx_spi_probe,
> >>> + 	.remove = pxa2xx_spi_remove,
> >>> +diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
> >>> +new file mode 100644
> >>> +index 0000000..5adc2a1
> >>> +--- /dev/null
> >>> ++++ b/drivers/spi/spi-pxa2xx.h
> >>> +@@ -0,0 +1,221 @@
> >>> ++/*
> >>> ++ * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
> >>> ++ * Copyright (C) 2013, Intel 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 SPI_PXA2XX_H
> >>> ++#define SPI_PXA2XX_H
> >>> ++
> >>> ++#include <linux/atomic.h>
> >>> ++#include <linux/dmaengine.h>
> >>> ++#include <linux/errno.h>
> >>> ++#include <linux/io.h>
> >>> ++#include <linux/interrupt.h>
> >>> ++#include <linux/platform_device.h>
> >>> ++#include <linux/pxa2xx_ssp.h>
> >>> ++#include <linux/scatterlist.h>
> >>> ++#include <linux/sizes.h>
> >>> ++#include <linux/spi/spi.h>
> >>> ++#include <linux/spi/pxa2xx_spi.h>
> >>> ++
> >>> ++struct driver_data {
> >>> ++	/* Driver model hookup */
> >>> ++	struct platform_device *pdev;
> >>> ++
> >>> ++	/* SSP Info */
> >>> ++	struct ssp_device *ssp;
> >>> ++
> >>> ++	/* SPI framework hookup */
> >>> ++	enum pxa_ssp_type ssp_type;
> >>> ++	struct spi_master *master;
> >>> ++
> >>> ++	/* PXA hookup */
> >>> ++	struct pxa2xx_spi_master *master_info;
> >>> ++
> >>> ++	/* PXA private DMA setup stuff */
> >>> ++	int rx_channel;
> >>> ++	int tx_channel;
> >>> ++	u32 *null_dma_buf;
> >>> ++
> >>> ++	/* SSP register addresses */
> >>> ++	void __iomem *ioaddr;
> >>> ++	u32 ssdr_physical;
> >>> ++
> >>> ++	/* SSP masks*/
> >>> ++	u32 dma_cr1;
> >>> ++	u32 int_cr1;
> >>> ++	u32 clear_sr;
> >>> ++	u32 mask_sr;
> >>> ++
> >>> ++	/* Maximun clock rate */
> >>> ++	unsigned long max_clk_rate;
> >>> ++
> >>> ++	/* Message Transfer pump */
> >>> ++	struct tasklet_struct pump_transfers;
> >>> ++
> >>> ++	/* DMA engine support */
> >>> ++	struct dma_chan *rx_chan;
> >>> ++	struct dma_chan *tx_chan;
> >>> ++	struct sg_table rx_sgt;
> >>> ++	struct sg_table tx_sgt;
> >>> ++	int rx_nents;
> >>> ++	int tx_nents;
> >>> ++	void *dummy;
> >>> ++	atomic_t dma_running;
> >>> ++
> >>> ++	/* Current message transfer state info */
> >>> ++	struct spi_message *cur_msg;
> >>> ++	struct spi_transfer *cur_transfer;
> >>> ++	struct chip_data *cur_chip;
> >>> ++	size_t len;
> >>> ++	void *tx;
> >>> ++	void *tx_end;
> >>> ++	void *rx;
> >>> ++	void *rx_end;
> >>> ++	int dma_mapped;
> >>> ++	dma_addr_t rx_dma;
> >>> ++	dma_addr_t tx_dma;
> >>> ++	size_t rx_map_len;
> >>> ++	size_t tx_map_len;
> >>> ++	u8 n_bytes;
> >>> ++	int (*write)(struct driver_data *drv_data);
> >>> ++	int (*read)(struct driver_data *drv_data);
> >>> ++	irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
> >>> ++	void (*cs_control)(u32 command);
> >>> ++
> >>> ++	void __iomem *lpss_base;
> >>> ++};
> >>> ++
> >>> ++struct chip_data {
> >>> ++	u32 cr0;
> >>> ++	u32 cr1;
> >>> ++	u32 psp;
> >>> ++	u32 timeout;
> >>> ++	u8 n_bytes;
> >>> ++	u32 dma_burst_size;
> >>> ++	u32 threshold;
> >>> ++	u32 dma_threshold;
> >>> ++	u16 lpss_rx_threshold;
> >>> ++	u16 lpss_tx_threshold;
> >>> ++	u8 enable_dma;
> >>> ++	u8 bits_per_word;
> >>> ++	u32 speed_hz;
> >>> ++	union {
> >>> ++		int gpio_cs;
> >>> ++		unsigned int frm;
> >>> ++	};
> >>> ++	int gpio_cs_inverted;
> >>> ++	int (*write)(struct driver_data *drv_data);
> >>> ++	int (*read)(struct driver_data *drv_data);
> >>> ++	void (*cs_control)(u32 command);
> >>> ++};
> >>> ++
> >>> ++#define DEFINE_SSP_REG(reg, off) \
> >>> ++static inline u32 read_##reg(void const __iomem *p) \
> >>> ++{ return __raw_readl(p + (off)); } \
> >>> ++\
> >>> ++static inline void write_##reg(u32 v, void __iomem *p) \
> >>> ++{ __raw_writel(v, p + (off)); }
> >>> ++
> >>> ++DEFINE_SSP_REG(SSCR0, 0x00)
> >>> ++DEFINE_SSP_REG(SSCR1, 0x04)
> >>> ++DEFINE_SSP_REG(SSSR, 0x08)
> >>> ++DEFINE_SSP_REG(SSITR, 0x0c)
> >>> ++DEFINE_SSP_REG(SSDR, 0x10)
> >>> ++DEFINE_SSP_REG(SSTO, 0x28)
> >>> ++DEFINE_SSP_REG(SSPSP, 0x2c)
> >>> ++DEFINE_SSP_REG(SSITF, SSITF)
> >>> ++DEFINE_SSP_REG(SSIRF, SSIRF)
> >>> ++
> >>> ++#define START_STATE ((void *)0)
> >>> ++#define RUNNING_STATE ((void *)1)
> >>> ++#define DONE_STATE ((void *)2)
> >>> ++#define ERROR_STATE ((void *)-1)
> >>> ++
> >>> ++#define IS_DMA_ALIGNED(x)	IS_ALIGNED((unsigned long)(x),
> >> DMA_ALIGNMENT)
> >>> ++#define DMA_ALIGNMENT		8
> >>> ++
> >>> ++static inline int pxa25x_ssp_comp(struct driver_data *drv_data)
> >>> ++{
> >>> ++	if (drv_data->ssp_type == PXA25x_SSP)
> >>> ++		return 1;
> >>> ++	if (drv_data->ssp_type == CE4100_SSP)
> >>> ++		return 1;
> >>> ++	return 0;
> >>> ++}
> >>> ++
> >>> ++static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val)
> >>> ++{
> >>> ++	void __iomem *reg = drv_data->ioaddr;
> >>> ++
> >>> ++	if (drv_data->ssp_type == CE4100_SSP)
> >>> ++		val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
> >>> ++
> >>> ++	write_SSSR(val, reg);
> >>> ++}
> >>> ++
> >>> ++extern int pxa2xx_spi_flush(struct driver_data *drv_data);
> >>> ++extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data);
> >>> ++
> >>> ++/*
> >>> ++ * Select the right DMA implementation.
> >>> ++ */
> >>> ++#if defined(CONFIG_SPI_PXA2XX_PXADMA)
> >>> ++#define SPI_PXA2XX_USE_DMA	1
> >>> ++#define MAX_DMA_LEN		8191
> >>> ++#define DEFAULT_DMA_CR1		(SSCR1_TSRE | SSCR1_RSRE |
> >> SSCR1_TINTE)
> >>> ++#elif defined(CONFIG_SPI_PXA2XX_DMA)
> >>> ++#define SPI_PXA2XX_USE_DMA	1
> >>> ++#define MAX_DMA_LEN		SZ_64K
> >>> ++#define DEFAULT_DMA_CR1		(SSCR1_TSRE | SSCR1_RSRE |
> >> SSCR1_TRAIL)
> >>> ++#else
> >>> ++#undef SPI_PXA2XX_USE_DMA
> >>> ++#define MAX_DMA_LEN		0
> >>> ++#define DEFAULT_DMA_CR1		0
> >>> ++#endif
> >>> ++
> >>> ++#ifdef SPI_PXA2XX_USE_DMA
> >>> ++extern bool pxa2xx_spi_dma_is_possible(size_t len);
> >>> ++extern int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data);
> >>> ++extern irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data
> >> *drv_data);
> >>> ++extern int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32
> >> dma_burst);
> >>> ++extern void pxa2xx_spi_dma_start(struct driver_data *drv_data);
> >>> ++extern int pxa2xx_spi_dma_setup(struct driver_data *drv_data);
> >>> ++extern void pxa2xx_spi_dma_release(struct driver_data *drv_data);
> >>> ++extern void pxa2xx_spi_dma_resume(struct driver_data *drv_data);
> >>> ++extern int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data
> >> *chip,
> >>> ++						  struct spi_device *spi,
> >>> ++						  u8 bits_per_word,
> >>> ++						  u32 *burst_code,
> >>> ++						  u32 *threshold);
> >>> ++#else
> >>> ++static inline bool pxa2xx_spi_dma_is_possible(size_t len) { return false; }
> >>> ++static inline int pxa2xx_spi_map_dma_buffers(struct driver_data
> >> *drv_data)
> >>> ++{
> >>> ++	return 0;
> >>> ++}
> >>> ++#define pxa2xx_spi_dma_transfer NULL
> >>> ++static inline void pxa2xx_spi_dma_prepare(struct driver_data *drv_data,
> >>> ++					  u32 dma_burst) {}
> >>> ++static inline void pxa2xx_spi_dma_start(struct driver_data *drv_data) {}
> >>> ++static inline int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
> >>> ++{
> >>> ++	return 0;
> >>> ++}
> >>> ++static inline void pxa2xx_spi_dma_release(struct driver_data *drv_data)
> >> {}
> >>> ++static inline void pxa2xx_spi_dma_resume(struct driver_data *drv_data)
> >> {}
> >>> ++static inline int pxa2xx_spi_set_dma_burst_and_threshold(struct
> >> chip_data *chip,
> >>> ++							 struct spi_device *spi,
> >>> ++							 u8 bits_per_word,
> >>> ++							 u32 *burst_code,
> >>> ++							 u32 *threshold)
> >>> ++{
> >>> ++	return -ENODEV;
> >>> ++}
> >>> ++#endif
> >>> ++
> >>> ++#endif /* SPI_PXA2XX_H */
> >>> +diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h
> >>> +index f366320..467cc63 100644
> >>> +--- a/include/linux/pxa2xx_ssp.h
> >>> ++++ b/include/linux/pxa2xx_ssp.h
> >>> +@@ -155,6 +155,14 @@
> >>> + #define SSACD_ACDS(x)		((x) << 0)	/* Audio clock divider
> >> select */
> >>> + #define SSACD_SCDX8		(1 << 7)	/* SYSCLK division ratio select
> >> */
> >>> +
> >>> ++/* LPSS SSP */
> >>> ++#define SSITF			0x44		/* TX FIFO trigger
> >> level */
> >>> ++#define SSITF_TxLoThresh(x)	(((x) - 1) << 8)
> >>> ++#define SSITF_TxHiThresh(x)	((x) - 1)
> >>> ++
> >>> ++#define SSIRF			0x48		/* RX FIFO trigger
> >> level */
> >>> ++#define SSIRF_RxThresh(x)	((x) - 1)
> >>> ++
> >>> + enum pxa_ssp_type {
> >>> + 	SSP_UNDEFINED = 0,
> >>> + 	PXA25x_SSP,  /* pxa 210, 250, 255, 26x */
> >>> +@@ -164,6 +172,7 @@ enum pxa_ssp_type {
> >>> + 	PXA168_SSP,
> >>> + 	PXA910_SSP,
> >>> + 	CE4100_SSP,
> >>> ++	LPSS_SSP,
> >>> + };
> >>> +
> >>> + struct ssp_device {
> >>> +@@ -206,6 +215,15 @@ static inline u32 pxa_ssp_read_reg(struct
> >> ssp_device *dev, u32 reg)
> >>> + 	return __raw_readl(dev->mmio_base + reg);
> >>> + }
> >>> +
> >>> ++#ifdef CONFIG_ARCH_PXA
> >>> + struct ssp_device *pxa_ssp_request(int port, const char *label);
> >>> + void pxa_ssp_free(struct ssp_device *);
> >>> ++#else
> >>> ++static inline struct ssp_device *pxa_ssp_request(int port, const char
> >> *label)
> >>> ++{
> >>> ++	return NULL;
> >>> ++}
> >>> ++static inline void pxa_ssp_free(struct ssp_device *ssp) {}
> >>> ++#endif
> >>> ++
> >>> + #endif
> >>> +diff --git a/include/linux/spi/pxa2xx_spi.h
> >> b/include/linux/spi/pxa2xx_spi.h
> >>> +index c73d144..82d5111 100644
> >>> +--- a/include/linux/spi/pxa2xx_spi.h
> >>> ++++ b/include/linux/spi/pxa2xx_spi.h
> >>> +@@ -28,6 +28,15 @@ struct pxa2xx_spi_master {
> >>> + 	u32 clock_enable;
> >>> + 	u16 num_chipselect;
> >>> + 	u8 enable_dma;
> >>> ++
> >>> ++	/* DMA engine specific config */
> >>> ++	int rx_chan_id;
> >>> ++	int tx_chan_id;
> >>> ++	int rx_slave_id;
> >>> ++	int tx_slave_id;
> >>> ++
> >>> ++	/* For non-PXA arches */
> >>> ++	struct ssp_device ssp;
> >>> + };
> >>> +
> >>> + /* spi_board_info.controller_data for SPI slave devices,
> >>> +@@ -35,6 +44,7 @@ struct pxa2xx_spi_master {
> >>> +  */
> >>> + struct pxa2xx_spi_chip {
> >>> + 	u8 tx_threshold;
> >>> ++	u8 tx_hi_threshold;
> >>> + 	u8 rx_threshold;
> >>> + 	u8 dma_burst_size;
> >>> + 	u32 timeout;
> >>> +@@ -50,103 +60,5 @@ struct pxa2xx_spi_chip {
> >>> +
> >>> + extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master
> >> *info);
> >>> +
> >>> +-#else
> >>> +-/*
> >>> +- * This is the implemtation for CE4100 on x86. ARM defines them in
> >> mach/ or
> >>> +- * plat/ include path.
> >>> +- * The CE4100 does not provide DMA support. This bits are here to let the
> >> driver
> >>> +- * compile and will never be used. Maybe we get DMA support at a later
> >> point in
> >>> +- * time.
> >>> +- */
> >>> +-
> >>> +-#define DCSR(n)         (n)
> >>> +-#define DSADR(n)        (n)
> >>> +-#define DTADR(n)        (n)
> >>> +-#define DCMD(n)         (n)
> >>> +-#define DRCMR(n)        (n)
> >>> +-
> >>> +-#define DCSR_RUN	(1 << 31)	/* Run Bit */
> >>> +-#define DCSR_NODESC	(1 << 30)	/* No-Descriptor Fetch */
> >>> +-#define DCSR_STOPIRQEN	(1 << 29)	/* Stop Interrupt Enable */
> >>> +-#define DCSR_REQPEND	(1 << 8)	/* Request Pending (read-only) */
> >>> +-#define DCSR_STOPSTATE	(1 << 3)	/* Stop State (read-only) */
> >>> +-#define DCSR_ENDINTR	(1 << 2)	/* End Interrupt */
> >>> +-#define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt */
> >>> +-#define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt */
> >>> +-
> >>> +-#define DCSR_EORIRQEN	(1 << 28)	/* End of Receive Interrupt
> >> Enable */
> >>> +-#define DCSR_EORJMPEN	(1 << 27)	/* Jump to next descriptor on
> >> EOR */
> >>> +-#define DCSR_EORSTOPEN	(1 << 26)	/* STOP on an EOR */
> >>> +-#define DCSR_SETCMPST	(1 << 25)	/* Set Descriptor Compare
> >> Status */
> >>> +-#define DCSR_CLRCMPST	(1 << 24)	/* Clear Descriptor Compare
> >> Status */
> >>> +-#define DCSR_CMPST	(1 << 10)	/* The Descriptor Compare
> >> Status */
> >>> +-#define DCSR_EORINTR	(1 << 9)	/* The end of Receive */
> >>> +-
> >>> +-#define DRCMR_MAPVLD	(1 << 7)	/* Map Valid */
> >>> +-#define DRCMR_CHLNUM	0x1f		/* mask for Channel Number
> >> */
> >>> +-
> >>> +-#define DDADR_DESCADDR	0xfffffff0	/* Address of next
> >> descriptor */
> >>> +-#define DDADR_STOP	(1 << 0)	/* Stop */
> >>> +-
> >>> +-#define DCMD_INCSRCADDR	(1 << 31)	/* Source Address
> >> Increment Setting. */
> >>> +-#define DCMD_INCTRGADDR	(1 << 30)	/* Target Address
> >> Increment Setting. */
> >>> +-#define DCMD_FLOWSRC	(1 << 29)	/* Flow Control by the source.
> >> */
> >>> +-#define DCMD_FLOWTRG	(1 << 28)	/* Flow Control by the target.
> >> */
> >>> +-#define DCMD_STARTIRQEN	(1 << 22)	/* Start Interrupt
> >> Enable */
> >>> +-#define DCMD_ENDIRQEN	(1 << 21)	/* End Interrupt Enable */
> >>> +-#define DCMD_ENDIAN	(1 << 18)	/* Device Endian-ness. */
> >>> +-#define DCMD_BURST8	(1 << 16)	/* 8 byte burst */
> >>> +-#define DCMD_BURST16	(2 << 16)	/* 16 byte burst */
> >>> +-#define DCMD_BURST32	(3 << 16)	/* 32 byte burst */
> >>> +-#define DCMD_WIDTH1	(1 << 14)	/* 1 byte width */
> >>> +-#define DCMD_WIDTH2	(2 << 14)	/* 2 byte width (HalfWord) */
> >>> +-#define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
> >>> +-#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1)
> >> */
> >>> +-
> >>> +-/*
> >>> +- * Descriptor structure for PXA's DMA engine
> >>> +- * Note: this structure must always be aligned to a 16-byte boundary.
> >>> +- */
> >>> +-
> >>> +-typedef enum {
> >>> +-	DMA_PRIO_HIGH = 0,
> >>> +-	DMA_PRIO_MEDIUM = 1,
> >>> +-	DMA_PRIO_LOW = 2
> >>> +-} pxa_dma_prio;
> >>> +-
> >>> +-/*
> >>> +- * DMA registration
> >>> +- */
> >>> +-
> >>> +-static inline int pxa_request_dma(char *name,
> >>> +-		pxa_dma_prio prio,
> >>> +-		void (*irq_handler)(int, void *),
> >>> +-		void *data)
> >>> +-{
> >>> +-	return -ENODEV;
> >>> +-}
> >>> +-
> >>> +-static inline void pxa_free_dma(int dma_ch)
> >>> +-{
> >>> +-}
> >>> +-
> >>> +-/*
> >>> +- * The CE4100 does not have the clk framework implemented and SPI
> >> clock can
> >>> +- * not be switched on/off or the divider changed.
> >>> +- */
> >>> +-static inline void clk_disable(struct clk *clk)
> >>> +-{
> >>> +-}
> >>> +-
> >>> +-static inline int clk_enable(struct clk *clk)
> >>> +-{
> >>> +-	return 0;
> >>> +-}
> >>> +-
> >>> +-static inline unsigned long clk_get_rate(struct clk *clk)
> >>> +-{
> >>> +-	return 3686400;
> >>> +-}
> >>> +-
> >>> + #endif
> >>> + #endif
> >>> +--
> >>> +1.7.10.4
> >>> +
> >>>
> >
> 

-- 
Darren Hart
Intel Open Source Technology Center
Yocto Project - Linux Kernel




More information about the linux-yocto mailing list