summaryrefslogtreecommitdiff
path: root/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-spi-slave-controller-driver-1.1.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-spi-slave-controller-driver-1.1.patch')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-spi-slave-controller-driver-1.1.patch2230
1 files changed, 0 insertions, 2230 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-spi-slave-controller-driver-1.1.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-spi-slave-controller-driver-1.1.patch
deleted file mode 100644
index 2328f9a30..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-spi-slave-controller-driver-1.1.patch
+++ /dev/null
@@ -1,2230 +0,0 @@
-From f52838cd03de045aa67cc1a0c1614ea5bfb30fcc Mon Sep 17 00:00:00 2001
-From: Alan Olsen <alan.r.olsen@intel.com>
-Date: Wed, 11 Nov 2009 13:12:42 -0800
-Subject: [PATCH 065/104] Moorestown SPI Slave Controller driver v1.1 consolidation patch
-
-This patch contains the following patches:
-
-Alpha2-1.0-1-1-mrst-SPI-Slave-Core-Driver-K29.patch
-
- [PATCH] SPI Slave Support Added to SPI Core Driver
-
- Signed-off-by: Pranav K. Sanghadia <pranav.k.sanghadia@intel.com>
-
-Alpha2-1.0-1-1-mrst-SPI-Slave-controller-driver.patch
-
- [PATCH] SPI slave controller driver for Moorestown platform
-
- This driver currently supports only programmed IO mode.
-
- Config settings are:
-
- CONFIG_SPI_MRST_SLAVE=y
- CONFIG_SPI_MRST_SLAVE_DMA is not set
-
- Signed-off-by: Ken Mills <ken.k.mills@intel.com>
-
-Alpha2-1.0-1-1-DMA-Support-added-in-SPI-Slave-Controller-Driver.patch
-
- [PATCH] This patch adds DMA support for SPI Slave Controller Driver. DMA provides
- highspeed data transfer between SPI-SSP and external Master mode device
-
- Signed-off-by: Pranav K. Sanghadia <pranav.k.sanghadia@intel.com>
-
-Alpha2-1.0-1-1-mrst-SPI-Slave-controller-fix-DMA-Issue.patch
-
- [PATCH] Alpha2-1.0-1-1-mrst-SPI-Slave-controller-fix-DMA-Issue.patch
-
-[PATCH] Optimized SSP clock bitbang routine
-
-Signed-off-by: Ken Mills <ken.k.mills@intel.com>
-
-Signed-off-by: Alan Olsen <alan.r.olsen@intel.com>
----
- drivers/spi/Kconfig | 11 +
- drivers/spi/Makefile | 1 +
- drivers/spi/mrst_spi_slave.c | 1227 ++++++++++++++++++++++++++++++++++++
- drivers/spi/spi.c | 403 +++++++++++-
- include/linux/spi/mrst_spi_slave.h | 143 +++++
- include/linux/spi/spi.h | 98 +++-
- 6 files changed, 1862 insertions(+), 21 deletions(-)
- create mode 100644 drivers/spi/mrst_spi_slave.c
- create mode 100644 include/linux/spi/mrst_spi_slave.h
-
-diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
-index 9d4ff53..b94445b 100644
---- a/drivers/spi/Kconfig
-+++ b/drivers/spi/Kconfig
-@@ -360,5 +360,16 @@ config SPI_TLE62X0
- endif # SPI_MASTER
-
- # (slave support would go here)
-+config SPI_MRST_SLAVE
-+ tristate "SPI slave controller driver for Intel Moorestown platform "
-+ depends on SPI_MASTER
-+ help
-+ This is the SPI slave controller driver for Intel Moorestown platform
-+
-+config SPI_MRST_SLAVE_DMA
-+ boolean "Enable DMA for MRST SPI Slave Controller"
-+ depends on INTEL_LNW_DMAC1
-+ help
-+ This has to be enabled after Moorestown DMAC1 driver is enabled
-
- endif # SPI
-diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
-index c78cb77..8acdd96 100644
---- a/drivers/spi/Makefile
-+++ b/drivers/spi/Makefile
-@@ -56,6 +56,7 @@ obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o
- # ... add above this line ...
-
- # SPI slave controller drivers (upstream link)
-+obj-$(CONFIG_SPI_MRST_SLAVE) += mrst_spi_slave.o
- # ... add above this line ...
-
- # SPI slave drivers (protocol for that link)
-diff --git a/drivers/spi/mrst_spi_slave.c b/drivers/spi/mrst_spi_slave.c
-new file mode 100644
-index 0000000..82a50b7
---- /dev/null
-+++ b/drivers/spi/mrst_spi_slave.c
-@@ -0,0 +1,1227 @@
-+/*
-+ * mrst_spi_slave.c - Moorestown SPI slave controller driver
-+ * based on pxa2xx_spi.c
-+ *
-+ * Copyright (C) Intel 2009
-+ * Ken Mills <ken.k.mills@intel.com>
-+ *
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ *
-+ */
-+
-+/*
-+ * Note:
-+ *
-+ * Supports interrupt programmed I/O, DMA and non-interrupt polled transfers.
-+ *
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/highmem.h>
-+#include <linux/pci.h>
-+#include <linux/interrupt.h>
-+
-+#ifdef CONFIG_SPI_MRST_SLAVE_DMA
-+#include <linux/dma-mapping.h>
-+#include <linux/lnw_dma.h>
-+#endif
-+
-+#include <linux/spi/spi.h>
-+#include <linux/spi/mrst_spi_slave.h>
-+
-+
-+#define DRIVER_NAME "mrst_spi_slave"
-+
-+#define SSP_NOT_SYNC 0x400000
-+
-+MODULE_AUTHOR("");
-+MODULE_DESCRIPTION("Moorestown SPI Slave Contoller");
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * For testing SSCR1 changes that require SSP restart, basically
-+ * everything except the service and interrupt enables
-+ */
-+#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_EBCEI | SSCR1_SCFR \
-+ | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
-+ | SSCR1_SFRMDIR \
-+ | SSCR1_RWOT | SSCR1_TRAIL | SSCR1_PINTE \
-+ | SSCR1_STRF | SSCR1_EFWR | SSCR1_RFT \
-+ | SSCR1_TFT | SSCR1_SPH | SSCR1_SPO)
-+
-+#define DEFINE_SSP_REG(reg, off) \
-+static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
-+static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); }
-+
-+DEFINE_SSP_REG(SSCR0, 0x00)
-+DEFINE_SSP_REG(SSCR1, 0x04)
-+DEFINE_SSP_REG(SSSR, 0x08)
-+DEFINE_SSP_REG(SSITR, 0x0c)
-+DEFINE_SSP_REG(SSDR, 0x10)
-+DEFINE_SSP_REG(SSTO, 0x28)
-+DEFINE_SSP_REG(SSPSP, 0x2c)
-+
-+DEFINE_SSP_REG(IPCCSR, 0x00);
-+DEFINE_SSP_REG(IPCPISR, 0x08);
-+DEFINE_SSP_REG(IPCPIMR, 0x10);
-+
-+DEFINE_SSP_REG(I2CCTRL, 0x00);
-+DEFINE_SSP_REG(I2CDATA, 0x04);
-+
-+DEFINE_SSP_REG(GPLR1, 0x04);
-+DEFINE_SSP_REG(GPDR1, 0x0c);
-+DEFINE_SSP_REG(GPSR1, 0x14);
-+DEFINE_SSP_REG(GPCR1, 0x1C);
-+DEFINE_SSP_REG(GAFR1_U, 0x44);
-+
-+#define START_STATE ((void *)0)
-+#define RUNNING_STATE ((void *)1)
-+#define DONE_STATE ((void *)2)
-+#define ERROR_STATE ((void *)-1)
-+
-+struct driver_data {
-+ /* Driver model hookup */
-+ struct pci_dev *pdev;
-+
-+ /* SPI framework hookup */
-+ struct spi_slave *slave;
-+
-+ /* SSP register addresses */
-+ void *paddr;
-+ void *ioaddr;
-+ u32 iolen;
-+ int irq;
-+
-+ /* IPC registers */
-+ void *IPC_paddr;
-+ void *IPC_ioaddr;
-+
-+ /* I2C registers */
-+ void *I2C_paddr;
-+ void *I2C_ioaddr;
-+
-+ /* SSP masks*/
-+ u32 dma_cr1;
-+ u32 int_cr1;
-+ u32 clear_sr;
-+ u32 mask_sr;
-+
-+ struct tasklet_struct poll_transfer;
-+
-+ spinlock_t lock;
-+ int busy;
-+ int run;
-+
-+ /* Current message transfer state info */
-+ struct spi_message *cur_msg;
-+ size_t len;
-+ void *tx;
-+ void *tx_end;
-+ void *rx;
-+ void *rx_end;
-+ int dma_mapped;
-+ dma_addr_t rx_dma;
-+ dma_addr_t tx_dma;
-+ size_t rx_map_len;
-+ size_t tx_map_len;
-+ u8 n_bytes;
-+ int (*write)(struct driver_data *drv_data);
-+ int (*read)(struct driver_data *drv_data);
-+ irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
-+ void (*cs_control)(u32 command);
-+
-+#ifdef CONFIG_SPI_MRST_SLAVE_DMA
-+ struct lnw_dma_slave dmas_tx;
-+ struct lnw_dma_slave dmas_rx;
-+ struct dma_chan *txchan;
-+ struct dma_chan *rxchan;
-+
-+ int txdma_done;
-+ int rxdma_done;
-+ u64 tx_param;
-+ u64 rx_param;
-+ struct pci_dev *dmac1;
-+#endif
-+};
-+
-+struct chip_data {
-+ u32 cr0;
-+ u32 cr1;
-+ u32 psp;
-+ u32 timeout;
-+ u8 n_bytes;
-+ u32 threshold;
-+ u8 enable_dma;
-+ u8 poll_mode; /* 1 means use poll mode */
-+ u8 bits_per_word;
-+ int (*write)(struct driver_data *drv_data);
-+ int (*read)(struct driver_data *drv_data);
-+};
-+
-+static void flush(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ u32 sssr;
-+
-+ /* If the transmit fifo is not empty, reset the interface. */
-+ sssr = read_SSSR(reg);
-+ if ((sssr & 0xf00) || (sssr & SSSR_TNF) == 0) {
-+ write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-+ return;
-+ }
-+
-+ while (read_SSSR(reg) & SSSR_RNE)
-+ read_SSDR(reg);
-+
-+ write_SSSR(SSSR_ROR, reg);
-+ write_SSSR(SSSR_TUR, reg);
-+
-+ return;
-+}
-+
-+static int null_writer(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ u8 n_bytes = drv_data->n_bytes;
-+
-+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
-+ || (drv_data->tx == drv_data->tx_end))
-+ return 0;
-+
-+ write_SSDR(0, reg);
-+ drv_data->tx += n_bytes;
-+
-+ return 1;
-+}
-+
-+static int null_reader(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ u8 n_bytes = drv_data->n_bytes;
-+
-+ while ((read_SSSR(reg) & SSSR_RNE)
-+ && (drv_data->rx < drv_data->rx_end)) {
-+ read_SSDR(reg);
-+ drv_data->rx += n_bytes;
-+ }
-+
-+ return drv_data->rx == drv_data->rx_end;
-+}
-+
-+static int u8_writer(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
-+ || (drv_data->tx == drv_data->tx_end))
-+ return 0;
-+
-+ write_SSDR(*(u8 *)(drv_data->tx), reg);
-+ ++drv_data->tx;
-+
-+ return 1;
-+}
-+
-+static int u8_reader(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ while ((read_SSSR(reg) & SSSR_RNE)
-+ && (drv_data->rx < drv_data->rx_end)) {
-+ *(u8 *)(drv_data->rx) = read_SSDR(reg);
-+ ++drv_data->rx;
-+ }
-+
-+ return drv_data->rx == drv_data->rx_end;
-+}
-+
-+static int u16_writer(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
-+ || (drv_data->tx == drv_data->tx_end))
-+ return 0;
-+
-+ write_SSDR(*(u16 *)(drv_data->tx), reg);
-+ drv_data->tx += 2;
-+
-+ return 1;
-+}
-+
-+static int u16_reader(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ while ((read_SSSR(reg) & SSSR_RNE)
-+ && (drv_data->rx < drv_data->rx_end)) {
-+ *(u16 *)(drv_data->rx) = read_SSDR(reg);
-+ drv_data->rx += 2;
-+ }
-+
-+ return drv_data->rx == drv_data->rx_end;
-+}
-+
-+static int u32_writer(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
-+ || (drv_data->tx == drv_data->tx_end))
-+ return 0;
-+
-+ write_SSDR(*(u32 *)(drv_data->tx), reg);
-+ drv_data->tx += 4;
-+
-+ return 1;
-+}
-+
-+static int u32_reader(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ while ((read_SSSR(reg) & SSSR_RNE)
-+ && (drv_data->rx < drv_data->rx_end)) {
-+ *(u32 *)(drv_data->rx) = read_SSDR(reg);
-+ drv_data->rx += 4;
-+ }
-+
-+ return drv_data->rx == drv_data->rx_end;
-+}
-+
-+
-+
-+/* caller already set message->status; dma and pio irqs are blocked */
-+static void giveback(struct driver_data *drv_data)
-+{
-+ struct spi_message *msg;
-+
-+ msg = drv_data->cur_msg;
-+ msg->state = NULL;
-+ if (msg->complete)
-+ msg->complete(msg->context);
-+}
-+
-+#ifdef CONFIG_SPI_MRST_SLAVE_DMA
-+
-+static bool chan_filter(struct dma_chan *chan, void *param)
-+{
-+ struct driver_data *drv_data = (struct driver_data *)param;
-+ bool ret = false;
-+
-+ if (!drv_data->dmac1)
-+ return ret;
-+
-+ if (chan->device->dev == &drv_data->dmac1->dev)
-+ ret = true;
-+
-+ return ret;
-+}
-+
-+static void int_transfer_complete(struct driver_data *drv_data);
-+
-+static void mrst_spi_dma_done(void *arg)
-+{
-+ u64 *param = arg;
-+ struct driver_data *drv_data;
-+ int *done;
-+
-+ drv_data = (struct driver_data *)(u32)(*param >> 32);
-+ done = (int *)(u32)(*param & 0xffffffff);
-+ *done = 1;
-+
-+ if (!drv_data->txdma_done || !drv_data->rxdma_done)
-+ return;
-+ int_transfer_complete(drv_data);
-+}
-+
-+static void mrst_spi_dma_init(struct driver_data *drv_data)
-+{
-+ struct lnw_dma_slave *rxs, *txs;
-+ dma_cap_mask_t mask;
-+
-+ /* Use DMAC1 */
-+ drv_data->dmac1 = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0814, NULL);
-+ if (!drv_data->dmac1) {
-+ printk(KERN_WARNING "SPI Slave:Can't find DMAC1\n");
-+ return;
-+ }
-+
-+ /* 1. init rx channel */
-+ rxs = &drv_data->dmas_rx;
-+
-+ rxs->dirn = DMA_FROM_DEVICE;
-+ rxs->hs_mode = LNW_DMA_HW_HS;
-+ rxs->cfg_mode = LNW_DMA_PER_TO_MEM;
-+ rxs->src_width = LNW_DMA_WIDTH_16BIT;
-+ rxs->dst_width = LNW_DMA_WIDTH_32BIT;
-+ rxs->src_msize = LNW_DMA_MSIZE_8;
-+ rxs->dst_msize = LNW_DMA_MSIZE_8;
-+
-+
-+ dma_cap_zero(mask);
-+ dma_cap_set(DMA_MEMCPY, mask);
-+ dma_cap_set(DMA_SLAVE, mask);
-+
-+ drv_data->rxchan = dma_request_channel(mask, chan_filter, drv_data);
-+ if (!drv_data->rxchan)
-+ goto err_exit;
-+
-+ drv_data->rxchan->private = rxs;
-+
-+ /* 2. init tx channel */
-+ txs = &drv_data->dmas_tx;
-+
-+ txs->dirn = DMA_TO_DEVICE;
-+ txs->hs_mode = LNW_DMA_HW_HS;
-+ txs->cfg_mode = LNW_DMA_MEM_TO_PER;
-+ txs->src_width = LNW_DMA_WIDTH_32BIT;
-+ txs->dst_width = LNW_DMA_WIDTH_16BIT;
-+ txs->src_msize = LNW_DMA_MSIZE_8;
-+ txs->dst_msize = LNW_DMA_MSIZE_8;
-+
-+
-+ dma_cap_set(DMA_SLAVE, mask);
-+ dma_cap_set(DMA_MEMCPY, mask);
-+
-+ drv_data->txchan = dma_request_channel(mask, chan_filter, drv_data);
-+ if (!drv_data->txchan)
-+ goto free_rxchan;
-+ else
-+
-+ drv_data->txchan->private = txs;
-+
-+ /* set the dma done bit to 1 */
-+ drv_data->txdma_done = 1;
-+ drv_data->rxdma_done = 1;
-+
-+ drv_data->tx_param = ((u64)(u32)drv_data << 32)
-+ | (u32)(&drv_data->txdma_done);
-+ drv_data->rx_param = ((u64)(u32)drv_data << 32)
-+ | (u32)(&drv_data->rxdma_done);
-+ return;
-+
-+free_rxchan:
-+ printk(KERN_ERR "SPI-Slave Error : DMA Channle Not available\n");
-+ dma_release_channel(drv_data->rxchan);
-+err_exit:
-+ printk(KERN_ERR "SPI-Slave Error : DMA Channel Not available\n");
-+ pci_dev_put(drv_data->dmac1);
-+ return;
-+}
-+
-+static void mrst_spi_dma_exit(struct driver_data *drv_data)
-+{
-+ dma_release_channel(drv_data->txchan);
-+ dma_release_channel(drv_data->rxchan);
-+ pci_dev_put(drv_data->dmac1);
-+}
-+
-+static void dma_transfer(struct driver_data *drv_data)
-+{
-+ dma_addr_t ssdr_addr;
-+ struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
-+ struct dma_chan *txchan, *rxchan;
-+ enum dma_ctrl_flags flag;
-+
-+ /* get Data Read/Write address */
-+ ssdr_addr = (dma_addr_t)(u32)(drv_data->paddr + 0x10);
-+
-+ if (drv_data->tx_dma)
-+ drv_data->txdma_done = 0;
-+
-+ if (drv_data->rx_dma)
-+ drv_data->rxdma_done = 0;
-+
-+ /* 2. start the TX dma transfer */
-+ txchan = drv_data->txchan;
-+ rxchan = drv_data->rxchan;
-+
-+ flag = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
-+
-+ if (drv_data->rx_dma) {
-+ rxdesc = rxchan->device->device_prep_dma_memcpy
-+ (rxchan, /* DMA Channel */
-+ drv_data->rx_dma, /* DAR */
-+ ssdr_addr, /* SAR */
-+ drv_data->len, /* Data Length */
-+ flag); /* Flag */
-+
-+ rxdesc->callback = mrst_spi_dma_done;
-+ rxdesc->callback_param = &drv_data->rx_param;
-+ }
-+
-+ /* 3. start the RX dma transfer */
-+ if (drv_data->tx_dma) {
-+ txdesc = txchan->device->device_prep_dma_memcpy
-+ (txchan, /* DMA Channel */
-+ ssdr_addr, /* DAR */
-+ drv_data->tx_dma, /* SAR */
-+ drv_data->len, /* Data Length */
-+ flag); /* Flag */
-+
-+ txdesc->callback = mrst_spi_dma_done;
-+ txdesc->callback_param = &drv_data->tx_param;
-+ }
-+
-+ if (rxdesc)
-+ rxdesc->tx_submit(rxdesc);
-+ if (txdesc)
-+ txdesc->tx_submit(txdesc);
-+
-+}
-+
-+static int map_dma_buffers(struct driver_data *drv_data)
-+{
-+ drv_data->rx_dma = (dma_addr_t) virt_to_phys(drv_data->rx);
-+ drv_data->tx_dma = (dma_addr_t) virt_to_phys(drv_data->tx);
-+ return 1;
-+}
-+#endif
-+
-+static void int_error_stop(struct driver_data *drv_data, const char* msg)
-+{
-+ void *reg = drv_data->ioaddr;
-+
-+ /* Stop and reset SSP */
-+ write_SSSR(drv_data->clear_sr, reg);
-+ write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-+ write_SSTO(0, reg);
-+ flush(drv_data);
-+
-+ dev_err(&drv_data->pdev->dev, "%s\n", msg);
-+
-+ drv_data->cur_msg->state = ERROR_STATE;
-+}
-+
-+static void int_transfer_complete(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+
-+ /* Clear Status Register */
-+ write_SSSR(drv_data->clear_sr, reg);
-+
-+#ifdef CONFIG_SPI_MRST_SLAVE_DMA
-+ /* Disable Triggers to DMA */
-+ write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-+#else
-+ /* Disable Interrupt */
-+ write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-+#endif
-+ /* Stop getting Time Outs */
-+ write_SSTO(0, reg);
-+
-+ /* Update total byte transfered return count actual bytes read */
-+ drv_data->cur_msg->actual_length += drv_data->len -
-+ (drv_data->rx_end - drv_data->rx);
-+
-+ drv_data->cur_msg->status = 0;
-+ giveback(drv_data);
-+}
-+
-+static void transfer_complete(struct driver_data *drv_data)
-+{
-+ /* Update total byte transfered return count actual bytes read */
-+ drv_data->cur_msg->actual_length +=
-+ drv_data->len - (drv_data->rx_end - drv_data->rx);
-+
-+ drv_data->cur_msg->status = 0;
-+ giveback(drv_data);
-+}
-+
-+static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
-+{
-+ void *reg = drv_data->ioaddr;
-+ 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;
-+ if (irq_status & SSSR_ROR) {
-+ int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
-+ return IRQ_HANDLED;
-+ }
-+
-+ if (irq_status & SSSR_TINT) {
-+ write_SSSR(SSSR_TINT, reg);
-+ if (drv_data->read(drv_data)) {
-+ int_transfer_complete(drv_data);
-+ return IRQ_HANDLED;
-+ }
-+ }
-+
-+ /* Drain rx fifo, Fill tx fifo and prevent overruns */
-+ do {
-+ if (drv_data->read(drv_data)) {
-+ int_transfer_complete(drv_data);
-+ return IRQ_HANDLED;
-+ }
-+ } while (drv_data->write(drv_data));
-+
-+ if (drv_data->read(drv_data)) {
-+ int_transfer_complete(drv_data);
-+ return IRQ_HANDLED;
-+ }
-+
-+ if (drv_data->tx == drv_data->tx_end)
-+ write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static irqreturn_t ssp_int(int irq, void *dev_id)
-+{
-+ struct driver_data *drv_data = dev_id;
-+ void *reg = drv_data->ioaddr;
-+ u32 status = read_SSSR(reg);
-+
-+ #ifdef CONFIG_SPI_MRST_SLAVE_DMA
-+ if (status & SSSR_ROR || status & SSSR_TUR) {
-+ printk(KERN_DEBUG "--- SPI ROR or TUR Occred : SSSR=%x\n", status);
-+ write_SSSR(SSSR_ROR, reg); /* Clear ROR */
-+ write_SSSR(SSSR_TUR, reg); /* Clear TUR */
-+ return IRQ_HANDLED;
-+ }
-+ return IRQ_NONE;
-+ #endif
-+ /* just return if this is not our interrupt */
-+ if (!(read_SSSR(reg) & drv_data->mask_sr))
-+ return IRQ_NONE;
-+
-+ if (!drv_data->cur_msg) {
-+ write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-+ write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-+ write_SSSR(drv_data->clear_sr, reg);
-+
-+ /* Never fail */
-+ return IRQ_HANDLED;
-+ }
-+ return drv_data->transfer_handler(drv_data);
-+}
-+
-+static void poll_transfer(unsigned long data)
-+{
-+ struct driver_data *drv_data = (struct driver_data *)data;
-+
-+ if (drv_data->tx)
-+ while (drv_data->tx != drv_data->tx_end) {
-+ drv_data->write(drv_data);
-+ drv_data->read(drv_data);
-+ }
-+
-+ while (!drv_data->read(drv_data))
-+ ;
-+
-+ transfer_complete(drv_data);
-+}
-+
-+static int transfer(struct spi_device *spi, struct spi_message *msg)
-+{
-+ struct driver_data *drv_data = \
-+ spi_slave_get_devdata(spi->slave);
-+ unsigned long flags;
-+ struct chip_data *chip = NULL;
-+ struct spi_transfer *transfer = NULL;
-+ void *reg = drv_data->ioaddr;
-+ void *i2cReg = drv_data->I2C_ioaddr;
-+ u32 clk_div = 0;
-+ u8 bits = 0;
-+ u32 cr0;
-+ u32 cr1;
-+ u32 sssr;
-+
-+ spin_lock_irqsave(&drv_data->lock, flags);
-+ msg->actual_length = 0;
-+ msg->status = -EINPROGRESS;
-+ drv_data->cur_msg = msg;
-+ /* Initial message state*/
-+ msg->state = START_STATE;
-+
-+ /* We handle only one transfer message since the protocol module has to
-+ control the out of band signaling. */
-+ transfer = list_entry(msg->transfers.next,
-+ struct spi_transfer,
-+ transfer_list);
-+
-+ chip = spi_get_ctldata(msg->spi);
-+
-+ drv_data->busy = 1;
-+
-+ /* Check transfer length */
-+ if (transfer->len > 8192) {
-+ dev_warn(&drv_data->pdev->dev, "SPI-SLAVE: transfer "
-+ "length greater than 8192\n");
-+ msg->status = -EINVAL;
-+ giveback(drv_data);
-+ spin_unlock_irqrestore(&drv_data->lock, flags);
-+ return 0;
-+ }
-+
-+ /* Setup the transfer state based on the type of transfer */
-+ flush(drv_data);
-+ drv_data->n_bytes = chip->n_bytes;
-+ drv_data->tx = (void *)transfer->tx_buf;
-+ drv_data->tx_end = drv_data->tx + transfer->len;
-+ drv_data->rx = transfer->rx_buf;
-+ drv_data->rx_end = drv_data->rx + transfer->len;
-+ drv_data->rx_dma = transfer->rx_dma;
-+ drv_data->tx_dma = transfer->tx_dma;
-+ drv_data->len = transfer->len;
-+ 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->bits_per_word) {
-+
-+ bits = chip->bits_per_word;
-+
-+ clk_div = 0x0;
-+
-+ if (transfer->bits_per_word)
-+ bits = transfer->bits_per_word;
-+
-+
-+ if (bits <= 8) {
-+ drv_data->n_bytes = 1;
-+ drv_data->read = drv_data->read != null_reader ?
-+ u8_reader : null_reader;
-+ drv_data->write = drv_data->write != null_writer ?
-+ u8_writer : null_writer;
-+ } else if (bits <= 16) {
-+ drv_data->n_bytes = 2;
-+ drv_data->read = drv_data->read != null_reader ?
-+ u16_reader : null_reader;
-+ drv_data->write = drv_data->write != null_writer ?
-+ u16_writer : null_writer;
-+ } else if (bits <= 32) {
-+ drv_data->n_bytes = 4;
-+ drv_data->read = drv_data->read != null_reader ?
-+ u32_reader : null_reader;
-+ drv_data->write = drv_data->write != null_writer ?
-+ u32_writer : null_writer;
-+ }
-+
-+ cr0 = clk_div
-+ | SSCR0_Motorola
-+ | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
-+ | SSCR0_SSE
-+ | SSCR0_TIM
-+ | SSCR0_RIM
-+ | (bits > 16 ? SSCR0_EDSS : 0);
-+ }
-+
-+
-+#ifdef CONFIG_SPI_MRST_SLAVE_DMA
-+ drv_data->dma_mapped = 0;
-+ if (chip->enable_dma)
-+ drv_data->dma_mapped = map_dma_buffers(drv_data);
-+#endif
-+
-+ msg->state = RUNNING_STATE;
-+ /* Ensure we have the correct interrupt handler */
-+ drv_data->transfer_handler = interrupt_transfer;
-+ /* Clear status */
-+ cr1 = chip->cr1 | chip->threshold;
-+ write_SSSR(drv_data->clear_sr, reg);
-+
-+ /* Reload the config and do bitbanging only if SSP not-enable or not-synchronized */
-+ if( ( read_SSSR(reg) & SSP_NOT_SYNC ) || (!(read_SSCR0(reg) & SSCR0_SSE) ) ) {
-+
-+ write_SSSR(drv_data->clear_sr, reg); /* clear status */
-+ write_SSCR0(cr0 & ~SSCR0_SSE, reg);
-+ write_SSPSP(0x02010007, reg);
-+ write_SSTO(chip->timeout, reg);
-+ write_SSCR1(0x13001DC0, reg); /* TBD remove hardcoded value */
-+ write_SSCR0(cr0, reg);
-+
-+ /*
-+ * This routine uses the DFx block to override the SSP inputs
-+ * and outputs allowing us to bit bang SSPSCLK. On Langwell,
-+ * we have to generate the clock to clear busy.
-+ */
-+
-+ write_I2CDATA(0x3, i2cReg);
-+ udelay(10);
-+ write_I2CCTRL(0x01070034, i2cReg);
-+ udelay(10);
-+ write_I2CDATA(0x00000099, i2cReg);
-+ udelay(10);
-+ write_I2CCTRL(0x01070038, i2cReg);
-+ udelay(10);
-+ sssr = read_SSSR(reg);
-+
-+ /* Bit bang the clock until CSS clears */
-+ while (sssr & 0x400000) {
-+ write_I2CDATA(0x2, i2cReg);
-+ udelay(10);
-+ write_I2CCTRL(0x01070034, i2cReg);
-+ udelay(10);
-+ write_I2CDATA(0x3, i2cReg);
-+ udelay(10);
-+ write_I2CCTRL(0x01070034, i2cReg);
-+ udelay(10);
-+ sssr = read_SSSR(reg);
-+ }
-+
-+ write_I2CDATA(0x0, i2cReg);
-+ udelay(10);
-+ write_I2CCTRL(0x01070038, i2cReg);
-+
-+ } else {
-+ write_SSTO(chip->timeout, reg);
-+ write_SSCR1(0x13001DC0, reg); /* TBD: remove hardcoded value */
-+ }
-+
-+ /* transfer using DMA */
-+ if (drv_data->dma_mapped) {
-+#ifdef CONFIG_SPI_MRST_SLAVE_DMA
-+ cr1 = cr1 | drv_data->dma_cr1;
-+ write_SSCR1(0x13701DC0, reg); /* TBD: remove hardcoded value */
-+ dma_transfer(drv_data);
-+#endif
-+ }
-+
-+ /* transfer using non interrupt polling */
-+ else if (chip->poll_mode)
-+ tasklet_schedule(&drv_data->poll_transfer);
-+
-+ /* transfer using interrupt driven programmed I/O */
-+ else {
-+ cr1 = cr1 | drv_data->int_cr1;
-+ write_SSCR1(cr1, reg);
-+ }
-+
-+ spin_unlock_irqrestore(&drv_data->lock, flags);
-+ return 0;
-+}
-+
-+static int setup(struct spi_device *spi)
-+{
-+ struct mrst_spi_chip *chip_info = NULL;
-+ struct chip_data *chip;
-+
-+ if (!spi->bits_per_word)
-+ spi->bits_per_word = 8;
-+
-+ if ((spi->bits_per_word < 4 || spi->bits_per_word > 32))
-+ return -EINVAL;
-+
-+ /* Only alloc on first setup */
-+ chip = spi_get_ctldata(spi);
-+ if (!chip) {
-+ chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
-+ if (!chip) {
-+ dev_err(&spi->dev,
-+ "failed setup: can't allocate chip data\n");
-+ return -ENOMEM;
-+ }
-+
-+ chip->enable_dma = 1;
-+ chip->poll_mode = 1;
-+ chip->timeout = 1000;
-+ chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
-+ }
-+
-+ /*
-+ * protocol drivers may change the chip settings, so...
-+ * if chip_info exists, use it
-+ */
-+ chip_info = spi->controller_data;
-+
-+ /* chip_info isn't always needed */
-+ chip->cr1 = 0;
-+ if (chip_info) {
-+
-+ chip->timeout = chip_info->timeout;
-+
-+ chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) &
-+ SSCR1_RFT) |
-+ (SSCR1_TxTresh(chip_info->tx_threshold) &
-+ SSCR1_TFT);
-+
-+
-+ if (chip_info->enable_loopback)
-+ chip->cr1 = SSCR1_LBM;
-+ }
-+
-+ chip->cr0 = SSCR0_Motorola
-+ | SSCR0_DataSize(spi->bits_per_word > 16 ?
-+ spi->bits_per_word - 16 : spi->bits_per_word)
-+ | SSCR0_SSE
-+ | SSCR0_TIM
-+ | SSCR0_RIM
-+ | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
-+ chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
-+ chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
-+ | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
-+ /* set slave mode */
-+ chip->cr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
-+ chip->cr1 |= SSCR1_SCFR; /* slave clock is not free running */
-+ dev_dbg(&spi->dev, "%d bits/word, mode %d\n",
-+ spi->bits_per_word,
-+ spi->mode & 0x3);
-+
-+ if (spi->bits_per_word <= 8) {
-+ chip->n_bytes = 1;
-+ chip->read = u8_reader;
-+ chip->write = u8_writer;
-+ } else if (spi->bits_per_word <= 16) {
-+ chip->n_bytes = 2;
-+ chip->read = u16_reader;
-+ chip->write = u16_writer;
-+ } else if (spi->bits_per_word <= 32) {
-+ chip->cr0 |= SSCR0_EDSS;
-+ chip->n_bytes = 4;
-+ chip->read = u32_reader;
-+ chip->write = u32_writer;
-+ } else {
-+ dev_err(&spi->dev, "invalid wordsize\n");
-+ return -ENODEV;
-+ }
-+ chip->bits_per_word = spi->bits_per_word;
-+ spi_set_ctldata(spi, chip);
-+
-+ return 0;
-+}
-+
-+static void cleanup(struct spi_device *spi)
-+{
-+ struct chip_data *chip = spi_get_ctldata(spi);
-+
-+ kfree(chip);
-+}
-+
-+static struct mrst_spi_chip spidev_chip_info = {
-+ .tx_threshold = 8, /* SSP hardware FIFO threshold */
-+ .rx_threshold = 8, /* SSP hardware FIFO threshold */
-+ .timeout = 235, /* See Intel documentation */
-+};
-+
-+/*
-+ * mrst_parse_spi_dib - mrst-ssp parse the spi device info block
-+ * table
-+ * @pdev: spi controller pci device structure
-+ * @drv_data: spi controller driver data
-+ * Context: can sleep
-+ *
-+ * ssp controller needs to parse the spi device info block table
-+ * saved in PCI bar 1 and register them with the spi core subsystem.
-+ */
-+static void mrst_parse_spi_dib(struct pci_dev *pdev,
-+ struct driver_data *drv_data)
-+{
-+ u32 dib_len;
-+ void *dib_vaddr;
-+ unsigned long dib_paddr;
-+ struct spi_board_info info[1];
-+ struct spi_dib_header *header;
-+ struct spi_dib *dib;
-+ int info_num, i, j, dib_bar;
-+ u16 *pval;
-+
-+ dib_bar = 1;
-+ dib_paddr = pci_resource_start(pdev, dib_bar);
-+ dib_len = pci_resource_len(pdev, dib_bar);
-+
-+ printk(KERN_INFO "SPI-Slave: %s() - paddr = 0x%08lx, "
-+ "iolen = 0x%x\n", __func__, dib_paddr, dib_len);
-+
-+ dib_vaddr = ioremap(dib_paddr, dib_len);
-+ if (!dib_vaddr) {
-+ dev_err(&pdev->dev, "%s(): ioremap failed\n", __func__);
-+ goto err_ioremap;
-+ }
-+
-+ /* bar1 contains a pointer to the SPI DIB table */
-+ if (dib_len == 8) {
-+ u32 *ptemp = (u32 *)dib_vaddr;
-+ dib_len = *(ptemp + 1);
-+ dib_vaddr = ioremap(*(unsigned long *)dib_vaddr, dib_len);
-+ iounmap(ptemp);
-+ }
-+
-+ header = (struct spi_dib_header *)dib_vaddr;
-+ info_num = (header->length - sizeof(*header)) /
-+ sizeof(*dib);
-+ dib = (struct spi_dib *)&header[1];
-+
-+ /* search for our dib entry. */
-+ for (i = 0; i < info_num; i++)
-+ if (dib[i].host_num == 3)
-+ break;
-+ if (i == info_num)
-+ return;
-+
-+ strncpy(info[0].modalias, dib[i].name, SPI_DIB_NAME_LEN);
-+ info[0].irq = dib[i].irq;
-+ info[0].bus_num = dib[i].host_num;
-+ info[0].chip_select = dib[i].cs;
-+ info[0].mode = 0;
-+ info[0].max_speed_hz = 0;
-+
-+ printk(KERN_INFO "SPI-Slave: name = %s, irq = 0x%x, "
-+ "bus = %d, cs = %d\n", info[0].modalias, info[0].irq,
-+ info[0].bus_num, info[0].chip_select);
-+
-+ pval = (u16 *)&(dib[i].dev_data[0]);
-+
-+ info[0].controller_data = &spidev_chip_info; /* Slave chip config */
-+
-+ for (j = 0; j < 5; j++) {
-+ spidev_chip_info.extra_data[j] = *pval;
-+ pval++;
-+ }
-+
-+ spi_register_board_info(info, 1);
-+
-+err_ioremap:
-+ pci_release_region(pdev, dib_bar);
-+
-+ return;
-+}
-+
-+static int mrst_spi_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct spi_slave *slave;
-+ struct driver_data *drv_data = 0;
-+ int status = 0;
-+ int pci_bar = 0;
-+
-+ printk(KERN_INFO "SPI-Slave: found PCI SSP controller(ID: %04x:%04x)\n",
-+ pdev->vendor, pdev->device);
-+
-+ status = pci_enable_device(pdev);
-+ if (status)
-+ return status;
-+
-+ /* Allocate Slave with space for drv_data and null dma buffer */
-+ slave = spi_alloc_slave(dev, sizeof(struct driver_data));
-+
-+ if (!slave) {
-+ dev_err(&pdev->dev, "cannot alloc spi_slave\n");
-+ status = -ENOMEM;
-+ goto err_free_slave0;
-+ }
-+
-+ drv_data = spi_slave_get_devdata(slave);
-+ drv_data->slave = slave;
-+
-+ drv_data->pdev = pdev;
-+ spin_lock_init(&drv_data->lock);
-+
-+ slave->bus_num = 3;
-+ slave->num_chipselect = 1;
-+ slave->cleanup = cleanup;
-+ slave->setup = setup;
-+ slave->transfer = transfer;
-+
-+ /* get basic io resource and map it */
-+ drv_data->paddr = (void *)pci_resource_start(pdev, pci_bar);
-+ drv_data->iolen = pci_resource_len(pdev, pci_bar);
-+
-+ status = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
-+ if (status)
-+ goto err_free_slave1;
-+
-+ drv_data->ioaddr =
-+ ioremap_nocache((u32)drv_data->paddr, drv_data->iolen);
-+ if (!drv_data->ioaddr) {
-+ status = -ENOMEM;
-+ goto err_free_slave2;
-+ }
-+ printk(KERN_INFO "SPI-Slave: ioaddr = : %08x\n", (int)drv_data->ioaddr);
-+ printk(KERN_INFO "SPI-Slave: attaching to IRQ: %04x\n", pdev->irq);
-+
-+ mrst_parse_spi_dib(pdev, drv_data);
-+
-+ /* get base address of IPC registers */
-+ drv_data->IPC_paddr = (void *)0xffae8000;
-+ drv_data->IPC_ioaddr =
-+ ioremap_nocache((unsigned long)drv_data->IPC_paddr, 0x80);
-+ if (!drv_data->IPC_ioaddr) {
-+ status = -ENOMEM;
-+ goto err_free_slave3;
-+ }
-+ /* get base address of I2C_Serbus registers */
-+ drv_data->I2C_paddr = (void *)0xff12b000;
-+ drv_data->I2C_ioaddr =
-+ ioremap_nocache((unsigned long)drv_data->I2C_paddr, 0x10);
-+ if (!drv_data->I2C_ioaddr) {
-+ status = -ENOMEM;
-+ goto err_free_slave4;
-+ }
-+
-+ printk(KERN_INFO "SPI-Slave: IPC_ioaddr = : %08x\n",
-+ (int)drv_data->IPC_ioaddr);
-+ printk(KERN_INFO "SPI-Slave: IPCCSR = : %08x\n",
-+ read_IPCCSR(drv_data->IPC_ioaddr));
-+ write_IPCCSR(0x802, drv_data->IPC_ioaddr);
-+ printk(KERN_INFO "SPI-Slave: IPCCSR = : %08x\n",
-+ read_IPCCSR(drv_data->IPC_ioaddr));
-+
-+ /* Attach to IRQ */
-+ drv_data->irq = pdev->irq;
-+ status = request_irq(drv_data->irq, ssp_int, IRQF_SHARED,
-+ "mrst_spi3", drv_data);
-+ if (status < 0) {
-+ dev_err(&pdev->dev, "can not get IRQ\n");
-+ goto err_free_slave5;
-+ }
-+
-+ drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
-+ drv_data->dma_cr1 = SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL;
-+ drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
-+ drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
-+
-+ tasklet_init(&drv_data->poll_transfer,
-+ poll_transfer, (unsigned long)drv_data);
-+
-+ /* Setup DMA if requested */
-+
-+ /* Load default SSP configuration */
-+ printk(KERN_INFO "SPI-Slave: setup default SSP configuration\n");
-+ write_SSCR0(0, drv_data->ioaddr);
-+ write_SSCR1(SSCR1_RxTresh(4) | SSCR1_TxTresh(12), drv_data->ioaddr);
-+ write_SSCR0(SSCR0_Motorola
-+ | SSCR0_DataSize(8),
-+ drv_data->ioaddr);
-+ write_SSTO(0, drv_data->ioaddr);
-+ write_SSPSP(0x02010007, drv_data->ioaddr);
-+
-+ /* Register with the SPI framework */
-+ printk(KERN_INFO "SPI-Slave: register with SPI framework\n");
-+
-+ status = spi_register_slave(slave);
-+
-+ if (status != 0) {
-+ dev_err(&pdev->dev, "problem registering spi slave\n");
-+ goto err_free_slave6;
-+ }
-+
-+#ifdef CONFIG_SPI_MRST_SLAVE_DMA
-+ mrst_spi_dma_init(drv_data);
-+#endif
-+
-+ pci_set_drvdata(pdev, drv_data);
-+
-+ return status;
-+
-+err_free_slave6:
-+ free_irq(drv_data->irq, drv_data);
-+err_free_slave5:
-+ iounmap(drv_data->I2C_ioaddr);
-+err_free_slave4:
-+ iounmap(drv_data->IPC_ioaddr);
-+err_free_slave3:
-+ iounmap(drv_data->ioaddr);
-+err_free_slave2:
-+ pci_release_region(pdev, pci_bar);
-+err_free_slave1:
-+ spi_slave_put(slave);
-+err_free_slave0:
-+ pci_disable_device(pdev);
-+
-+ return status;
-+}
-+
-+static void __devexit mrst_spi_remove(struct pci_dev *pdev)
-+{
-+ struct driver_data *drv_data = pci_get_drvdata(pdev);
-+
-+ if (!drv_data)
-+ return;
-+
-+ pci_set_drvdata(pdev, NULL);
-+
-+#ifdef CONFIG_SPI_MRST_SLAVE_DMA
-+ mrst_spi_dma_exit(drv_data);
-+ pci_dev_put(drv_data->dmac1);
-+#endif
-+
-+ /* Release IRQ */
-+ free_irq(drv_data->irq, drv_data);
-+
-+ iounmap(drv_data->ioaddr);
-+ iounmap(drv_data->I2C_ioaddr);
-+ iounmap(drv_data->IPC_ioaddr);
-+
-+ pci_release_region(pdev, 0);
-+
-+ /* disconnect from the SPI framework */
-+ spi_unregister_slave(drv_data->slave);
-+
-+ pci_disable_device(pdev);
-+
-+ return;
-+}
-+
-+#ifdef CONFIG_PM
-+
-+static int mrst_spi_suspend(struct pci_dev *pdev, pm_message_t state)
-+{
-+ struct driver_data *drv_data = pci_get_drvdata(pdev);
-+ printk(KERN_ERR "spi-slave: suspend\n");
-+
-+ tasklet_disable(&drv_data->poll_transfer);
-+
-+ return 0;
-+}
-+
-+static int mrst_spi_resume(struct pci_dev *pdev)
-+{
-+ struct driver_data *drv_data = pci_get_drvdata(pdev);
-+ printk(KERN_ERR "spi-slave: resume\n");
-+
-+ tasklet_enable(&drv_data->poll_transfer);
-+
-+ return 0;
-+}
-+#else
-+#define mrst_spi_suspend NULL
-+#define mrst_spi_resume NULL
-+#endif /* CONFIG_PM */
-+
-+
-+static const struct pci_device_id pci_ids[] __devinitdata = {
-+
-+ {
-+ .vendor = PCI_VENDOR_ID_INTEL,
-+ .device = 0x0815,
-+ .subvendor = PCI_ANY_ID,
-+ .subdevice = PCI_ANY_ID,
-+ },
-+ {},
-+};
-+
-+static struct pci_driver mrst_spi_slave_driver = {
-+ .name = DRIVER_NAME,
-+ .id_table = pci_ids,
-+ .probe = mrst_spi_probe,
-+ .remove = __devexit_p(mrst_spi_remove),
-+ .suspend = mrst_spi_suspend,
-+ .resume = mrst_spi_resume,
-+};
-+
-+static int __init mrst_spi_init(void)
-+{
-+ return pci_register_driver(&mrst_spi_slave_driver);
-+}
-+
-+late_initcall_sync(mrst_spi_init);
-+
-+static void __exit mrst_spi_exit(void)
-+{
-+ pci_unregister_driver(&mrst_spi_slave_driver);
-+}
-+module_exit(mrst_spi_exit);
-diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
-index b76f246..f58f8c3 100644
---- a/drivers/spi/spi.c
-+++ b/drivers/spi/spi.c
-@@ -27,10 +27,16 @@
- #include <linux/spi/spi.h>
-
-
--/* SPI bustype and spi_master class are registered after board init code
-- * provides the SPI device tables, ensuring that both are present by the
-- * time controller driver registration causes spi_devices to "enumerate".
-- */
-+/* SPI bustype, spi_master and spi_slave class are registered after board
-+* init code provides the SPI device tables, ensuring that both are present
-+* by the time controller driver registration causes spi_devices
-+* to "enumerate".
-+*/
-+
-+/* SPI Slave Support is added for new spi slave devices: It uses common APIs,
-+* apart from few new APIs and a spi_slave structure.
-+*/
-+
- static void spidev_release(struct device *dev)
- {
- struct spi_device *spi = to_spi_device(dev);
-@@ -43,11 +49,22 @@ static void spidev_release(struct device *dev)
- kfree(dev);
- }
-
-+static void spidev_slave_release(struct device *dev)
-+{
-+ struct spi_device *spi = to_spi_device(dev);
-+
-+ /* spi slave may cleanup */
-+ if (spi->slave->cleanup)
-+ spi->slave->cleanup(spi);
-+
-+ spi_slave_put(spi->slave);
-+ kfree(dev);
-+}
-+
- static ssize_t
- modalias_show(struct device *dev, struct device_attribute *a, char *buf)
- {
- const struct spi_device *spi = to_spi_device(dev);
--
- return sprintf(buf, "%s\n", spi->modalias);
- }
-
-@@ -177,10 +194,13 @@ int spi_register_driver(struct spi_driver *sdrv)
- sdrv->driver.bus = &spi_bus_type;
- if (sdrv->probe)
- sdrv->driver.probe = spi_drv_probe;
-+
- if (sdrv->remove)
- sdrv->driver.remove = spi_drv_remove;
-+
- if (sdrv->shutdown)
- sdrv->driver.shutdown = spi_drv_shutdown;
-+
- return driver_register(&sdrv->driver);
- }
- EXPORT_SYMBOL_GPL(spi_register_driver);
-@@ -201,6 +221,7 @@ struct boardinfo {
-
- static LIST_HEAD(board_list);
- static DEFINE_MUTEX(board_lock);
-+static DEFINE_MUTEX(slave_board_lock);
-
- /**
- * spi_alloc_device - Allocate a new SPI device
-@@ -221,28 +242,70 @@ static DEFINE_MUTEX(board_lock);
- */
- struct spi_device *spi_alloc_device(struct spi_master *master)
- {
-- struct spi_device *spi;
-+ struct spi_device *spi_m_dev;
- struct device *dev = master->dev.parent;
-
- if (!spi_master_get(master))
- return NULL;
-
-- spi = kzalloc(sizeof *spi, GFP_KERNEL);
-- if (!spi) {
-+ spi_m_dev = kzalloc(sizeof *spi_m_dev, GFP_KERNEL);
-+ if (!spi_m_dev) {
- dev_err(dev, "cannot alloc spi_device\n");
- spi_master_put(master);
- return NULL;
- }
-
-- spi->master = master;
-- spi->dev.parent = dev;
-- spi->dev.bus = &spi_bus_type;
-- spi->dev.release = spidev_release;
-- device_initialize(&spi->dev);
-- return spi;
-+ spi_m_dev->master = master;
-+ spi_m_dev->using_slave = 0;
-+ spi_m_dev->dev.parent = dev;
-+ spi_m_dev->dev.bus = &spi_bus_type;
-+ spi_m_dev->dev.release = spidev_release;
-+ device_initialize(&spi_m_dev->dev);
-+ return spi_m_dev;
- }
- EXPORT_SYMBOL_GPL(spi_alloc_device);
-
-+/*
-+* spi_alloc_slave_device - Allocate a new SPI device
-+* @slave: Controller to which device is connected
-+* Context: can sleep
-+*
-+* Allows a driver to allocate and initialize a spi_device without
-+* registering it immediately. This allows a driver to directly
-+* fill the spi_device with device parameters before calling
-+* spi_add_slave_device() on it.
-+*
-+* Caller is responsible to call spi_add_slave_device() on the returned
-+* spi_device structure to add it to the SPI slave. If the caller
-+* needs to discard the spi_device without adding it, then it should
-+* call spi_dev_slave_put() on it.
-+* Returns a pointer to the new device, or NULL.
-+*/
-+struct spi_device *spi_alloc_slave_device(struct spi_slave *slave)
-+{
-+ struct spi_device *spi_s;
-+ struct device *dev = slave->dev.parent;
-+
-+ if (!spi_slave_get(slave))
-+ return NULL;
-+
-+ spi_s = kzalloc(sizeof *spi_s, GFP_KERNEL);
-+ if (!spi_s) {
-+ dev_err(dev, "cannot alloc spi_slave_device\n");
-+ spi_slave_put(slave);
-+ return NULL;
-+ }
-+
-+ spi_s->slave = slave;
-+ spi_s->using_slave = 9;
-+ spi_s->dev.parent = dev;
-+ spi_s->dev.bus = &spi_bus_type;
-+ spi_s->dev.release = spidev_slave_release;
-+ device_initialize(&spi_s->dev);
-+ return spi_s;
-+}
-+EXPORT_SYMBOL_GPL(spi_alloc_slave_device);
-+
- /**
- * spi_add_device - Add spi_device allocated with spi_alloc_device
- * @spi: spi_device to register
-@@ -301,6 +364,7 @@ int spi_add_device(struct spi_device *spi)
- if (status < 0)
- dev_err(dev, "can't %s %s, status %d\n",
- "add", dev_name(&spi->dev), status);
-+
- else
- dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
-
-@@ -311,6 +375,74 @@ done:
- EXPORT_SYMBOL_GPL(spi_add_device);
-
- /**
-+* spi_add_slave_device - Add spi_device allocated with spi_alloc_slave_device
-+* @spi: spi_device to register
-+*
-+* Companion function to spi_alloc_slave_device. Devices allocated with
-+* spi_alloc_slave_device can be added onto the spi bus with this function.
-+*
-+* Returns 0 on success; negative errno on failure
-+*/
-+int spi_add_slave_device(struct spi_device *spi)
-+{
-+ static DEFINE_MUTEX(spi_slave_add_lock);
-+ struct device *dev = spi->slave->dev.parent;
-+ int status;
-+
-+ /* Chipselects are numbered 0..max; validate. */
-+ if (spi->chip_select >= spi->slave->num_chipselect) {
-+ dev_err(dev, "cs%d >= max %d\n",
-+ spi->chip_select,
-+ spi->slave->num_chipselect);
-+ return -EINVAL;
-+ }
-+
-+ /* Set the bus ID string */
-+ dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->slave->dev),
-+ spi->chip_select);
-+
-+
-+ /* We need to make sure there's no other device with this
-+ * chipselect **BEFORE** we call setup(), else we'll trash
-+ * its configuration. Lock against concurrent add() calls.
-+ */
-+ mutex_lock(&spi_slave_add_lock);
-+
-+ if (bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev))
-+ != NULL) {
-+ dev_err(dev, "chipselect %d already in use\n",
-+ spi->chip_select);
-+ status = -EBUSY;
-+ goto done;
-+ }
-+
-+ /* Drivers may modify this initial i/o setup, but will
-+ * normally rely on the device being setup. Devices
-+ * using SPI_CS_HIGH can't coexist well otherwise...
-+ */
-+ status = spi->slave->setup(spi);
-+ if (status < 0) {
-+ dev_err(dev, "can't %s %s, status %d\n",
-+ "setup", dev_name(&spi->dev), status);
-+ goto done;
-+ }
-+
-+ /* Device may be bound to an active driver when this returns */
-+ status = device_add(&spi->dev);
-+ if (status < 0)
-+ dev_err(dev, "can't %s %s, status %d\n",
-+ "add", dev_name(&spi->dev), status);
-+ else
-+ dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
-+
-+done:
-+ mutex_unlock(&spi_slave_add_lock);
-+ return status;
-+}
-+EXPORT_SYMBOL_GPL(spi_add_slave_device);
-+
-+
-+/**
- * spi_new_device - instantiate one new SPI device
- * @master: Controller to which device is connected
- * @chip: Describes the SPI device
-@@ -341,6 +473,8 @@ struct spi_device *spi_new_device(struct spi_master *master,
- if (!proxy)
- return NULL;
-
-+
-+
- WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
-
- proxy->chip_select = chip->chip_select;
-@@ -363,6 +497,54 @@ struct spi_device *spi_new_device(struct spi_master *master,
- EXPORT_SYMBOL_GPL(spi_new_device);
-
- /**
-+* spi_slave_new_device - instantiate one new SPI device
-+* @slave: Controller to which device is connected
-+* @chip: Describes the SPI device
-+* Context: can sleep
-+*
-+* On typical mainboards, this is purely internal; and it's not needed
-+* after board init creates the hard-wired devices. Some development
-+* platforms may not be able to use spi_register_board_info though, and
-+* this is exported so that for example a USB or parport based adapter
-+* driver could add devices (which it would learn about out-of-band).
-+*
-+* Returns the new device, or NULL.
-+*/
-+struct spi_device *spi_slave_new_device(struct spi_slave *slave,
-+ struct spi_board_info *chip)
-+{
-+ struct spi_device *proxy_slave;
-+ int status;
-+
-+ proxy_slave = spi_alloc_slave_device(slave);
-+
-+ if (!proxy_slave)
-+ return NULL;
-+
-+ WARN_ON(strlen(chip->modalias) >= sizeof(proxy_slave->modalias));
-+
-+ proxy_slave->chip_select = chip->chip_select;
-+ proxy_slave->max_speed_hz = chip->max_speed_hz;
-+ proxy_slave->mode = chip->mode;
-+ proxy_slave->irq = chip->irq;
-+ strlcpy(proxy_slave->modalias, chip->modalias,
-+ sizeof(proxy_slave->modalias));
-+ proxy_slave->dev.platform_data = (void *) chip->platform_data;
-+ proxy_slave->controller_data = chip->controller_data;
-+ proxy_slave->controller_state = NULL;
-+
-+ status = spi_add_slave_device(proxy_slave);
-+ if (status < 0) {
-+ spi_dev_put(proxy_slave);
-+ return NULL;
-+ }
-+
-+ return proxy_slave;
-+}
-+EXPORT_SYMBOL_GPL(spi_slave_new_device);
-+
-+
-+/**
- * spi_register_board_info - register SPI devices for a given board
- * @info: array of chip descriptors
- * @n: how many descriptors are provided
-@@ -389,6 +571,7 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
- bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
- if (!bi)
- return -ENOMEM;
-+
- bi->n_board_info = n;
- memcpy(bi->board_info, info, n * sizeof *info);
-
-@@ -398,6 +581,7 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
- return 0;
- }
-
-+
- /* FIXME someone should add support for a __setup("spi", ...) that
- * creates board info from kernel command lines
- */
-@@ -423,6 +607,28 @@ static void scan_boardinfo(struct spi_master *master)
- mutex_unlock(&board_lock);
- }
-
-+static void spi_slave_scan_boardinfo(struct spi_slave *slave)
-+{
-+ struct boardinfo *bi;
-+
-+ mutex_lock(&slave_board_lock);
-+ list_for_each_entry(bi, &board_list, list) {
-+ struct spi_board_info *chip = bi->board_info;
-+ unsigned n;
-+
-+ for (n = bi->n_board_info; n > 0; n--, chip++) {
-+ if (chip->bus_num != slave->bus_num)
-+ continue;
-+ /* NOTE: this relies on spi_new_device to
-+ * issue diagnostics when given bogus inputs
-+ */
-+ (void) spi_slave_new_device(slave, chip);
-+
-+ }
-+ }
-+ mutex_unlock(&slave_board_lock);
-+}
-+
- /*-------------------------------------------------------------------------*/
-
- static void spi_master_release(struct device *dev)
-@@ -439,6 +645,19 @@ static struct class spi_master_class = {
- .dev_release = spi_master_release,
- };
-
-+static void spi_slave_release(struct device *dev)
-+{
-+ struct spi_slave *slave;
-+
-+ slave = container_of(dev, struct spi_slave, dev);
-+ kfree(slave);
-+}
-+
-+static struct class spi_slave_class = {
-+ .name = "spi_slave",
-+ .owner = THIS_MODULE,
-+ .dev_release = spi_slave_release,
-+};
-
- /**
- * spi_alloc_master - allocate SPI master controller
-@@ -480,6 +699,47 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
- EXPORT_SYMBOL_GPL(spi_alloc_master);
-
- /**
-+* spi_alloc_slave - allocate SPI slave controller
-+* @dev: the controller, possibly using the platform_bus
-+* @size: how much zeroed driver-private data to allocate; the pointer to this
-+* memory is in the driver_data field of the returned device,
-+* accessible with spi_slave_get_devdata().
-+* Context: can sleep
-+*
-+* This call is used only by SPI master controller drivers, which are the
-+* only ones directly touching chip registers. It's how they allocate
-+* an spi_master structure, prior to calling spi_register_slave().
-+*
-+* This must be called from context that can sleep. It returns the SPI
-+* master structure on success, else NULL.
-+*
-+* The caller is responsible for assigning the bus number and initializing
-+* the master's methods before calling spi_register_slave(); and (after errors
-+* adding the device) calling spi_slave_put() to prevent a memory leak.
-+*/
-+struct spi_slave *spi_alloc_slave(struct device *dev, unsigned size)
-+{
-+ struct spi_slave *slave;
-+
-+ if (!dev)
-+ return NULL;
-+
-+ slave = kzalloc(size + sizeof *slave, GFP_KERNEL);
-+ if (!slave)
-+ return NULL;
-+
-+ device_initialize(&slave->dev);
-+ slave->dev.class = &spi_slave_class;
-+ slave->dev.parent = get_device(dev);
-+ spi_slave_set_devdata(slave, &slave[1]);
-+
-+ return slave;
-+}
-+EXPORT_SYMBOL_GPL(spi_alloc_slave);
-+
-+
-+
-+/**
- * spi_register_master - register SPI master controller
- * @master: initialized master, originally from spi_alloc_master()
- * Context: can sleep
-@@ -531,7 +791,8 @@ int spi_register_master(struct spi_master *master)
- status = device_add(&master->dev);
- if (status < 0)
- goto done;
-- dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
-+
-+ dev_dbg(dev, "spi_register_master() : %s%s\n", dev_name(&master->dev),
- dynamic ? " (dynamic)" : "");
-
- /* populate children from any spi device tables */
-@@ -542,6 +803,71 @@ done:
- }
- EXPORT_SYMBOL_GPL(spi_register_master);
-
-+/**
-+* spi_register_slave - register SPI slave controller
-+* @master: initialized master, originally from spi_alloc_slave()
-+* Context: can sleep
-+*
-+* SPI slave controllers connect to their drivers using some non-SPI bus,
-+* such as the platform bus. The final stage of probe() in that code
-+* includes calling spi_register_slave() to hook up to this SPI bus glue.
-+*
-+* SPI controllers use board specific (often SOC specific) bus numbers,
-+* and board-specific addressing for SPI devices combines those numbers
-+* with chip select numbers. Since SPI does not directly support dynamic
-+* device identification, boards need configuration tables telling which
-+* chip is at which address.
-+*
-+* This must be called from context that can sleep. It returns zero on
-+* success, else a negative error code (dropping the slave's refcount).
-+* After a successful return, the caller is responsible for calling
-+* spi_unregister_slave().
-+*/
-+int spi_register_slave(struct spi_slave *slave)
-+{
-+ static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
-+ struct device *dev = slave->dev.parent;
-+ int status = -ENODEV;
-+ int dynamic = 0;
-+
-+ if (!dev)
-+ return -ENODEV;
-+
-+ /* even if it's just one always-selected device, there must
-+ * be at least one chipselect
-+ */
-+ if (slave->num_chipselect == 0)
-+ return -EINVAL;
-+
-+ /* convention: dynamically assigned bus IDs count down from the max */
-+ if (slave->bus_num < 0) {
-+ /* FIXME switch to an IDR based scheme, something like
-+ * I2C now uses, so we can't run out of "dynamic" IDs
-+ */
-+ slave->bus_num = atomic_dec_return(&dyn_bus_id);
-+ dynamic = 1;
-+ }
-+
-+ /* register the device, then userspace will see it.
-+ * registration fails if the bus ID is in use.
-+ */
-+ dev_set_name(&slave->dev, "spi%u", slave->bus_num);
-+ status = device_add(&slave->dev);
-+ if (status < 0)
-+ goto done;
-+
-+ dev_dbg(dev, "registered slave %s%s\n", dev_name(&slave->dev),
-+ dynamic ? " (dynamic)" : "");
-+
-+ /* populate children from any spi device tables */
-+ spi_slave_scan_boardinfo(slave);
-+ status = 0;
-+done:
-+ return status;
-+}
-+EXPORT_SYMBOL_GPL(spi_register_slave);
-+
-+
-
- static int __unregister(struct device *dev, void *master_dev)
- {
-@@ -571,6 +897,27 @@ void spi_unregister_master(struct spi_master *master)
- }
- EXPORT_SYMBOL_GPL(spi_unregister_master);
-
-+/**
-+* spi_unregister_slave - unregister SPI slave controller
-+* @master: the slave being unregistered
-+* Context: can sleep
-+*
-+* This call is used only by SPI slave controller drivers, which are the
-+* only ones directly touching chip registers.
-+*
-+* This must be called from context that can sleep.
-+*/
-+void spi_unregister_slave(struct spi_slave *slave)
-+{
-+ int dummy;
-+
-+ dummy = device_for_each_child(slave->dev.parent, &slave->dev,
-+ __unregister);
-+ device_unregister(&slave->dev);
-+}
-+EXPORT_SYMBOL_GPL(spi_unregister_slave);
-+
-+
- static int __spi_master_match(struct device *dev, void *data)
- {
- struct spi_master *m;
-@@ -718,7 +1065,12 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
-
- message->spi = spi;
- message->status = -EINPROGRESS;
-- return master->transfer(spi, message);
-+
-+ /* TODO: ugly*/
-+ if (spi->using_slave == 9)
-+ return spi->slave->transfer(spi, message); /* Slave */
-+ else
-+ return spi->master->transfer(spi, message); /* Master */
- }
- EXPORT_SYMBOL_GPL(spi_async);
-
-@@ -773,6 +1125,18 @@ int spi_sync(struct spi_device *spi, struct spi_message *message)
- }
- EXPORT_SYMBOL_GPL(spi_sync);
-
-+/* spi_transfer_async - Wraper function to allow spi_async to expose to
-+* user protocol drivers for modem handshaking
-+*/
-+
-+int spi_transfer_async(struct spi_device *spi, struct spi_message *message)
-+{
-+ int status;
-+ status = spi_async(spi, message);
-+ return status;
-+}
-+EXPORT_SYMBOL_GPL(spi_transfer_async);
-+
- /* portable code must never pass more than 32 bytes */
- #define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
-
-@@ -871,6 +1235,12 @@ static int __init spi_init(void)
- status = class_register(&spi_master_class);
- if (status < 0)
- goto err2;
-+
-+ status = class_register(&spi_slave_class);
-+
-+ if (status < 0)
-+ goto err2;
-+
- return 0;
-
- err2:
-@@ -890,4 +1260,3 @@ err0:
- * include needing to have boardinfo data structures be much more public.
- */
- postcore_initcall(spi_init);
--
-diff --git a/include/linux/spi/mrst_spi_slave.h b/include/linux/spi/mrst_spi_slave.h
-new file mode 100644
-index 0000000..4d73f0e
---- /dev/null
-+++ b/include/linux/spi/mrst_spi_slave.h
-@@ -0,0 +1,143 @@
-+/*
-+ * Copyright (C) Intel 2009
-+ * Ken Mills <ken.k.mills@intel.com>
-+ *
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ *
-+ */
-+#ifndef MRST_SSP_H_
-+#define MRST_SSP_H_
-+
-+
-+/*
-+ * Langwell SSP serial port register definitions
-+ */
-+
-+#define SSCR0_DSS (0x0000000f) /* Data Size Select (mask) */
-+#define SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..16] */
-+#define SSCR0_FRF (0x00000030) /* FRame Format (mask) */
-+#define SSCR0_Motorola (0x0 << 4) /* Motorola's SPI mode */
-+#define SSCR0_ECS (1 << 6) /* External clock select */
-+#define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */
-+
-+
-+#define SSCR0_SCR (0x000fff00) /* Serial Clock Rate (mask) */
-+#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */
-+#define SSCR0_EDSS (1 << 20) /* Extended data size select */
-+#define SSCR0_NCS (1 << 21) /* Network clock select */
-+#define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun int mask */
-+#define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun int mask */
-+#define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */
-+#define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame */
-+#define SSCR0_ADC (1 << 30) /* Audio clock select */
-+#define SSCR0_MOD (1 << 31) /* Mode (normal or network) */
-+
-+
-+#define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */
-+#define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */
-+#define SSCR1_LBM (1 << 2) /* Loop-Back Mode */
-+#define SSCR1_SPO (1 << 3) /* SSPSCLK polarity setting */
-+#define SSCR1_SPH (1 << 4) /* Motorola SPI SSPSCLK phase setting */
-+#define SSCR1_MWDS (1 << 5) /* Microwire Transmit Data Size */
-+#define SSCR1_TFT (0x000003c0) /* Transmit FIFO Threshold (mask) */
-+#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */
-+#define SSCR1_RFT (0x00003c00) /* Receive FIFO Threshold (mask) */
-+#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */
-+
-+#define SSSR_TNF (1 << 2) /* Transmit FIFO Not Full */
-+#define SSSR_RNE (1 << 3) /* Receive FIFO Not Empty */
-+#define SSSR_BSY (1 << 4) /* SSP Busy */
-+#define SSSR_TFS (1 << 5) /* Transmit FIFO Service Request */
-+#define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */
-+#define SSSR_ROR (1 << 7) /* Receive FIFO Overrun */
-+
-+#define SSCR0_TIM (1 << 23) /* Transmit FIFO Under Run Int Mask */
-+#define SSCR0_RIM (1 << 22) /* Receive FIFO Over Run int Mask */
-+#define SSCR0_NCS (1 << 21) /* Network Clock Select */
-+#define SSCR0_EDSS (1 << 20) /* Extended Data Size Select */
-+
-+#define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */
-+#define SSCR0_PSP (3 << 4) /* PSP - Programmable Serial Protocol */
-+#define SSCR1_TTELP (1 << 31) /* TXD Tristate Enable Last Phase */
-+#define SSCR1_TTE (1 << 30) /* TXD Tristate Enable */
-+#define SSCR1_EBCEI (1 << 29) /* Enable Bit Count Error interrupt */
-+#define SSCR1_SCFR (1 << 28) /* Slave Clock free Running */
-+#define SSCR1_ECRA (1 << 27) /* Enable Clock Request A */
-+#define SSCR1_ECRB (1 << 26) /* Enable Clock request B */
-+#define SSCR1_SCLKDIR (1 << 25) /* Serial Bit Rate Clock Direction */
-+#define SSCR1_SFRMDIR (1 << 24) /* Frame Direction */
-+#define SSCR1_RWOT (1 << 23) /* Receive Without Transmit */
-+#define SSCR1_TRAIL (1 << 22) /* Trailing Byte */
-+#define SSCR1_TSRE (1 << 21) /* Transmit Service Request Enable */
-+#define SSCR1_RSRE (1 << 20) /* Receive Service Request Enable */
-+#define SSCR1_TINTE (1 << 19) /* Receiver Time-out Interrupt enable */
-+#define SSCR1_PINTE (1 << 18) /* Trailing Byte Interupt Enable */
-+#define SSCR1_STRF (1 << 15) /* Select FIFO or EFWR */
-+#define SSCR1_EFWR (1 << 14) /* Enable FIFO Write/Read */
-+
-+#define SSSR_BCE (1 << 23) /* Bit Count Error */
-+#define SSSR_CSS (1 << 22) /* Clock Synchronisation Status */
-+#define SSSR_TUR (1 << 21) /* Transmit FIFO Under Run */
-+#define SSSR_EOC (1 << 20) /* End Of Chain */
-+#define SSSR_TINT (1 << 19) /* Receiver Time-out Interrupt */
-+#define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */
-+
-+#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */
-+#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */
-+#define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */
-+#define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */
-+#define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */
-+#define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */
-+#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */
-+#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */
-+#define SSPSP_SCMODE(x) ((x) << 0) /* Serial Bit Rate Clock Mode */
-+
-+/* spi_board_info.controller_data for SPI slave devices,
-+ * copied to spi_device.platform_data ... mostly for dma tuning
-+ */
-+struct mrst_spi_chip {
-+ u8 tx_threshold;
-+ u8 rx_threshold;
-+ u8 dma_burst_size;
-+ u32 timeout;
-+ u8 enable_loopback;
-+ u16 extra_data[5];
-+};
-+
-+
-+#define SPI_DIB_NAME_LEN 16
-+#define SPI_DIB_SPEC_INFO_LEN 10
-+
-+struct spi_dib_header {
-+ u32 signature;
-+ u32 length;
-+ u8 rev;
-+ u8 checksum;
-+ u8 dib[0];
-+} __attribute__((packed));
-+
-+struct spi_dib {
-+ u16 host_num;
-+ u16 cs;
-+ u16 irq;
-+ char name[SPI_DIB_NAME_LEN];
-+ u8 dev_data[SPI_DIB_SPEC_INFO_LEN];
-+} __attribute__((packed));
-+
-+#endif /*MRST_SSP_H_*/
-diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
-index 97b60b3..87b4d12 100644
---- a/include/linux/spi/spi.h
-+++ b/include/linux/spi/spi.h
-@@ -23,15 +23,19 @@
- #include <linux/mod_devicetable.h>
-
- /*
-- * INTERFACES between SPI master-side drivers and SPI infrastructure.
-- * (There's no SPI slave support for Linux yet...)
-+ * INTERFACES between SPI Master/Slave side drivers and
-+ * SPI infrastructure.
-+ * SPI Slave Support added : It uses few new APIs and
-+ * a new spi_slave struct
- */
- extern struct bus_type spi_bus_type;
-
- /**
- * struct spi_device - Master side proxy for an SPI slave device
- * @dev: Driver model representation of the device.
-- * @master: SPI controller used with the device.
-+ * @master: SPI Master controller used with the device.
-+ * @slave: SPI Slave Controller used with the device
-+ * @using_slave: SPI Slave Flag used by spi_async()
- * @max_speed_hz: Maximum clock rate to be used with this chip
- * (on this board); may be changed by the device's driver.
- * The spi_transfer.speed_hz can override this for each transfer.
-@@ -68,6 +72,8 @@ extern struct bus_type spi_bus_type;
- struct spi_device {
- struct device dev;
- struct spi_master *master;
-+ struct spi_slave *slave;
-+ u8 using_slave;
- u32 max_speed_hz;
- u8 chip_select;
- u8 mode;
-@@ -143,7 +149,6 @@ static inline void *spi_get_drvdata(struct spi_device *spi)
- struct spi_message;
-
-
--
- /**
- * struct spi_driver - Host side "protocol" driver
- * @id_table: List of SPI devices supported by this driver
-@@ -295,16 +300,56 @@ struct spi_master {
- void (*cleanup)(struct spi_device *spi);
- };
-
-+/**
-+ * struct spi_slave - interface to SPI Slave Controller
-+ * @dev: device interface to this driver
-+ * @bus_num: board-specific (and often SOC-specific) identifier for a
-+ * given SPI controller.
-+ * @num_chipselect: chipselects are used to distinguish individual
-+ * SPI slaves, and are numbered from zero to num_chipselects.
-+ * each slave has a chipselect signal, but it's common that not
-+ * every chipselect is connected to a slave.
-+ * @setup: updates the device mode and clocking records used by a
-+ * device's SPI controller; protocol code may call this. This
-+ * must fail if an unrecognized or unsupported mode is requested.
-+ * It's always safe to call this unless transfers are pending on
-+ * the device whose settings are being modified.
-+ * @transfer: adds a message to the controller's transfer queue.
-+ * @cleanup: frees controller-specific state
-+ */
-+struct spi_slave {
-+ struct device dev;
-+ s16 bus_num;
-+ u16 num_chipselect;
-+
-+ int (*setup)(struct spi_device *spi);
-+
-+ int (*transfer)(struct spi_device *spi,
-+ struct spi_message *mesg);
-+
-+ void (*cleanup)(struct spi_device *spi);
-+};
-+
- static inline void *spi_master_get_devdata(struct spi_master *master)
- {
- return dev_get_drvdata(&master->dev);
- }
-
-+static inline void *spi_slave_get_devdata(struct spi_slave *slave)
-+{
-+ return dev_get_drvdata(&slave->dev);
-+}
-+
- static inline void spi_master_set_devdata(struct spi_master *master, void *data)
- {
- dev_set_drvdata(&master->dev, data);
- }
-
-+static inline void spi_slave_set_devdata(struct spi_slave *slave, void *data)
-+{
-+ dev_set_drvdata(&slave->dev, data);
-+}
-+
- static inline struct spi_master *spi_master_get(struct spi_master *master)
- {
- if (!master || !get_device(&master->dev))
-@@ -312,20 +357,42 @@ static inline struct spi_master *spi_master_get(struct spi_master *master)
- return master;
- }
-
-+static inline struct spi_slave *spi_slave_get(struct spi_slave *slave)
-+{
-+ if (!slave || !get_device(&slave->dev))
-+ return NULL;
-+ return slave;
-+}
-+
- static inline void spi_master_put(struct spi_master *master)
- {
- if (master)
- put_device(&master->dev);
- }
-
-+static inline void spi_slave_put(struct spi_slave *slave)
-+{
-+ if (slave)
-+ put_device(&slave->dev);
-+}
-+
-
- /* the spi driver core manages memory for the spi_master classdev */
- extern struct spi_master *
- spi_alloc_master(struct device *host, unsigned size);
-
-+extern struct spi_slave *
-+spi_alloc_slave(struct device *host, unsigned size);
-+
-+
- extern int spi_register_master(struct spi_master *master);
-+
-+extern int spi_register_slave(struct spi_slave *slave);
-+
- extern void spi_unregister_master(struct spi_master *master);
-
-+extern void spi_unregister_slave(struct spi_slave *slave);
-+
- extern struct spi_master *spi_busnum_to_master(u16 busnum);
-
- /*---------------------------------------------------------------------------*/
-@@ -551,6 +618,18 @@ extern int spi_async(struct spi_device *spi, struct spi_message *message);
-
- extern int spi_sync(struct spi_device *spi, struct spi_message *message);
-
-+static inline int
-+spi_slave_setup(struct spi_device *spi)
-+{
-+ return spi->slave->setup(spi);
-+}
-+
-+
-+/* spi_transfer_async() exposes spi_async() functionality */
-+extern int spi_transfer_async(struct spi_device *spi,
-+ struct spi_message *message);
-+
-+
- /**
- * spi_write - SPI synchronous write
- * @spi: device to which data will be written
-@@ -759,12 +838,23 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
- extern struct spi_device *
- spi_alloc_device(struct spi_master *master);
-
-+extern struct spi_device *
-+spi_alloc_slave_device(struct spi_slave *slave);
-+
- extern int
- spi_add_device(struct spi_device *spi);
-
-+extern int
-+spi_add_slave_device(struct spi_device *spi);
-+
-+
- extern struct spi_device *
- spi_new_device(struct spi_master *, struct spi_board_info *);
-
-+extern struct spi_device *
-+spi_slave_new_device(struct spi_slave *, struct spi_board_info *);
-+
-+
- static inline void
- spi_unregister_device(struct spi_device *spi)
- {
---
-1.6.2.5
-