aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch')
-rw-r--r--recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch2349
1 files changed, 2349 insertions, 0 deletions
diff --git a/recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch b/recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch
new file mode 100644
index 0000000..7c89b92
--- /dev/null
+++ b/recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch
@@ -0,0 +1,2349 @@
+From xxxx Mon Sep 17 00:00:00 2001
+From: Dan O'Donovan <danielx.o'donovan@intel.com>
+Date: Thu, 13 Feb 2014 16:41:02 +0000
+Subject: [PATCH 19/21] Quark SC SPI
+
+---
+ drivers/spi/Kconfig | 39 ++-
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-gpio.c | 2 +-
+ drivers/spi/spi-pxa2xx-pci.c | 129 ++++-
+ drivers/spi/spi-pxa2xx.c | 1290 +++++++++++++++++++++++++++-------------
+ include/linux/pxa2xx_ssp.h | 25 +
+ include/linux/spi/pxa2xx_spi.h | 15 +-
+ include/linux/spi/spi.h | 2 +
+ 8 files changed, 1078 insertions(+), 425 deletions(-)
+
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 2e188e1..71358a6 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -35,6 +35,14 @@ config SPI_DEBUG
+ Say "yes" to enable debug messaging (like dev_dbg and pr_debug),
+ sysfs, and debugfs support in SPI controller and protocol drivers.
+
++config GEN3_SPI
++ bool "Intel Media SOC SPI support"
++ depends on SPI && ARCH_GEN3 && INTEL_QUARK_X1000_SOC
++ default y
++ help
++ This option enables Intel Media SOC SPI support.
++ For Quark this option depends on INTEL_QUARK_X1000_SOC.
++
+ #
+ # MASTER side ... talking to discrete SPI slave chips including microcontrollers
+ #
+@@ -74,7 +82,15 @@ config SPI_ATMEL
+ This selects a driver for the Atmel SPI Controller, present on
+ many AT32 (AVR32) and AT91 (ARM) chips.
+
+-config SPI_BFIN5XX
++config SPI_CE5XX_SPI_FLASH
++ tristate "CE5XX SPI FLASH"
++ depends on ARCH_GEN3 && HW_MUTEXES
++ default y
++ help
++ This selects a driver for CE5XX Serial Flash controler
++
++
++config SPI_BFIN
+ tristate "SPI controller driver for ADI Blackfin5xx"
+ depends on BLACKFIN
+ help
+@@ -302,12 +318,21 @@ config SPI_PXA2XX
+ depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
+ select PXA_SSP if ARCH_PXA
+ help
+- This enables using a PXA2xx or Sodaville SSP port as a SPI master
++ This enables using a PXA2xx or Intel CE4100/CE4200/CE5300 port as a SPI master
+ controller. The driver can be configured to use any SSP port and
+ additional documentation can be found a Documentation/spi/pxa2xx.
+
+ config SPI_PXA2XX_PCI
+- def_bool SPI_PXA2XX && X86_32 && PCI
++ tristate "Intel CE SPI PCI adapter"
++ depends on SPI_PXA2XX && X86_32 && PCI && GEN3_SPI
++ help
++ This driver supports the Intel CE SPI master controller and acts
++ as the PCI-SPI glue code for PXA's driver
++
++config SPI_CE5XX_SPI_SLAVE
++ tristate "CE5XX SPI SLAVE"
++ help
++ This selects a driver for CE5XX SPI Slave controler, it is emudulated into a spi device
+
+ config SPI_RSPI
+ tristate "Renesas RSPI controller"
+@@ -471,6 +496,14 @@ config SPI_DW_MMIO
+ depends on SPI_DESIGNWARE && HAVE_CLK
+
+ #
++# Bring out the LPC_SCH SPI block
++#
++
++config SPI_LPC_SCH
++ tristate "LPC SCH Legacy SPI controller"
++ depends on LPC_SCH
++
++#
+ # There are lots of SPI device types, with sensors and memory
+ # being probably the most widely used ones.
+ #
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index 64e970b..b67de97 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -26,6 +26,7 @@ obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
+ obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
+ obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
+ spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
++obj-$(CONFIG_SPI_LPC_SCH) += spi-lpc-sch.o
+ obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
+ obj-$(CONFIG_SPI_FALCON) += spi-falcon.o
+ obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
+diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
+index c7cf0b7..0fa345c 100644
+--- a/drivers/spi/spi-gpio.c
++++ b/drivers/spi/spi-gpio.c
+@@ -265,9 +265,9 @@ static int spi_gpio_setup(struct spi_device *spi)
+ }
+ }
+ if (!status) {
+- status = spi_bitbang_setup(spi);
+ /* in case it was initialized from static board data */
+ spi_gpio->cs_gpios[spi->chip_select] = cs;
++ status = spi_bitbang_setup(spi);
+ }
+
+ if (status) {
+diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
+index cf95587..5250cd9 100644
+--- a/drivers/spi/spi-pxa2xx-pci.c
++++ b/drivers/spi/spi-pxa2xx-pci.c
+@@ -7,6 +7,47 @@
+ #include <linux/of_device.h>
+ #include <linux/module.h>
+ #include <linux/spi/pxa2xx_spi.h>
++#include <linux/irq.h>
++#include <linux/platform_data/quark.h>
++
++/* defined here to avoid including arch/x86/pci/intel_media_proc_gen3.c */
++#define CE3100_SOC_DEVICE_ID 0x2E50
++#define CE4100_SOC_DEVICE_ID 0x0708
++#define CE4200_SOC_DEVICE_ID 0x0709
++#define CE5300_SOC_DEVICE_ID 0x0C40
++#define CE2600_SOC_DEVICE_ID 0x0931
++
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC_FPGAEMU
++#define CE4200_NUM_SPI_MASTER 1
++#else
++#define CE4200_NUM_SPI_MASTER 2
++#endif
++
++#define CE4X00_SPI_MAX_SPEED 1843200
++
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++#define CE4200_NUM_CHIPSELECT 2
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC_FPGAEMU
++#define CE5X00_SPI_MAX_SPEED 3500000
++#else
++#define CE5X00_SPI_MAX_SPEED 50000000
++#endif
++#else
++#define CE4200_NUM_CHIPSELECT 4
++#define CE5X00_SPI_MAX_SPEED 5000000
++#endif
++
++#define SPI_CE_DEBUG
++
++static int interface;
++
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++static int enable_msi = 1;
++#else
++static int enable_msi;
++#endif
++module_param(enable_msi, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(enable_msi, "Enable PCI MSI mode");
+
+ struct ce4100_info {
+ struct ssp_device ssp;
+@@ -57,10 +98,11 @@ static int ce4100_spi_probe(struct pci_dev *dev,
+ int ret;
+ resource_size_t phys_beg;
+ resource_size_t phys_len;
+- struct ce4100_info *spi_info;
++ struct ce4100_info *spi_info = NULL;
+ struct platform_device *pdev;
+ struct pxa2xx_spi_master spi_pdata;
+ struct ssp_device *ssp;
++ unsigned int id;
+
+ ret = pci_enable_device(dev);
+ if (ret)
+@@ -77,42 +119,75 @@ static int ce4100_spi_probe(struct pci_dev *dev,
+ }
+
+ pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
++ if (!pdev) {
++ ret = -ENOMEM;
++ goto err_release_mem_region;
++ }
+ spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
+- if (!pdev || !spi_info ) {
++ if (!spi_info) {
+ ret = -ENOMEM;
+- goto err_nomem;
++ goto err_platform_device_put;
+ }
+ memset(&spi_pdata, 0, sizeof(spi_pdata));
+- spi_pdata.num_chipselect = dev->devfn;
++ spi_pdata.num_chipselect = CE4200_NUM_CHIPSELECT;
+
+ ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata));
+ if (ret)
+- goto err_nomem;
++ goto err_free_spi_info;
+
++ pdev->id = interface;
+ pdev->dev.parent = &dev->dev;
++#ifdef CONFIG_OF
+ pdev->dev.of_node = dev->dev.of_node;
++#endif
+ ssp = &spi_info->ssp;
++ ssp->pcidev = dev;
+ ssp->phys_base = pci_resource_start(dev, 0);
+ ssp->mmio_base = ioremap(phys_beg, phys_len);
+ if (!ssp->mmio_base) {
+ dev_err(&pdev->dev, "failed to ioremap() registers\n");
+ ret = -EIO;
+- goto err_nomem;
++ goto err_ioremap;
++ }
++ pci_set_master(dev);
++ if (enable_msi == 1) {
++ ret = pci_enable_msi(dev);
++ if (ret) {
++ dev_err(&dev->dev, "failed to allocate MSI entry\n");
++ goto err_dev_add;
++ }
+ }
++
+ ssp->irq = dev->irq;
+ ssp->port_id = pdev->id;
+- ssp->type = PXA25x_SSP;
+
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ id = CE5300_SOC_DEVICE_ID;
++#else
++ intelce_get_soc_info(&id, NULL);
++#endif
++ switch (id) {
++ case CE5300_SOC_DEVICE_ID:
++ ssp->type = CE5X00_SSP;
++ break;
++ case CE4200_SOC_DEVICE_ID:
++ default:
++ ssp->type = CE4100_SSP;
++ break;
++ }
+ mutex_lock(&ssp_lock);
+ list_add(&ssp->node, &ssp_list);
+ mutex_unlock(&ssp_lock);
+
+ pci_set_drvdata(dev, spi_info);
+
++ spi_info->spi_pdev = pdev;
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto err_dev_add;
+
++ interface++;
++
+ return ret;
+
+ err_dev_add:
+@@ -121,11 +196,16 @@ err_dev_add:
+ list_del(&ssp->node);
+ mutex_unlock(&ssp_lock);
+ iounmap(ssp->mmio_base);
++err_ioremap:
+
+-err_nomem:
+- release_mem_region(phys_beg, phys_len);
+- platform_device_put(pdev);
++err_free_spi_info:
+ kfree(spi_info);
++
++err_platform_device_put:
++ platform_device_put(pdev);
++
++err_release_mem_region:
++ release_mem_region(phys_beg, phys_len);
+ return ret;
+ }
+
+@@ -146,21 +226,50 @@ static void ce4100_spi_remove(struct pci_dev *dev)
+ list_del(&ssp->node);
+ mutex_unlock(&ssp_lock);
+
++ if (enable_msi == 1) {
++ if (pci_dev_msi_enabled(dev))
++ pci_disable_msi(dev);
++ }
++
+ pci_set_drvdata(dev, NULL);
+ pci_disable_device(dev);
+ kfree(spi_info);
+ }
+
++
++#ifdef CONFIG_PM
++static int ce4XXX_spi_suspend(struct pci_dev *dev, pm_message_t state)
++{
++ pci_save_state(dev);
++ pci_set_power_state(dev, pci_choose_state(dev, state));
++ return 0;
++}
++
++static int ce4XXX_spi_resume(struct pci_dev *dev)
++{
++ pci_set_power_state(dev, PCI_D0);
++ pci_restore_state(dev);
++
++ return 0;
++}
++#endif
++
+ static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0935) },
+ { },
+ };
++
+ MODULE_DEVICE_TABLE(pci, ce4100_spi_devices);
+
+ static struct pci_driver ce4100_spi_driver = {
+ .name = "ce4100_spi",
+ .id_table = ce4100_spi_devices,
+ .probe = ce4100_spi_probe,
++#ifdef CONFIG_PM
++ .suspend = ce4XXX_spi_suspend,
++ .resume = ce4XXX_spi_resume,
++#endif
+ .remove = ce4100_spi_remove,
+ };
+
+diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
+index 5c8c4f5..4860e85 100644
+--- a/drivers/spi/spi-pxa2xx.c
++++ b/drivers/spi/spi-pxa2xx.c
+@@ -26,14 +26,18 @@
+ #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/clk.h>
+ #include <linux/gpio.h>
+ #include <linux/slab.h>
++#include <linux/io.h>
++#include <linux/delay.h>
++#include <linux/pm_runtime.h>
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++#include <asm/qrk.h>
++#endif
+
+-#include <asm/io.h>
+ #include <asm/irq.h>
+-#include <asm/delay.h>
+
+
+ MODULE_AUTHOR("Stephen Street");
+@@ -51,6 +55,9 @@ MODULE_ALIAS("platform:pxa2xx-spi");
+ #define MAX_DMA_LEN 8191
+ #define DMA_ALIGNMENT 8
+
++#define CE5X00_FIFO_DEPTH 32
++#define CE4X00_FIFO_DEPTH 4
++
+ /*
+ * for testing SSCR1 changes that require SSP restart, basically
+ * everything except the service and interrupt enables, the pxa270 developer
+@@ -59,35 +66,144 @@ MODULE_ALIAS("platform:pxa2xx-spi");
+ * service and interrupt enables
+ */
+ #define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
+- | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
+- | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
+- | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
+- | 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)
++ | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
++ | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
++ | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
++ | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
++ | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
++
++#define CE5X00_SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
++ | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
++ | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
++ | SSCR1_IFS | CE5X00_SSCR1_STRF \
++ | CE5X00_SSCR1_EFWR \
++ | CE5X00_SSCR1_RFT | CE5X00_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)
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++DEFINE_SSP_REG(dds_rate, 0x28) /* SSTO unused for qrk */
++#endif
++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
+
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++#define DDS_MAX 0x800000
++#define DDS_666666 0x666666
++#define DDS_400000 0x400000
++#define DDS_200000 0x200000
++#define DDS_100000 0x100000
++#define DDS_80000 0x80000
++#define DDS_40000 0x40000
++#define DDS_20000 0x20000
++#define DDS_10000 0x10000
++#define DDS_8000 0x8000
++
++#if defined(CONFIG_INTEL_QUARK_X1000_SOC_FPGAEMU)
++/* these values are different on emulations where system clock is 14mhz */
++#define FSYS 14 /* mhz */
++#define BITRATE_50MHZ 3500000
++#define BITRATE_40MHZ 2800000
++#define BITRATE_25MHZ 1750000
++#define BITRATE_20MHZ 1400000
++#define BITRATE_16667KHZ 1167000
++#define BITRATE_13333KHZ 933000
++#define BITRATE_12500KHZ 875000
++#define BITRATE_10MHZ 700000
++#define BITRATE_8MHZ 560000
++#define BITRATE_6250KHZ 438000
++#define BITRATE_5MHZ 350000
++#define BITRATE_4MHZ 280000
++#define BITRATE_3125KHZ 219000
++#define BITRATE_2500KHZ 175000
++#define BITRATE_2MHZ 140000
++#define BITRATE_1563KHZ 109000
++#define BITRATE_1250KHZ 88000
++#define BITRATE_1MHZ 70000
++#define BITRATE_800KHZ 56000
++#define BITRATE_781KHZ 54688
++#define BITRATE_625KHZ 43750
++#define BITRATE_500KHZ 35000
++#define BITRATE_400KHZ 28000
++#define BITRATE_390KHZ 27344
++#define BITRATE_250KHZ 17500
++#define BITRATE_200KHZ 14000
++#define BITRATE_195KHZ 13672
++#define BITRATE_125KHZ 8750
++#define BITRATE_100KHZ 7000
++#define BITRATE_50KHZ 3500
++#define BITRATE_25KHZ 1750
++#define BITRATE_10KHZ 701
++#define BITRATE_5KHZ 353
++#define BITRATE_1KHZ 70
++#define BITRATE_MAX BITRATE_50MHZ
++#define BITRATE_MIN BITRATE_1KHZ
++
++#else
++
++#define BITRATE_50MHZ 50000000
++#define BITRATE_40MHZ 40000000
++#define BITRATE_25MHZ 25000000
++#define BITRATE_20MHZ 20000000
++#define BITRATE_16667KHZ 16667000
++#define BITRATE_13333KHZ 13333000
++#define BITRATE_12500KHZ 12500000
++#define BITRATE_10MHZ 10000000
++#define BITRATE_8MHZ 8000000
++#define BITRATE_6250KHZ 6250000
++#define BITRATE_5MHZ 5000000
++#define BITRATE_4MHZ 4000000
++#define BITRATE_3125KHZ 3125000
++#define BITRATE_2500KHZ 2500000
++#define BITRATE_2MHZ 2000000
++#define BITRATE_1563KHZ 1563000
++#define BITRATE_1250KHZ 1250000
++#define BITRATE_1MHZ 1000000
++#define BITRATE_800KHZ 800000
++#define BITRATE_781KHZ 781250
++#define BITRATE_625KHZ 625000
++#define BITRATE_500KHZ 500000
++#define BITRATE_400KHZ 400000
++#define BITRATE_390KHZ 390625
++#define BITRATE_250KHZ 250000
++#define BITRATE_200KHZ 200000
++#define BITRATE_195KHZ 195313
++#define BITRATE_125KHZ 125000
++#define BITRATE_100KHZ 100000
++#define BITRATE_50KHZ 50000
++#define BITRATE_25KHZ 25000
++#define BITRATE_10KHZ 10016
++#define BITRATE_5KHZ 5040
++#define BITRATE_1KHZ 1000
++#define BITRATE_MIN BITRATE_1KHZ
++#define BITRATE_MAX BITRATE_50MHZ
++#define FSYS 200 /* mhz */
++
++#endif /* #if defined(CONFIG_INTEL_QUARK_X1000_SOC_FPGAEMU) */
++
++#endif /* CONFIG_INTEL_QUARK_X1000_SOC */
++
+ struct driver_data {
+ /* Driver model hookup */
+ struct platform_device *pdev;
+@@ -117,20 +233,12 @@ struct driver_data {
+ 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 */
++ /* Message per-transfer pump */
+ struct tasklet_struct pump_transfers;
+
+ /* Current message transfer state info */
+- struct spi_message* cur_msg;
+- struct spi_transfer* cur_transfer;
++ struct spi_message *cur_msg;
++ struct spi_transfer *cur_transfer;
+ struct chip_data *cur_chip;
+ size_t len;
+ void *tx;
+@@ -153,6 +261,9 @@ struct driver_data {
+ struct chip_data {
+ u32 cr0;
+ u32 cr1;
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ u32 dds_rate;
++#endif
+ u32 psp;
+ u32 timeout;
+ u8 n_bytes;
+@@ -173,14 +284,14 @@ struct chip_data {
+ void (*cs_control)(u32 command);
+ };
+
+-static void pump_messages(struct work_struct *work);
+-
+ static void cs_assert(struct driver_data *drv_data)
+ {
+ struct chip_data *chip = drv_data->cur_chip;
+
+- if (drv_data->ssp_type == CE4100_SSP) {
+- write_SSSR(drv_data->cur_chip->frm, drv_data->ioaddr);
++ if (drv_data->ssp_type == CE4100_SSP ||
++ (drv_data->ssp_type == CE5X00_SSP &&
++ (!gpio_is_valid(chip->gpio_cs)))) {
++ write_sssr(drv_data->cur_chip->frm, drv_data->ioaddr);
+ return;
+ }
+
+@@ -197,9 +308,11 @@ static void cs_deassert(struct driver_data *drv_data)
+ {
+ struct chip_data *chip = drv_data->cur_chip;
+
+- if (drv_data->ssp_type == CE4100_SSP)
++ if (drv_data->ssp_type == CE4100_SSP ||
++ (drv_data->ssp_type == CE5X00_SSP
++ && (!gpio_is_valid(chip->gpio_cs)))) {
+ return;
+-
++ }
+ if (chip->cs_control) {
+ chip->cs_control(PXA2XX_CS_DEASSERT);
+ return;
+@@ -209,14 +322,15 @@ static void cs_deassert(struct driver_data *drv_data)
+ gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
+ }
+
+-static void write_SSSR_CS(struct driver_data *drv_data, u32 val)
++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;
++ if (drv_data->ssp_type == CE4100_SSP
++ || drv_data->ssp_type == CE5X00_SSP)
++ val |= read_sssr(reg) & SSSR_ALT_FRM_MASK;
+
+- write_SSSR(val, reg);
++ write_sssr(val, reg);
+ }
+
+ static int pxa25x_ssp_comp(struct driver_data *drv_data)
+@@ -225,6 +339,10 @@ static int pxa25x_ssp_comp(struct driver_data *drv_data)
+ return 1;
+ if (drv_data->ssp_type == CE4100_SSP)
+ return 1;
++#ifdef CONFIG_GEN3_SPI
++ if (drv_data->ssp_type == CE5X00_SSP)
++ return 2;
++#endif
+ return 0;
+ }
+
+@@ -235,25 +353,46 @@ static int flush(struct driver_data *drv_data)
+ void __iomem *reg = drv_data->ioaddr;
+
+ do {
+- while (read_SSSR(reg) & SSSR_RNE) {
+- read_SSDR(reg);
+- }
+- } while ((read_SSSR(reg) & SSSR_BSY) && --limit);
+- write_SSSR_CS(drv_data, SSSR_ROR);
++ while (read_sssr(reg) & SSSR_RNE)
++ read_ssdr(reg);
++ } while ((read_sssr(reg) & SSSR_BSY) && --limit);
++ write_sssr_cs(drv_data, SSSR_ROR);
+
+ return limit;
+ }
+
++#ifdef CONFIG_GEN3_SPI
++static void wait_till_not_busy(struct driver_data *drv_data)
++{
++ /*
++ * Most cases, the BSY bit will be cleared in very short time.
++ * But if the controller is set to the slowest speed, the BSY
++ * bit waitting time will increase a lot.
++ * Here, we set the wait time to 100ms is to deal with such corner case,
++ * but in real world, there is almost no one will use the slowest
++ * speed to transfer data, which means there is no need to add more
++ * complex code to to deal with the slowest speed case.
++ */
++ unsigned long end = jiffies + 1 + usecs_to_jiffies(100000);
++ void __iomem *reg = drv_data->ioaddr;
++ while (time_before(jiffies, end)) {
++ if (!(read_sssr(reg) & SSSR_BSY))
++ return;
++ }
++ pr_err("SPI MASTER keeps busy for 100ms after a read/write!\n");
++}
++#endif
++
+ static int null_writer(struct driver_data *drv_data)
+ {
+ void __iomem *reg = drv_data->ioaddr;
+ u8 n_bytes = drv_data->n_bytes;
+
+- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+- || (drv_data->tx == drv_data->tx_end))
++ if ((!(read_sssr(reg) & SSSR_TNF))
++ || (drv_data->tx == drv_data->tx_end))
+ return 0;
+
+- write_SSDR(0, reg);
++ write_ssdr(0, reg);
+ drv_data->tx += n_bytes;
+
+ return 1;
+@@ -264,9 +403,9 @@ static int null_reader(struct driver_data *drv_data)
+ void __iomem *reg = drv_data->ioaddr;
+ u8 n_bytes = drv_data->n_bytes;
+
+- while ((read_SSSR(reg) & SSSR_RNE)
++ while ((read_sssr(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+- read_SSDR(reg);
++ read_ssdr(reg);
+ drv_data->rx += n_bytes;
+ }
+
+@@ -277,11 +416,11 @@ static int u8_writer(struct driver_data *drv_data)
+ {
+ void __iomem *reg = drv_data->ioaddr;
+
+- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+- || (drv_data->tx == drv_data->tx_end))
++ if ((!(read_sssr(reg) & SSSR_TNF))
++ || (drv_data->tx == drv_data->tx_end))
+ return 0;
+
+- write_SSDR(*(u8 *)(drv_data->tx), reg);
++ write_ssdr(*(u8 *)(drv_data->tx), reg);
+ ++drv_data->tx;
+
+ return 1;
+@@ -291,9 +430,9 @@ static int u8_reader(struct driver_data *drv_data)
+ {
+ void __iomem *reg = drv_data->ioaddr;
+
+- while ((read_SSSR(reg) & SSSR_RNE)
+- && (drv_data->rx < drv_data->rx_end)) {
+- *(u8 *)(drv_data->rx) = read_SSDR(reg);
++ while ((read_sssr(reg) & SSSR_RNE)
++ && (drv_data->rx < drv_data->rx_end)) {
++ *(u8 *)(drv_data->rx) = read_ssdr(reg);
+ ++drv_data->rx;
+ }
+
+@@ -304,11 +443,11 @@ static int u16_writer(struct driver_data *drv_data)
+ {
+ void __iomem *reg = drv_data->ioaddr;
+
+- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+- || (drv_data->tx == drv_data->tx_end))
++ if ((!(read_sssr(reg) & SSSR_TNF))
++ || (drv_data->tx == drv_data->tx_end))
+ return 0;
+
+- write_SSDR(*(u16 *)(drv_data->tx), reg);
++ write_ssdr(*(u16 *)(drv_data->tx), reg);
+ drv_data->tx += 2;
+
+ return 1;
+@@ -318,9 +457,9 @@ static int u16_reader(struct driver_data *drv_data)
+ {
+ void __iomem *reg = drv_data->ioaddr;
+
+- while ((read_SSSR(reg) & SSSR_RNE)
+- && (drv_data->rx < drv_data->rx_end)) {
+- *(u16 *)(drv_data->rx) = read_SSDR(reg);
++ while ((read_sssr(reg) & SSSR_RNE)
++ && (drv_data->rx < drv_data->rx_end)) {
++ *(u16 *)(drv_data->rx) = read_ssdr(reg);
+ drv_data->rx += 2;
+ }
+
+@@ -331,11 +470,11 @@ static int u32_writer(struct driver_data *drv_data)
+ {
+ void __iomem *reg = drv_data->ioaddr;
+
+- if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+- || (drv_data->tx == drv_data->tx_end))
++ if ((!(read_sssr(reg) & SSSR_TNF))
++ || (drv_data->tx == drv_data->tx_end))
+ return 0;
+
+- write_SSDR(*(u32 *)(drv_data->tx), reg);
++ write_ssdr(*(u32 *)(drv_data->tx), reg);
+ drv_data->tx += 4;
+
+ return 1;
+@@ -345,9 +484,9 @@ static int u32_reader(struct driver_data *drv_data)
+ {
+ void __iomem *reg = drv_data->ioaddr;
+
+- while ((read_SSSR(reg) & SSSR_RNE)
+- && (drv_data->rx < drv_data->rx_end)) {
+- *(u32 *)(drv_data->rx) = read_SSDR(reg);
++ while ((read_sssr(reg) & SSSR_RNE)
++ && (drv_data->rx < drv_data->rx_end)) {
++ *(u32 *)(drv_data->rx) = read_ssdr(reg);
+ drv_data->rx += 4;
+ }
+
+@@ -443,20 +582,11 @@ static void unmap_dma_buffers(struct driver_data *drv_data)
+ /* 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;
++ struct spi_transfer *last_transfer;
+
+- 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,
+- transfer_list);
++ last_transfer = list_entry(drv_data->cur_msg->transfers.prev,
++ struct spi_transfer,
++ transfer_list);
+
+ /* Delay if requested before any change in chip select */
+ if (last_transfer->delay_usecs)
+@@ -475,41 +605,33 @@ static void giveback(struct driver_data *drv_data)
+ * time with the following tests unless this was hinted.
+ *
+ * We cannot postpone this until pump_messages, because
+- * after calling msg->complete (below) the driver that
+- * sent the current message could be unloaded, which
+- * could invalidate the cs_control() callback...
++ * after calling spi_finalize_current_message (below) the
++ * driver that sent the current message could be unloaded,
++ * which could invalidate the cs_control() callback...
+ */
+-
+ /* 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
+ */
+- if (next_msg && next_msg->spi != msg->spi)
++ if (next_msg && next_msg->spi != drv_data->cur_msg->spi)
+ next_msg = NULL;
+- if (!next_msg || msg->state == ERROR_STATE)
++ if (!next_msg || drv_data->cur_msg->state == ERROR_STATE)
+ cs_deassert(drv_data);
+ }
+
+- msg->state = NULL;
+- if (msg->complete)
+- msg->complete(msg->context);
+-
++ drv_data->cur_msg = NULL;
++ drv_data->cur_transfer = NULL;
+ drv_data->cur_chip = NULL;
++ spi_finalize_current_message(drv_data->master);
+ }
+
+ static int wait_ssp_rx_stall(void const __iomem *ioaddr)
+ {
+ unsigned long limit = loops_per_jiffy << 1;
+
+- while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
++ while ((read_sssr(ioaddr) & SSSR_BSY) && --limit)
+ cpu_relax();
+
+ return limit;
+@@ -532,12 +654,12 @@ static void dma_error_stop(struct driver_data *drv_data, const char *msg)
+ /* 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);
++ 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);
++ write_ssto(0, reg);
+ flush(drv_data);
+- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
++ write_sscr0(read_sscr0(reg) & ~SSCR0_SSE, reg);
+
+ unmap_dma_buffers(drv_data);
+
+@@ -553,8 +675,8 @@ static void dma_transfer_complete(struct driver_data *drv_data)
+ 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);
++ 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;
+
+@@ -630,7 +752,7 @@ 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;
++ 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;
+@@ -639,7 +761,7 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
+ /* Check for false positive timeout */
+ if ((irq_status & SSSR_TINT)
+ && (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
+- write_SSSR(SSSR_TINT, reg);
++ write_sssr(SSSR_TINT, reg);
+ return IRQ_HANDLED;
+ }
+
+@@ -648,7 +770,7 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
+ /* Clear and disable timeout interrupt, do the rest in
+ * dma_transfer_complete */
+ if (!pxa25x_ssp_comp(drv_data))
+- write_SSTO(0, reg);
++ write_ssto(0, reg);
+
+ /* finish this transfer, start the next */
+ dma_transfer_complete(drv_data);
+@@ -666,23 +788,26 @@ static void reset_sccr1(struct driver_data *drv_data)
+ struct chip_data *chip = drv_data->cur_chip;
+ u32 sccr1_reg;
+
+- sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1;
+- sccr1_reg &= ~SSCR1_RFT;
++ sccr1_reg = read_sscr1(reg) & ~drv_data->int_cr1;
++ if (drv_data->ssp_type == CE5X00_SSP)
++ sccr1_reg &= ~CE5X00_SSCR1_RFT;
++ else
++ sccr1_reg &= ~SSCR1_RFT;
+ sccr1_reg |= chip->threshold;
+- write_SSCR1(sccr1_reg, reg);
++ write_sscr1(sccr1_reg, reg);
+ }
+
+-static void int_error_stop(struct driver_data *drv_data, const char* msg)
++static void int_error_stop(struct driver_data *drv_data, const char *msg)
+ {
+ void __iomem *reg = drv_data->ioaddr;
+
+ /* Stop and reset SSP */
+- write_SSSR_CS(drv_data, drv_data->clear_sr);
++ write_sssr_cs(drv_data, drv_data->clear_sr);
+ reset_sccr1(drv_data);
+ if (!pxa25x_ssp_comp(drv_data))
+- write_SSTO(0, reg);
++ write_ssto(0, reg);
+ flush(drv_data);
+- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
++ write_sscr0(read_sscr0(reg) & ~SSCR0_SSE, reg);
+
+ dev_err(&drv_data->pdev->dev, "%s\n", msg);
+
+@@ -695,10 +820,10 @@ static void int_transfer_complete(struct driver_data *drv_data)
+ void __iomem *reg = drv_data->ioaddr;
+
+ /* Stop SSP */
+- write_SSSR_CS(drv_data, drv_data->clear_sr);
++ write_sssr_cs(drv_data, drv_data->clear_sr);
+ reset_sccr1(drv_data);
+ if (!pxa25x_ssp_comp(drv_data))
+- write_SSTO(0, reg);
++ write_ssto(0, reg);
+
+ /* Update total byte transferred return count actual bytes read */
+ drv_data->cur_msg->actual_length += drv_data->len -
+@@ -715,14 +840,16 @@ static void int_transfer_complete(struct driver_data *drv_data)
+ tasklet_schedule(&drv_data->pump_transfers);
+ }
+
++#ifndef CONFIG_GEN3_SPI
++
+ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+ {
+ void __iomem *reg = drv_data->ioaddr;
+
+- u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
++ u32 irq_mask = (read_sscr1(reg) & SSCR1_TIE) ?
+ drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
+
+- u32 irq_status = read_SSSR(reg) & irq_mask;
++ u32 irq_status = read_sssr(reg) & irq_mask;
+
+ if (irq_status & SSSR_ROR) {
+ int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
+@@ -730,7 +857,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+ }
+
+ if (irq_status & SSSR_TINT) {
+- write_SSSR(SSSR_TINT, reg);
++ write_sssr_cs(drv_data, SSSR_TINT);
+ if (drv_data->read(drv_data)) {
+ int_transfer_complete(drv_data);
+ return IRQ_HANDLED;
+@@ -751,10 +878,12 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+ }
+
+ if (drv_data->tx == drv_data->tx_end) {
+- u32 bytes_left;
++#ifndef CONFIG_GEN3_SPI
++ u32 bytes_left = 0;
++#endif
+ u32 sccr1_reg;
+
+- sccr1_reg = read_SSCR1(reg);
++ sccr1_reg = read_sscr1(reg);
+ sccr1_reg &= ~SSCR1_TIE;
+
+ /*
+@@ -762,13 +891,13 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+ * remaining RX bytes.
+ */
+ if (pxa25x_ssp_comp(drv_data)) {
+-
++#ifndef CONFIG_GEN3_SPI
+ sccr1_reg &= ~SSCR1_RFT;
+
+ bytes_left = drv_data->rx_end - drv_data->rx;
+ switch (drv_data->n_bytes) {
+ case 4:
+- bytes_left >>= 1;
++ bytes_left >>= 2;
+ case 2:
+ bytes_left >>= 1;
+ }
+@@ -777,23 +906,198 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+ bytes_left = RX_THRESH_DFLT;
+
+ sccr1_reg |= SSCR1_RxTresh(bytes_left);
++#endif
++ }
++ write_sscr1(sccr1_reg, reg);
++#ifdef CONFIG_GEN3_SPI
++ if (!wait_ssp_rx_stall(reg)) {
++ int_error_stop(drv_data,
++ "interrupt_transfer: rx stall failed");
++ return IRQ_HANDLED;
++ }
++
++ if (!drv_data->read(drv_data)) {
++ int_error_stop(drv_data,
++ "interrupt_transfer: "
++ "trailing byte read failed");
++ return IRQ_HANDLED;
++ }
++
++ int_transfer_complete(drv_data);
++#endif
++
++ }
++
++ /* We did something */
++ return IRQ_HANDLED;
++}
++#else
++#ifdef WANT_TO_USE_THIS
++static int is_txfifo_empty(struct driver_data *drv_data, u32 tfl_mask)
++{
++ void __iomem *reg = drv_data->ioaddr;
++ u32 sssr = read_sssr(reg);
++ u32 tx_fifo_entry = 0;
++ tx_fifo_entry = (sssr & tfl_mask)>>8;
++ if ((sssr & SSSR_TNF) && (!tx_fifo_entry))
++ return 1;
++ return 0;
++}
++#endif
++
++static void pxa2xx_update_tx_threshold(struct driver_data *drv_data,
++ u32 threshold)
++{
++ void __iomem *reg = drv_data->ioaddr;
++ u32 sscr1_reg = 0;
++ sscr1_reg = read_sscr1(reg);
++ sscr1_reg |= SSCR1_TIE;
++ if (drv_data->ssp_type == CE5X00_SSP) {
++ sscr1_reg &= ~CE5X00_SSCR1_TFT;
++ sscr1_reg |= CE5X00_SSCR1_TxTresh(threshold);
++ } else {
++ sscr1_reg &= ~SSCR1_TFT;
++ sscr1_reg |= SSCR1_TxTresh(threshold);
++ }
++
++ write_sscr1(sscr1_reg, reg);
++}
++
++static void pxa2xx_mask_intr(void __iomem *reg, u32 intr)
++{
++ u32 mask;
++ mask = read_sscr1(reg) & ~intr;
++ write_sscr1(mask, reg);
++}
++
++static void pxa2xx_unmask_intr(void __iomem *reg, u32 intr)
++{
++ u32 mask;
++ mask = read_sscr1(reg) | intr;
++ write_sscr1(mask, reg);
++}
++
++static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
++{
++ void __iomem *reg = drv_data->ioaddr;
++
++ u32 tx_count;
++ u32 irq_mask = (read_sscr1(reg) & SSCR1_TIE) ?
++ drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
++
++ int left;
++
++ u32 tmp_sssr = read_sssr(reg);
++ u32 irq_status = tmp_sssr & irq_mask;
++ /*
++ * Transmit FIFO Level Depth/MASK/Default value
++ */
++ u32 fifo_depth, sssr_tfl_mask, sscr1_tft_mask, tfl_default;
++
++ /*
++ * Check whether the irq is valid spi interrupt
++ */
++ if (!(tmp_sssr & (SSSR_TFS | SSSR_RFS | SSSR_ROR)))
++ return IRQ_NONE;
++
++ switch (drv_data->ssp_type) {
++ case CE4100_SSP:
++ fifo_depth = CE4X00_FIFO_DEPTH;
++ sssr_tfl_mask = SSSR_TFL_MASK;
++ sscr1_tft_mask = SSCR1_TFT;
++ tfl_default = TX_THRESH_DFLT;
++ break;
++ case CE5X00_SSP:
++ fifo_depth = CE5X00_FIFO_DEPTH;
++ sssr_tfl_mask = CE5X00_SSSR_TFL_MASK;
++ sscr1_tft_mask = CE5X00_SSCR1_TFT;
++ tfl_default = TX_THRESH_CE5X00_DFLT;
++ break;
++ default:
++ int_error_stop(drv_data, "Unsupported spi contoller type");
++ return IRQ_HANDLED;
++ }
++
++
++ if (irq_status & SSSR_ROR) {
++ int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
++ return IRQ_HANDLED;
++ }
++
++
++ if (irq_status & SSSR_TINT) {
++ write_sssr_cs(drv_data, SSSR_TINT);
++ if (drv_data->read(drv_data)) {
++ int_transfer_complete(drv_data);
++ return IRQ_HANDLED;
+ }
+- write_SSCR1(sccr1_reg, reg);
+ }
+
++
++ if (irq_status & SSSR_TFS) {
++
++ /*
++ * Mask the Transmit interrupt
++ */
++ pxa2xx_mask_intr(reg, SSCR1_TIE);
++
++ left = (drv_data->tx_end - drv_data->tx) / drv_data->n_bytes;
++
++ tmp_sssr = read_sssr(reg);
++ tmp_sssr = (tmp_sssr & sssr_tfl_mask)>>8;
++ /*
++ * Choose the correct tx_count to fill the Tx fifo and
++ * avoid the Rx Fifo overrun
++ */
++ tx_count = (fifo_depth - 1) - tmp_sssr;
++
++ if (left <= tx_count) {
++ if (left > 0) {
++ drv_data->read(drv_data);
++ pxa2xx_update_tx_threshold(drv_data, 1);
++ while ((left) > 0) {
++ left--;
++ drv_data->write(drv_data);
++ }
++ pxa2xx_unmask_intr(reg, SSCR1_TIE);
++ return IRQ_HANDLED;
++ } else {
++ /*
++ * Tx transfer is done now,
++ * Read data when controller is not busy.
++ */
++ wait_till_not_busy(drv_data);
++ drv_data->read(drv_data);
++ pxa2xx_unmask_intr(reg, SSCR1_TIE);
++ int_transfer_complete(drv_data);
++ return IRQ_HANDLED;
++ }
++ } else {
++ left = (left > tx_count) ? tx_count : left;
++ drv_data->read(drv_data);
++ while ((left) > 0) {
++ left--;
++ drv_data->write(drv_data);
++ }
++ pxa2xx_unmask_intr(reg, SSCR1_TIE);
++ return IRQ_HANDLED;
++ }
++ }
+ /* We did something */
+ return IRQ_HANDLED;
+ }
++#endif
+
+ 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 = read_sscr1(reg);
+ u32 mask = drv_data->mask_sr;
+ u32 status;
++ irqreturn_t ret;
+
+- status = read_SSSR(reg);
++ status = read_sssr(reg);
+
+ /* Ignore possible writes if we don't need to write */
+ if (!(sccr1_reg & SSCR1_TIE))
+@@ -802,22 +1106,27 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
+ if (!(status & mask))
+ return IRQ_NONE;
+
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ mask_pvm(drv_data->ssp->pcidev);
++#endif
+ if (!drv_data->cur_msg) {
+
+- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+- write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
++ write_sscr0(read_sscr0(reg) & ~SSCR0_SSE, reg);
++ write_sscr1(read_sscr1(reg) & ~drv_data->int_cr1, reg);
+ if (!pxa25x_ssp_comp(drv_data))
+- write_SSTO(0, reg);
+- write_SSSR_CS(drv_data, drv_data->clear_sr);
+-
+- dev_err(&drv_data->pdev->dev, "bad message state "
+- "in interrupt handler\n");
++ write_ssto(0, reg);
++ write_sssr_cs(drv_data, drv_data->clear_sr);
+
++ dev_err(&drv_data->pdev->dev,
++ "bad message state in interrupt handler\n");
+ /* Never fail */
+ return IRQ_HANDLED;
+ }
+-
+- return drv_data->transfer_handler(drv_data);
++ ret = drv_data->transfer_handler(drv_data);
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ unmask_pvm(drv_data->ssp->pcidev);
++#endif
++ return ret;
+ }
+
+ static int set_dma_burst_and_threshold(struct chip_data *chip,
+@@ -916,16 +1225,192 @@ static int set_dma_burst_and_threshold(struct chip_data *chip,
+
+ return retval;
+ }
++#ifdef CONFIG_GEN3_SPI
++/* this returns the value of DDS_FREQ not Input_Clock
++ DDS_FREQ = Input_Clock ( DDS_CLK_RATEdec / 2^24) */
++static unsigned long spi_clk_get_rate(int ssp_type)
++{
++ switch (ssp_type) {
++ case CE5X00_SSP:
++ /* CE5X00 clk is 10MHZ */
++ return 10000000;
++ case CE4100_SSP:
++ /* CE4X00 clk is 3.684MHZ */
++ default:
++ return 3686400;
++ }
+
++ return 3686400;
++}
++#endif
++
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++/* see Quark SPI data sheet for implementation rationale */
++u32 qrk_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div)
++{
++ if (rate <= BITRATE_MAX && rate >= BITRATE_MIN) {
++ if (rate >= BITRATE_50MHZ) {
++ *dds = DDS_MAX;
++ *clk_div = 0;
++ return BITRATE_50MHZ;
++ } else if (rate >= BITRATE_40MHZ) {
++ *dds = DDS_666666;
++ *clk_div = 0;
++ return BITRATE_40MHZ;
++ } else if (rate >= BITRATE_25MHZ) {
++ *dds = DDS_400000;
++ *clk_div = 0;
++ return BITRATE_25MHZ;
++ } else if (rate >= BITRATE_20MHZ) {
++ *dds = DDS_666666;
++ *clk_div = 1;
++ return BITRATE_20MHZ;
++ } else if (rate >= BITRATE_16667KHZ) {
++ *dds = DDS_MAX;
++ *clk_div = 2;
++ return BITRATE_16667KHZ;
++ } else if (rate >= BITRATE_13333KHZ) {
++ *dds = DDS_666666;
++ *clk_div = 2;
++ return BITRATE_13333KHZ;
++ } else if (rate >= BITRATE_12500KHZ) {
++ *dds = DDS_200000;
++ *clk_div = 0;
++ return BITRATE_12500KHZ;
++ } else if (rate >= BITRATE_10MHZ) {
++ *dds = DDS_MAX;
++ *clk_div = 4;
++ return BITRATE_10MHZ;
++ } else if (rate >= BITRATE_8MHZ) {
++ *dds = DDS_666666;
++ *clk_div = 4;
++ return BITRATE_8MHZ;
++ } else if (rate >= BITRATE_6250KHZ) {
++ *dds = DDS_400000;
++ *clk_div = 3;
++ return BITRATE_6250KHZ;
++ } else if (rate >= BITRATE_5MHZ) {
++ *dds = DDS_400000;
++ *clk_div = 4;
++ return BITRATE_5MHZ;
++ } else if (rate >= BITRATE_4MHZ) {
++ *dds = DDS_666666;
++ *clk_div = 9;
++ return BITRATE_4MHZ;
++ } else if (rate >= BITRATE_3125KHZ) {
++ *dds = DDS_80000;
++ *clk_div = 0;
++ return BITRATE_3125KHZ;
++ } else if (rate >= BITRATE_2500KHZ) {
++ *dds = DDS_400000;
++ *clk_div = 9;
++ return BITRATE_2500KHZ;
++ } else if (rate >= BITRATE_2MHZ) {
++ *dds = DDS_666666;
++ *clk_div = 19;
++ return BITRATE_2MHZ;
++ } else if (rate >= BITRATE_1563KHZ) {
++ *dds = DDS_40000;
++ *clk_div = 0;
++ return BITRATE_1563KHZ;
++ } else if (rate >= BITRATE_1250KHZ) {
++ *dds = DDS_200000;
++ *clk_div = 9;
++ return BITRATE_1250KHZ;
++ } else if (rate >= BITRATE_1MHZ) {
++ *dds = DDS_400000;
++ *clk_div = 24;
++ return BITRATE_1MHZ;
++ } else if (rate >= BITRATE_800KHZ) {
++ *dds = DDS_666666;
++ *clk_div = 49;
++ return BITRATE_800KHZ;
++ } else if (rate >= BITRATE_781KHZ) {
++ *dds = DDS_20000;
++ *clk_div = 0;
++ return BITRATE_781KHZ;
++ } else if (rate >= BITRATE_625KHZ) {
++ *dds = DDS_200000;
++ *clk_div = 19;
++ return BITRATE_625KHZ;
++ } else if (rate >= BITRATE_500KHZ) {
++ *dds = DDS_400000;
++ *clk_div = 49;
++ return BITRATE_500KHZ;
++ } else if (rate >= BITRATE_400KHZ) {
++ *dds = DDS_666666;
++ *clk_div = 99;
++ return BITRATE_400KHZ;
++ } else if (rate >= BITRATE_390KHZ) {
++ *dds = DDS_10000;
++ *clk_div = 0;
++ return BITRATE_390KHZ;
++ } else if (rate >= BITRATE_250KHZ) {
++ *dds = DDS_400000;
++ *clk_div = 99;
++ return BITRATE_250KHZ;
++ } else if (rate >= BITRATE_200KHZ) {
++ *dds = DDS_666666;
++ *clk_div = 199;
++ return BITRATE_200KHZ;
++ } else if (rate >= BITRATE_195KHZ) {
++ *dds = DDS_8000;
++ *clk_div = 0;
++ return BITRATE_195KHZ;
++ } else if (rate >= BITRATE_125KHZ) {
++ *dds = DDS_100000;
++ *clk_div = 49;
++ return BITRATE_125KHZ;
++ } else if (rate >= BITRATE_100KHZ) {
++ *dds = DDS_200000;
++ *clk_div = 124;
++ return BITRATE_100KHZ;
++ } else if (rate >= BITRATE_50KHZ) {
++ *dds = DDS_100000;
++ *clk_div = 124;
++ return BITRATE_50KHZ;
++ } else if (rate >= BITRATE_25KHZ) {
++ *dds = DDS_80000;
++ *clk_div = 124;
++ return BITRATE_25KHZ;
++ } else if (rate >= BITRATE_10KHZ) {
++ *dds = DDS_20000;
++ *clk_div = 77;
++ return BITRATE_10KHZ;
++ } else if (rate >= BITRATE_5KHZ) {
++ *dds = DDS_20000;
++ *clk_div = 154;
++ return BITRATE_5KHZ;
++ } else if (rate >= BITRATE_1KHZ) {
++ *dds = DDS_8000;
++ *clk_div = 194;
++ return BITRATE_1KHZ;
++ }
++ } else {
++ *dds = DDS_8000;
++ *clk_div = 194;
++ return BITRATE_MIN;
++ }
++ return 0;
++}
++#else
++/* this returns the value that SCR needs to be set to
++ Bit rate = DDS_FREQ / (2 x (SCR + 1)) */
+ static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
+ {
++#ifdef CONFIG_GEN3_SPI
++ unsigned long ssp_clk = spi_clk_get_rate(ssp->type);
++#else
+ unsigned long ssp_clk = clk_get_rate(ssp->clk);
++#endif
+
+- if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
++ if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP
++ || ssp->type == CE5X00_SSP)
+ return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
+ else
+ return ((ssp_clk / rate - 1) & 0xfff) << 8;
+ }
++#endif /* CONFIG_INTEL_QUARK_X1000_SOC */
+
+ static void pump_transfers(unsigned long data)
+ {
+@@ -934,7 +1419,11 @@ static void pump_transfers(unsigned long data)
+ struct spi_transfer *transfer = NULL;
+ struct spi_transfer *previous = NULL;
+ struct chip_data *chip = NULL;
++#ifndef CONFIG_INTEL_QUARK_X1000_SOC
+ struct ssp_device *ssp = drv_data->ssp;
++#else
++ u32 actual_speed = 0;
++#endif
+ void __iomem *reg = drv_data->ioaddr;
+ u32 clk_div = 0;
+ u8 bits = 0;
+@@ -947,8 +1436,11 @@ static void pump_transfers(unsigned long data)
+ /* Get current state information */
+ message = drv_data->cur_msg;
+ transfer = drv_data->cur_transfer;
++
+ chip = drv_data->cur_chip;
+
++ if (transfer->bits_per_word)
++ chip->n_bytes = (transfer->bits_per_word + 7)/8;
+ /* Handle for abort */
+ if (message->state == ERROR_STATE) {
+ message->status = -EIO;
+@@ -992,11 +1484,11 @@ static void pump_transfers(unsigned long data)
+ }
+
+ /* warn ... we force this to PIO mode */
+- if (printk_ratelimit())
+- dev_warn(&message->spi->dev, "pump_transfers: "
+- "DMA disabled for transfer length %ld "
+- "greater than %d\n",
+- (long)drv_data->len, MAX_DMA_LEN);
++ dev_warn_ratelimited(&message->spi->dev,
++ "pump_transfers: "
++ "DMA disabled for transfer length %ld "
++ "greater than %d\n",
++ (long)drv_data->len, MAX_DMA_LEN);
+ }
+
+ /* Setup the transfer state based on the type of transfer */
+@@ -1009,19 +1501,21 @@ static void pump_transfers(unsigned long data)
+ 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->tx_end = drv_data->tx
++ + (transfer->len/drv_data->n_bytes)*drv_data->n_bytes;
+ drv_data->rx = transfer->rx_buf;
+- drv_data->rx_end = drv_data->rx + transfer->len;
++ drv_data->rx_end = drv_data->rx
++ + (transfer->len/drv_data->n_bytes)*drv_data->n_bytes;
+ 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->n_bytes)
++ * drv_data->n_bytes & DCMD_LENGTH;
+ drv_data->write = drv_data->tx ? chip->write : null_writer;
+ drv_data->read = drv_data->rx ? chip->read : null_reader;
+
+ /* Change speed and bit per word on a per transfer */
+ cr0 = chip->cr0;
+ if (transfer->speed_hz || transfer->bits_per_word) {
+-
+ bits = chip->bits_per_word;
+ speed = chip->speed_hz;
+
+@@ -1031,8 +1525,13 @@ static void pump_transfers(unsigned long data)
+ if (transfer->bits_per_word)
+ bits = transfer->bits_per_word;
+
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ actual_speed = qrk_set_clk_regvals
++ (speed, &chip->dds_rate, &clk_div);
++ clk_div = (clk_div << 8);
++#else
+ clk_div = ssp_get_clk_div(ssp, speed);
+-
++#endif
+ if (bits <= 8) {
+ drv_data->n_bytes = 1;
+ drv_data->dma_width = DCMD_WIDTH1;
+@@ -1061,18 +1560,32 @@ static void pump_transfers(unsigned long data)
+ if (set_dma_burst_and_threshold(chip, message->spi,
+ bits, &dma_burst,
+ &dma_thresh))
+- if (printk_ratelimit())
+- dev_warn(&message->spi->dev,
+- "pump_transfers: "
+- "DMA burst size reduced to "
+- "match bits_per_word\n");
++ dev_warn_ratelimited(&message->spi->dev,
++ "pump_transfers: "
++ "DMA burst size reduced to"
++ " match bits_per_word\n");
+ }
+
+- cr0 = clk_div
+- | SSCR0_Motorola
+- | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
+- | SSCR0_SSE
+- | (bits > 16 ? SSCR0_EDSS : 0);
++ switch (drv_data->ssp_type) {
++ case CE5X00_SSP:
++ chip->cr0 = clk_div
++ | CE5X00_SSCR0_Motorola
++ | CE5X00_SSCR0_DataSize(bits > 32 ?
++ 8 : bits)
++ | SSCR0_SSE;
++ break;
++ case CE4100_SSP:
++ case PXA25x_SSP:
++ default:
++ chip->cr0 = clk_div
++ | SSCR0_Motorola
++ | SSCR0_DataSize(bits > 16 ?
++ bits - 16 : bits)
++ | SSCR0_SSE
++ | (bits > 16 ? SSCR0_EDSS : 0);
++ }
++
++ cr0 = chip->cr0;
+ }
+
+ message->state = RUNNING_STATE;
+@@ -1138,7 +1651,7 @@ static void pump_transfers(unsigned long data)
+
+ /* Clear status and start DMA engine */
+ cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
+- write_SSSR(drv_data->clear_sr, reg);
++ write_sssr(drv_data->clear_sr, reg);
+ DCSR(drv_data->rx_channel) |= DCSR_RUN;
+ DCSR(drv_data->tx_channel) |= DCSR_RUN;
+ } else {
+@@ -1147,100 +1660,72 @@ static void pump_transfers(unsigned long data)
+
+ /* Clear status */
+ cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
+- write_SSSR_CS(drv_data, drv_data->clear_sr);
++ write_sssr_cs(drv_data, drv_data->clear_sr);
+ }
+
+ /* see if we need to reload the config registers */
+- if ((read_SSCR0(reg) != cr0)
+- || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
+- (cr1 & SSCR1_CHANGE_MASK)) {
++ if (drv_data->ssp_type == CE5X00_SSP) {
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ if (read_dds_rate(reg) != chip->dds_rate)
++ write_dds_rate(chip->dds_rate, reg);
++#endif
++ if ((read_sscr0(reg) != cr0)
++ || (read_sscr1(reg) & CE5X00_SSCR1_CHANGE_MASK) !=
++ (cr1 & CE5X00_SSCR1_CHANGE_MASK)) {
++ /* stop the SSP, and update the other bits */
++ write_sscr0(cr0 & ~SSCR0_SSE, reg);
++ if (!pxa25x_ssp_comp(drv_data))
++ write_ssto(chip->timeout, reg);
++ /* first set CR1 w/o interrupt and service enables */
++ write_sscr1(cr1 & CE5X00_SSCR1_CHANGE_MASK, reg);
++ /* restart the SSP */
++ write_sscr0(cr0, reg);
+
++ } else {
++ if (!pxa25x_ssp_comp(drv_data))
++ write_ssto(chip->timeout, reg);
++ }
++ } else if ((read_sscr0(reg) != cr0)
++ || (read_sscr1(reg) & SSCR1_CHANGE_MASK) !=
++ (cr1 & SSCR1_CHANGE_MASK)) {
+ /* stop the SSP, and update the other bits */
+- write_SSCR0(cr0 & ~SSCR0_SSE, reg);
++ write_sscr0(cr0 & ~SSCR0_SSE, reg);
+ if (!pxa25x_ssp_comp(drv_data))
+- write_SSTO(chip->timeout, reg);
++ write_ssto(chip->timeout, reg);
+ /* first set CR1 without interrupt and service enables */
+- write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
++ write_sscr1(cr1 & SSCR1_CHANGE_MASK, reg);
+ /* restart the SSP */
+- write_SSCR0(cr0, reg);
++ write_sscr0(cr0, reg);
+
+- } else {
+- if (!pxa25x_ssp_comp(drv_data))
+- write_SSTO(chip->timeout, reg);
++ } else if (!pxa25x_ssp_comp(drv_data)) {
++ write_ssto(chip->timeout, reg);
+ }
+-
+ cs_assert(drv_data);
+
+ /* after chip select, release the data by enabling service
+ * requests and interrupts, without changing any mode bits */
+- write_SSCR1(cr1, reg);
++ write_sscr1(cr1, reg);
+ }
+
+-static void pump_messages(struct work_struct *work)
++static int 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;
+- }
++ struct driver_data *drv_data = spi_master_get_devdata(master);
+
+- /* 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);
++ /* Initial message state */
++ drv_data->cur_msg = msg;
++ msg->state = START_STATE;
+
+- /* Initial message state*/
+- drv_data->cur_msg->state = START_STATE;
+- drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+- struct spi_transfer,
+- transfer_list);
++ drv_data->cur_transfer = list_entry(msg->transfers.next,
++ struct spi_transfer, transfer_list);
+
+ /* prepare to setup the SSP, in pump_transfers, using the per
+ * chip configuration */
+- drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
++ drv_data->cur_chip = spi_get_ctldata(msg->spi);
+
+- /* Mark as busy and launch transfers */
++ /* Launch transfers */
+ tasklet_schedule(&drv_data->pump_transfers);
+
+- drv_data->busy = 1;
+- spin_unlock_irqrestore(&drv_data->lock, flags);
+-}
+-
+-static int transfer(struct spi_device *spi, struct spi_message *msg)
+-{
+- 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;
+-
+- list_add_tail(&msg->queue, &drv_data->queue);
+-
+- if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
+- queue_work(drv_data->workqueue, &drv_data->pump_messages);
+-
+- spin_unlock_irqrestore(&drv_data->lock, flags);
+-
+ return 0;
+ }
+
+@@ -1267,8 +1752,9 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
+ if (gpio_is_valid(chip_info->gpio_cs)) {
+ err = gpio_request(chip_info->gpio_cs, "SPI_CS");
+ if (err) {
+- dev_err(&spi->dev, "failed to request chip select "
+- "GPIO%d\n", chip_info->gpio_cs);
++ dev_err(&spi->dev,
++ "failed to request chip select "
++ "GPIO%d\n", chip_info->gpio_cs);
+ return err;
+ }
+
+@@ -1282,6 +1768,31 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
+ return err;
+ }
+
++static int prepare_transfer_hardware(struct spi_master *master)
++{
++ struct driver_data *drv_data = spi_master_get_devdata(master);
++
++ /*
++ * Just make sure we have all we need to run the transfer by syncing
++ * with the runtime PM framework.
++ */
++ pm_runtime_get_sync(&drv_data->pdev->dev);
++ return 0;
++}
++
++static int unprepare_transfer_hardware(struct spi_master *master)
++{
++ struct driver_data *drv_data = spi_master_get_devdata(master);
++
++ /* nothing more to do - disable spi/ssp and power off */
++ write_sscr0(0, drv_data->ioaddr);
++ clk_disable(drv_data->ssp->clk);
++
++ pm_runtime_put(&drv_data->pdev->dev);
++
++ return 0;
++}
++
+ static int setup(struct spi_device *spi)
+ {
+ struct pxa2xx_spi_chip *chip_info = NULL;
+@@ -1289,21 +1800,29 @@ static int setup(struct spi_device *spi)
+ struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+ struct ssp_device *ssp = drv_data->ssp;
+ unsigned int clk_div;
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ u32 actual_speed;
++#endif
+ uint tx_thres = TX_THRESH_DFLT;
+ uint rx_thres = RX_THRESH_DFLT;
+-
+- if (!pxa25x_ssp_comp(drv_data)
++ if (drv_data->ssp_type == CE5X00_SSP) {
++ tx_thres = TX_THRESH_CE5X00_DFLT;
++ rx_thres = RX_THRESH_CE5X00_DFLT;
++ }
++ if ((!pxa25x_ssp_comp(drv_data) || pxa25x_ssp_comp(drv_data) == 2)
+ && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
+- dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
+- "b/w not 4-32 for type non-PXA25x_SSP\n",
+- drv_data->ssp_type, spi->bits_per_word);
++ dev_err(&spi->dev,
++ "failed setup: ssp_type=%d, bits/wrd=%d "
++ "b/w not 4-32 for type non-PXA25x_SSP\n",
++ drv_data->ssp_type, spi->bits_per_word);
+ return -EINVAL;
+- } else if (pxa25x_ssp_comp(drv_data)
++ } else if (pxa25x_ssp_comp(drv_data) == 1
+ && (spi->bits_per_word < 4
+ || spi->bits_per_word > 16)) {
+- dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
+- "b/w not 4-16 for type PXA25x_SSP\n",
+- drv_data->ssp_type, spi->bits_per_word);
++ dev_err(&spi->dev,
++ "failed setup: ssp_type=%d, bits/wrd=%d "
++ "b/w not 4-16 for type PXA25x_SSP\n",
++ drv_data->ssp_type, spi->bits_per_word);
+ return -EINVAL;
+ }
+
+@@ -1319,8 +1838,9 @@ static int setup(struct spi_device *spi)
+
+ if (drv_data->ssp_type == CE4100_SSP) {
+ if (spi->chip_select > 4) {
+- dev_err(&spi->dev, "failed setup: "
+- "cs number must not be > 4.\n");
++ dev_err(&spi->dev,
++ "failed setup: "
++ "cs number must not be > 4.\n");
+ kfree(chip);
+ return -EINVAL;
+ }
+@@ -1328,6 +1848,7 @@ static int setup(struct spi_device *spi)
+ chip->frm = spi->chip_select;
+ } else
+ chip->gpio_cs = -1;
++
+ chip->enable_dma = 0;
+ chip->timeout = TIMOUT_DFLT;
+ chip->dma_burst_size = drv_data->master_info->enable_dma ?
+@@ -1340,6 +1861,7 @@ static int setup(struct spi_device *spi)
+
+ /* chip_info isn't always needed */
+ chip->cr1 = 0;
++ chip->cr0 = 0;
+ if (chip_info) {
+ if (chip_info->timeout)
+ chip->timeout = chip_info->timeout;
+@@ -1353,9 +1875,6 @@ static int setup(struct spi_device *spi)
+ chip->cr1 = SSCR1_LBM;
+ }
+
+- chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
+- (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
+-
+ /* 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 */
+@@ -1364,33 +1883,73 @@ static int setup(struct spi_device *spi)
+ if (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 "
+- "to match bits_per_word\n");
++ dev_warn(&spi->dev,
++ "in setup: DMA burst size reduced "
++ "to match bits_per_word\n");
+ }
+ }
+-
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ actual_speed = qrk_set_clk_regvals(spi->max_speed_hz,
++ &chip->dds_rate, &clk_div);
++ clk_div = (clk_div << 8);
++#else
+ clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz);
++#endif
+ chip->speed_hz = spi->max_speed_hz;
+
+- chip->cr0 = clk_div
++ switch (drv_data->ssp_type) {
++ case CE5X00_SSP:
++ chip->cr0 = clk_div
++ | CE5X00_SSCR0_Motorola
++ | CE5X00_SSCR0_DataSize(spi->bits_per_word > 32 ?
++ 8 : spi->bits_per_word)
++ | SSCR0_SSE;
++ chip->threshold = (CE5X00_SSCR1_RxTresh(rx_thres)
++ & CE5X00_SSCR1_RFT) |
++ (CE5X00_SSCR1_TxTresh(tx_thres) & CE5X00_SSCR1_TFT);
++ break;
++ case CE4100_SSP:
++ case PXA25x_SSP:
++ default:
++ chip->cr0 = clk_div
+ | SSCR0_Motorola
+ | SSCR0_DataSize(spi->bits_per_word > 16 ?
+ spi->bits_per_word - 16 : spi->bits_per_word)
+ | SSCR0_SSE
+ | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
++ chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
++ (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
++ }
++
+ chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
++ | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0)
++ | (((spi->mode & SPI_LOOP) != 0) ? SSCR1_LBM : 0);
++#else
+ chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
+ | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
++#endif
+
+ /* NOTE: PXA25x_SSP _could_ use external clocking ... */
+ if (!pxa25x_ssp_comp(drv_data))
+- dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
++ dev_dbg(&spi->dev,
++ "%ld Hz actual, %s\n",
++#ifndef CONFIG_GEN3_SPI
+ clk_get_rate(ssp->clk)
++#else
++ spi_clk_get_rate(ssp->type)
++#endif
+ / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
+ chip->enable_dma ? "DMA" : "PIO");
+ else
+- dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
++ dev_dbg(&spi->dev,
++ "%ld Hz actual, %s\n",
++#ifndef CONFIG_GEN3_SPI
+ clk_get_rate(ssp->clk) / 2
++#else
++ spi_clk_get_rate(ssp->type) / 2
++#endif
+ / (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
+ chip->enable_dma ? "DMA" : "PIO");
+
+@@ -1405,7 +1964,9 @@ static int setup(struct spi_device *spi)
+ chip->read = u16_reader;
+ chip->write = u16_writer;
+ } else if (spi->bits_per_word <= 32) {
++#ifndef CONFIG_GEN3_SPI
+ chip->cr0 |= SSCR0_EDSS;
++#endif
+ chip->n_bytes = 4;
+ chip->dma_width = DCMD_WIDTH4;
+ chip->read = u32_reader;
+@@ -1438,94 +1999,6 @@ static void cleanup(struct spi_device *spi)
+ kfree(chip);
+ }
+
+-static int init_queue(struct driver_data *drv_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;
+-
+- return 0;
+-}
+-
+-static int start_queue(struct driver_data *drv_data)
+-{
+- 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;
+- }
+-
+- 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);
+-
+- return 0;
+-}
+-
+-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);
+- }
+-
+- if (!list_empty(&drv_data->queue) || drv_data->busy)
+- status = -EBUSY;
+-
+- spin_unlock_irqrestore(&drv_data->lock, flags);
+-
+- return status;
+-}
+-
+-static int destroy_queue(struct driver_data *drv_data)
+-{
+- int status;
+-
+- 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;
+-
+- destroy_workqueue(drv_data->workqueue);
+-
+- return 0;
+-}
+-
+ static int pxa2xx_spi_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+@@ -1557,16 +2030,27 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
+ drv_data->ssp = ssp;
+
+ master->dev.parent = &pdev->dev;
++#ifdef CONFIG_OF
++#ifndef CONFIG_GEN3_SPI
+ master->dev.of_node = pdev->dev.of_node;
++#endif
++#endif
++
+ /* the spi->mode bits understood by this driver: */
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
++#else
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+-
++#endif
+ master->bus_num = pdev->id;
+ master->num_chipselect = platform_info->num_chipselect;
+ master->dma_alignment = DMA_ALIGNMENT;
+ master->cleanup = cleanup;
+ master->setup = setup;
+- master->transfer = transfer;
++ master->prepare_transfer_hardware = prepare_transfer_hardware;
++ master->transfer_one_message = transfer_one_message;
++ master->unprepare_transfer_hardware = unprepare_transfer_hardware;
++ master->rt = true;
+
+ drv_data->ssp_type = ssp->type;
+ drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data +
+@@ -1628,43 +2112,59 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
+ clk_enable(ssp->clk);
+
+ /* Load default SSP configuration */
+- write_SSCR0(0, drv_data->ioaddr);
+- write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
+- SSCR1_TxTresh(TX_THRESH_DFLT),
+- drv_data->ioaddr);
+- write_SSCR0(SSCR0_SCR(2)
+- | SSCR0_Motorola
+- | SSCR0_DataSize(8),
+- drv_data->ioaddr);
++ write_sscr0(0, drv_data->ioaddr);
++ switch (drv_data->ssp_type) {
++ case CE5X00_SSP:
++ write_sscr1(CE5X00_SSCR1_RxTresh(RX_THRESH_CE5X00_DFLT) |
++ CE5X00_SSCR1_TxTresh(TX_THRESH_CE5X00_DFLT),
++ drv_data->ioaddr);
++#ifdef CONFIG_INTEL_QUARK_X1000_SOC
++ /* using the Motorola SPI protocol and use 8 bit frame */
++ write_sscr0(CE5X00_SSCR0_Motorola
++ | CE5X00_SSCR0_DataSize(8),
++ drv_data->ioaddr);
++#else
++ /* default using Motorola SPI protocol and use 8 bit frame */
++ write_sscr0(SSCR0_SCR(2)
++ | CE5X00_SSCR0_Motorola
++ | CE5X00_SSCR0_DataSize(8),
++ drv_data->ioaddr);
++#endif
++ break;
++ case CE4100_SSP:
++ case PXA25x_SSP:
++ default:
++ write_sscr1(SSCR1_RxTresh(RX_THRESH_DFLT) |
++ SSCR1_TxTresh(TX_THRESH_DFLT),
++ drv_data->ioaddr);
++ write_sscr0(SSCR0_SCR(2)
++ | SSCR0_Motorola
++ | SSCR0_DataSize(8),
++ drv_data->ioaddr);
++ }
+ if (!pxa25x_ssp_comp(drv_data))
+- write_SSTO(0, drv_data->ioaddr);
+- write_SSPSP(0, drv_data->ioaddr);
++ write_ssto(0, drv_data->ioaddr);
++#ifndef CONFIG_GEN3_SPI
++ /*
++ * SSPSP register is resrved on the CEXXXX SOCs.
++ */
++ write_sspsp(0, drv_data->ioaddr);
++#endif
+
+- /* 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;
+- }
++ /* Initialise transfer pump */
++ 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;
+
+-out_error_queue_alloc:
+- destroy_queue(drv_data);
+-
+ out_error_clock_enabled:
+ clk_disable(ssp->clk);
+
+@@ -1687,28 +2187,13 @@ 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");
+-
+ /* Disable the SSP at the peripheral and SOC level */
+- write_SSCR0(0, drv_data->ioaddr);
++ write_sscr0(0, drv_data->ioaddr);
+ clk_disable(ssp->clk);
+
+ /* Release DMA */
+@@ -1725,6 +2210,9 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
+ /* Release SSP */
+ pxa_ssp_free(ssp);
+
++ /* Disable transfer pump */
++ tasklet_disable(&drv_data->pump_transfers);
++
+ /* Disconnect from the SPI framework */
+ spi_unregister_master(drv_data->master);
+
+@@ -1738,7 +2226,8 @@ static void pxa2xx_spi_shutdown(struct platform_device *pdev)
+ {
+ int status = 0;
+
+- if ((status = pxa2xx_spi_remove(pdev)) != 0)
++ status = pxa2xx_spi_remove(pdev);
++ if (status != 0)
+ dev_err(&pdev->dev, "shutdown failed with %d\n", status);
+ }
+
+@@ -1749,10 +2238,15 @@ static int pxa2xx_spi_suspend(struct device *dev)
+ struct ssp_device *ssp = drv_data->ssp;
+ int status = 0;
+
+- status = stop_queue(drv_data);
+- if (status != 0)
++ status = spi_master_suspend(drv_data->master);
++ if (status) {
++ dev_warn(dev, "cannot suspend master\n");
+ return status;
+- write_SSCR0(0, drv_data->ioaddr);
++ }
++
++ pm_runtime_get_sync(dev);
++
++ write_sscr0(0, drv_data->ioaddr);
+ clk_disable(ssp->clk);
+
+ return 0;
+@@ -1774,14 +2268,14 @@ static int pxa2xx_spi_resume(struct device *dev)
+ /* Enable the SSP clock */
+ clk_enable(ssp->clk);
+
++ pm_runtime_put(dev);
++
+ /* Start the queue running */
+- status = start_queue(drv_data);
+- if (status != 0) {
++ status = spi_master_resume(drv_data->master);
++ if (status)
+ dev_err(dev, "problem starting queue (%d)\n", status);
+- return status;
+- }
+
+- return 0;
++ return status;
+ }
+
+ static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
+diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h
+index f366320..9810c71 100644
+--- a/include/linux/pxa2xx_ssp.h
++++ b/include/linux/pxa2xx_ssp.h
+@@ -104,6 +104,28 @@
+ #define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..4] */
+ #define SSCR1_RFT (0x00000c00) /* Receive FIFO Threshold (mask) */
+ #define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */
++
++/* CE5X00 SSCR0 bit definition */
++#define CE5X00_SSCR0_DSS ((1<<5)-1) /* Data Size Select (mask) */
++#define CE5X00_SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..32] */
++#define CE5X00_SSCR0_FRF (((1<<2)-1) << 5) /* FRame Format (mask) */
++#define CE5X00_SSCR0_Motorola (0x0 << 5) /* Motorola's Serial Peripheral Interface (SPI) */
++#define CE5X00_SSCR0_TI (0x1 << 5) /* Texas Instruments' Synchronous Serial Protocol (SSP) */
++#define CE5X00_SSCR0_National (0x2 << 5) /* National Microwire */
++
++#define RX_THRESH_CE5X00_DFLT 16
++#define TX_THRESH_CE5X00_DFLT 16
++
++#define CE5X00_SSSR_TFL_MASK (0x1F << 8) /* Transmit FIFO Level mask */
++#define CE5X00_SSSR_RFL_MASK (0x1F << 13) /* Receive FIFO Level mask */
++
++#define CE5X00_SSCR1_TFT (((1<<5)-1) << 6) /* Transmit FIFO Threshold (mask) */
++#define CE5X00_SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..32] */
++#define CE5X00_SSCR1_RFT (((1<<5)-1) << 11) /* Receive FIFO Threshold (mask) */
++#define CE5X00_SSCR1_RxTresh(x) (((x) - 1) << 11) /* level [1..32] */
++#define CE5X00_SSCR1_STRF (1 << 17) /* Select FIFO or EFWR */
++#define CE5X00_SSCR1_EFWR (1 << 16) /* Enable FIFO Write/Read */
++
+ #endif
+
+ /* extra bits in PXA255, PXA26x and PXA27x SSP ports */
+@@ -164,6 +186,7 @@ enum pxa_ssp_type {
+ PXA168_SSP,
+ PXA910_SSP,
+ CE4100_SSP,
++ CE5X00_SSP,
+ };
+
+ struct ssp_device {
+@@ -181,6 +204,7 @@ struct ssp_device {
+ int irq;
+ int drcmr_rx;
+ int drcmr_tx;
++ struct pci_dev *pcidev;
+ };
+
+ /**
+@@ -208,4 +232,5 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
+
+ struct ssp_device *pxa_ssp_request(int port, const char *label);
+ void pxa_ssp_free(struct ssp_device *);
++int pxa_msi_enabled(void);
+ #endif
+diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h
+index c73d144..acac9ae 100644
+--- a/include/linux/spi/pxa2xx_spi.h
++++ b/include/linux/spi/pxa2xx_spi.h
+@@ -130,23 +130,12 @@ 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;
+-}
+-
++#ifndef CONFIG_GEN3_SPI
+ static inline unsigned long clk_get_rate(struct clk *clk)
+ {
+ return 3686400;
+ }
++#endif
+
+ #endif
+ #endif
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index f629189..307d218 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -80,6 +80,8 @@ struct spi_device {
+ #define SPI_MODE_2 (SPI_CPOL|0)
+ #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
+ #define SPI_CS_HIGH 0x04 /* chipselect active high? */
++#define SPI_MODE_QUAD_IO 0x05 /* Quad IO mode using 4 wire */
++#define SPI_MODE_DUAL_IO 0x06 /* Dual IO mode using 2 wire */
+ #define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
+ #define SPI_3WIRE 0x10 /* SI/SO signals shared */
+ #define SPI_LOOP 0x20 /* loopback mode */
+--
+1.7.4.1
+