diff options
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.patch | 2349 |
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 + |