adjust for name conventions
authorcmc <cmc@rock-chips.com>
Tue, 30 Nov 2010 01:59:53 +0000 (09:59 +0800)
committercmc <cmc@rock-chips.com>
Tue, 30 Nov 2010 01:59:53 +0000 (09:59 +0800)
arch/arm/mach-rk29/board-rk29sdk.c
drivers/spi/Makefile
drivers/spi/rk29_spim.c [new file with mode: 0755]
drivers/spi/rk29_spim.h [new file with mode: 0755]
drivers/spi/rk29xx_spim.c [deleted file]
drivers/spi/rk29xx_spim.h [deleted file]

index ff3b11f039a5f226070be779c204f9904631a576..bbd5cc7aa8e348ed2b67ff95489da152c6a08a23 100755 (executable)
@@ -1091,7 +1091,7 @@ static struct spi_board_info board_spi_devices[] = {
        {\r
                .modalias       = "xpt2046_ts",\r
                .chip_select    = 0,\r
-               .max_speed_hz   = 125 * 1000 * 8,/* (max sample rate @ 3V) * (cmd + data + overhead) */\r
+               .max_speed_hz   = 125 * 1000 * 26,/* (max sample rate @ 3V) * (cmd + data + overhead) */\r
                .bus_num        = 0,\r
                .irq = XPT2046_GPIO_INT,\r
                .platform_data = &xpt2046_info,\r
index 8e200b197ea70da216a329266650374c04af6cc1..95d4d091e73c258930bd52686150311877859192 100755 (executable)
@@ -17,7 +17,7 @@ obj-$(CONFIG_SPI_BITBANG)             += spi_bitbang.o
 obj-$(CONFIG_SPI_AU1550)               += au1550_spi.o
 obj-$(CONFIG_SPI_BUTTERFLY)            += spi_butterfly.o
 obj-$(CONFIG_SPIM_RK2818)              += rk2818_spim.o
-obj-$(CONFIG_SPIM_RK29)                += rk29xx_spim.o
+obj-$(CONFIG_SPIM_RK29)                        += rk29_spim.o
 obj-$(CONFIG_SPI_GPIO)                 += spi_gpio.o
 obj-$(CONFIG_SPI_IMX)                  += spi_imx.o
 obj-$(CONFIG_SPI_LM70_LLP)             += spi_lm70llp.o
diff --git a/drivers/spi/rk29_spim.c b/drivers/spi/rk29_spim.c
new file mode 100755 (executable)
index 0000000..9d15abc
--- /dev/null
@@ -0,0 +1,1955 @@
+/*drivers/serial/rk29xx_spim.c - driver for rk29xx spim device \r
+ *\r
+ * Copyright (C) 2010 ROCKCHIP, Inc.\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ */\r
+\r
+#include <linux/dma-mapping.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/highmem.h>\r
+#include <linux/delay.h>\r
+#include <linux/slab.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/clk.h>\r
+#include <linux/cpufreq.h>\r
+#include <mach/gpio.h>\r
+#include <linux/dma-mapping.h>\r
+#include <asm/dma.h>\r
+\r
+#include "rk29xx_spim.h"\r
+#include <linux/spi/spi.h>\r
+#include <mach/board.h>\r
+\r
+#ifdef CONFIG_DEBUG_FS\r
+#include <linux/debugfs.h>\r
+#endif\r
+\r
+/*Ô­ÓеÄspiÇý¶¯Ð§ÂʱȽϵͣ¬\r
+ÎÞ·¨Âú×ã´óÊý¾ÝÁ¿µÄ´«Ê䣻\r
+QUICK_TRANSFERÓÃÓÚ¿ìËÙ´«Ê䣬ͬʱ¿ÉÖ¸¶¨°ëË«¹¤»òÈ«Ë«¹¤£¬\r
+ĬÈÏʹÓðëË«¹¤\r
+*/\r
+\r
+//#define QUICK_TRANSFER         \r
+\r
+#if 1\r
+#define DBG   printk\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define DMA_MIN_BYTES 8\r
+\r
+\r
+#define START_STATE    ((void *)0)\r
+#define RUNNING_STATE  ((void *)1)\r
+#define DONE_STATE     ((void *)2)\r
+#define ERROR_STATE    ((void *)-1)\r
+\r
+#define QUEUE_RUNNING  0\r
+#define QUEUE_STOPPED  1\r
+\r
+#define MRST_SPI_DEASSERT      0\r
+#define MRST_SPI_ASSERT                1  ///CS0\r
+#define MRST_SPI_ASSERT1       2  ///CS1\r
+\r
+/* Slave spi_dev related */\r
+struct chip_data {\r
+       u16 cr0;\r
+       u8 cs;                  /* chip select pin */\r
+       u8 n_bytes;             /* current is a 1/2/4 byte op */\r
+       u8 tmode;               /* TR/TO/RO/EEPROM */\r
+       u8 type;                /* SPI/SSP/MicroWire */\r
+\r
+       u8 poll_mode;           /* 1 means use poll mode */\r
+\r
+       u32 dma_width;\r
+       u32 rx_threshold;\r
+       u32 tx_threshold;\r
+       u8 enable_dma:1;\r
+       u8 bits_per_word;\r
+       u16 clk_div;            /* baud rate divider */\r
+       u32 speed_hz;           /* baud rate */\r
+       int (*write)(struct rk29xx_spi *dws);\r
+       int (*read)(struct rk29xx_spi *dws);\r
+       void (*cs_control)(struct rk29xx_spi *dws, u32 cs, u8 flag);\r
+};\r
+\r
+#define SUSPND    (1<<0)\r
+#define SPIBUSY   (1<<1)\r
+#define RXBUSY    (1<<2)\r
+#define TXBUSY    (1<<3)\r
+\r
+#ifdef CONFIG_DEBUG_FS\r
+static int spi_show_regs_open(struct inode *inode, struct file *file)\r
+{\r
+       file->private_data = inode->i_private;\r
+       return 0;\r
+}\r
+\r
+#define SPI_REGS_BUFSIZE       1024\r
+static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,\r
+                               size_t count, loff_t *ppos)\r
+{\r
+       struct rk29xx_spi *dws;\r
+       char *buf;\r
+       u32 len = 0;\r
+       ssize_t ret;\r
+\r
+       dws = file->private_data;\r
+\r
+       buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);\r
+       if (!buf)\r
+               return 0;\r
+\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "MRST SPI0 registers:\n");\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "=================================\n");\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "CTRL0: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_CTRLR0));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "CTRL1: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_CTRLR1));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "SSIENR: \t0x%08x\n", rk29xx_readl(dws, SPIM_ENR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "SER: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_SER));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "BAUDR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_BAUDR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "TXFTLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_TXFTLR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "RXFTLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_RXFTLR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "TXFLR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_TXFLR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "RXFLR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_RXFLR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "SR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_SR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "IMR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_IMR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "ISR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_ISR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "DMACR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_DMACR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "DMATDLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_DMATDLR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "DMARDLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_DMARDLR));\r
+       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
+                       "=================================\n");\r
+\r
+       ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);\r
+       kfree(buf);\r
+       return ret;\r
+}\r
+\r
+static const struct file_operations mrst_spi_regs_ops = {\r
+       .owner          = THIS_MODULE,\r
+       .open           = spi_show_regs_open,\r
+       .read           = spi_show_regs,\r
+};\r
+\r
+static int mrst_spi_debugfs_init(struct rk29xx_spi *dws)\r
+{\r
+       dws->debugfs = debugfs_create_dir("mrst_spi", NULL);\r
+       if (!dws->debugfs)\r
+               return -ENOMEM;\r
+\r
+       debugfs_create_file("registers", S_IFREG | S_IRUGO,\r
+               dws->debugfs, (void *)dws, &mrst_spi_regs_ops);\r
+       return 0;\r
+}\r
+\r
+static void mrst_spi_debugfs_remove(struct rk29xx_spi *dws)\r
+{\r
+       if (dws->debugfs)\r
+               debugfs_remove_recursive(dws->debugfs);\r
+}\r
+\r
+#else\r
+static inline int mrst_spi_debugfs_init(struct rk29xx_spi *dws)\r
+{\r
+       return 0;\r
+}\r
+\r
+static inline void mrst_spi_debugfs_remove(struct rk29xx_spi *dws)\r
+{\r
+}\r
+#endif /* CONFIG_DEBUG_FS */\r
+\r
+static void wait_till_not_busy(struct rk29xx_spi *dws)\r
+{\r
+       unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);\r
+\r
+       while (time_before(jiffies, end)) {\r
+               if (!(rk29xx_readw(dws, SPIM_SR) & SR_BUSY))\r
+                       return;\r
+       }\r
+       dev_err(&dws->master->dev,\r
+               "DW SPI: Status keeps busy for 1000us after a read/write!\n");\r
+}\r
+\r
+#if defined(QUICK_TRANSFER)\r
+static void wait_till_tf_empty(struct rk29xx_spi *dws)\r
+{\r
+       unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);\r
+\r
+       while (time_before(jiffies, end)) {\r
+               if (rk29xx_readw(dws, SPIM_SR) & SR_TF_EMPT)\r
+                       return;\r
+       }\r
+       dev_err(&dws->master->dev,\r
+               "DW SPI: Status keeps busy for 1000us after a read/write!\n");\r
+}\r
+#endif\r
+\r
+static void flush(struct rk29xx_spi *dws)\r
+{\r
+       while (!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT))\r
+               rk29xx_readw(dws, SPIM_RXDR);\r
+\r
+       wait_till_not_busy(dws);\r
+}\r
+\r
+#if 0\r
+static void spi_cs_control(struct rk29xx_spi *dws, u32 cs, u8 flag)\r
+{\r
+       struct rk29xx_spi_platform_data *pdata = dws->master->dev.platform_data;\r
+       struct spi_cs_gpio *cs_gpios = pdata->chipselect_gpios;\r
+\r
+       if (flag == 0)\r
+               gpio_direction_output(cs_gpios[cs].cs_gpio, GPIO_HIGH);\r
+       else\r
+               gpio_direction_output(cs_gpios[cs].cs_gpio, GPIO_LOW);\r
+}\r
+#endif\r
+\r
+static int null_writer(struct rk29xx_spi *dws)\r
+{\r
+       u8 n_bytes = dws->n_bytes;\r
+\r
+       if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
+               || (dws->tx == dws->tx_end))\r
+               return 0;\r
+       rk29xx_writew(dws, SPIM_TXDR, 0);\r
+       dws->tx += n_bytes;\r
+       //wait_till_not_busy(dws);\r
+\r
+       return 1;\r
+}\r
+\r
+static int null_reader(struct rk29xx_spi *dws)\r
+{\r
+       u8 n_bytes = dws->n_bytes;\r
+       while ((!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT))\r
+               && (dws->rx < dws->rx_end)) {\r
+               rk29xx_readw(dws, SPIM_RXDR);\r
+               dws->rx += n_bytes;\r
+       }\r
+       wait_till_not_busy(dws);\r
+       return dws->rx == dws->rx_end;\r
+}\r
+\r
+static int u8_writer(struct rk29xx_spi *dws)\r
+{      \r
+       if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
+               || (dws->tx == dws->tx_end))\r
+               return 0;\r
+       rk29xx_writew(dws, SPIM_TXDR, *(u8 *)(dws->tx));\r
+       ++dws->tx;\r
+       //wait_till_not_busy(dws);\r
+\r
+       return 1;\r
+}\r
+\r
+static int u8_reader(struct rk29xx_spi *dws)\r
+{\r
+       while (!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT)\r
+               && (dws->rx < dws->rx_end)) {\r
+               *(u8 *)(dws->rx) = rk29xx_readw(dws, SPIM_RXDR) & 0xFFU;\r
+               ++dws->rx;\r
+       }\r
+\r
+       wait_till_not_busy(dws);\r
+       return dws->rx == dws->rx_end;\r
+}\r
+\r
+static int u16_writer(struct rk29xx_spi *dws)\r
+{\r
+       if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
+               || (dws->tx == dws->tx_end))\r
+               return 0;\r
+\r
+       rk29xx_writew(dws, SPIM_TXDR, *(u16 *)(dws->tx));\r
+       dws->tx += 2;\r
+       //wait_till_not_busy(dws);\r
+\r
+       return 1;\r
+}\r
+\r
+static int u16_reader(struct rk29xx_spi *dws)\r
+{\r
+       u16 temp;\r
+\r
+       while (!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT)\r
+               && (dws->rx < dws->rx_end)) {\r
+               temp = rk29xx_readw(dws, SPIM_RXDR);\r
+               *(u16 *)(dws->rx) = temp;\r
+               dws->rx += 2;\r
+       }\r
+\r
+       wait_till_not_busy(dws);\r
+       return dws->rx == dws->rx_end;\r
+}\r
+\r
+static void *next_transfer(struct rk29xx_spi *dws)\r
+{\r
+       struct spi_message *msg = dws->cur_msg;\r
+       struct spi_transfer *trans = dws->cur_transfer;\r
+\r
+       /* Move to next transfer */\r
+       if (trans->transfer_list.next != &msg->transfers) {\r
+               dws->cur_transfer =\r
+                       list_entry(trans->transfer_list.next,\r
+                                       struct spi_transfer,\r
+                                       transfer_list);\r
+               return RUNNING_STATE;\r
+       } else\r
+               return DONE_STATE;\r
+}\r
+\r
+static void rk29_spi_dma_rxcb(void *buf_id,\r
+                                int size, enum rk29_dma_buffresult res)\r
+{\r
+       struct rk29xx_spi *dws = buf_id;\r
+       unsigned long flags;\r
+\r
+       spin_lock_irqsave(&dws->lock, flags);\r
+\r
+       if (res == RK29_RES_OK)\r
+               dws->state &= ~RXBUSY;\r
+       else\r
+               dev_err(&dws->master->dev, "DmaAbrtRx-%d, size: %d\n", res, size);\r
+\r
+       /* If the other done */\r
+       if (!(dws->state & TXBUSY))\r
+               complete(&dws->xfer_completion);\r
+\r
+       spin_unlock_irqrestore(&dws->lock, flags);\r
+}\r
+\r
+static void rk29_spi_dma_txcb(void *buf_id,\r
+                                int size, enum rk29_dma_buffresult res)\r
+{\r
+       struct rk29xx_spi *dws = buf_id;\r
+       unsigned long flags;\r
+\r
+       spin_lock_irqsave(&dws->lock, flags);\r
+\r
+       if (res == RK29_RES_OK)\r
+               dws->state &= ~TXBUSY;\r
+       else\r
+               dev_err(&dws->master->dev, "DmaAbrtTx-%d \n", size);\r
+\r
+       /* If the other done */\r
+       if (!(dws->state & RXBUSY)) \r
+               complete(&dws->xfer_completion);\r
+\r
+       spin_unlock_irqrestore(&dws->lock, flags);\r
+}\r
+\r
+\r
+static struct rk29_dma_client rk29_spi_dma_client = {\r
+       .name = "rk29xx-spi-dma",\r
+};\r
+\r
+static int acquire_dma(struct rk29xx_spi *dws)\r
+{      \r
+       if (dws->dma_inited) {\r
+               return 0;\r
+       }\r
+\r
+       if(rk29_dma_request(dws->rx_dmach, \r
+               &rk29_spi_dma_client, NULL) < 0) {\r
+               dev_err(&dws->master->dev, "dws->rx_dmach : %d, cannot get RxDMA\n", dws->rx_dmach);\r
+               return -1;\r
+       }\r
+\r
+       if (rk29_dma_request(dws->tx_dmach,\r
+                                       &rk29_spi_dma_client, NULL) < 0) {\r
+               dev_err(&dws->master->dev, "dws->tx_dmach : %d, cannot get TxDMA\n", dws->tx_dmach);\r
+               rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client);\r
+               return -1;\r
+       }\r
+       \r
+    dws->dma_inited = 1;\r
+       return 0;\r
+}\r
+\r
+static void release_dma(struct rk29xx_spi *dws)\r
+{\r
+       if(!dws && dws->dma_inited) {\r
+               rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client);\r
+               rk29_dma_free(dws->tx_dmach, &rk29_spi_dma_client);\r
+       }\r
+}\r
+\r
+/*\r
+ * Note: first step is the protocol driver prepares\r
+ * a dma-capable memory, and this func just need translate\r
+ * the virt addr to physical\r
+ */\r
+static int map_dma_buffers(struct rk29xx_spi *dws)\r
+{\r
+       if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited\r
+               || !dws->cur_chip->enable_dma)\r
+               return -1;\r
+\r
+       if (dws->cur_transfer->tx_dma) {\r
+               dws->tx_dma = dws->cur_transfer->tx_dma;\r
+               if (rk29_dma_set_buffdone_fn(dws->tx_dmach, rk29_spi_dma_txcb)) {\r
+                       dev_err(&dws->master->dev, "rk29_dma_set_buffdone_fn fail\n");\r
+                       return -1;\r
+               }\r
+               if (rk29_dma_devconfig(dws->tx_dmach, RK29_DMASRC_MEM,\r
+                                       (unsigned long)dws->sfr_start + SPIM_TXDR)) {\r
+                       dev_err(&dws->master->dev, "rk29_dma_devconfig fail\n");\r
+                       return -1;\r
+               }\r
+       }\r
+\r
+       if (dws->cur_transfer->rx_dma) {\r
+               dws->rx_dma = dws->cur_transfer->rx_dma;\r
+               if (rk29_dma_set_buffdone_fn(dws->rx_dmach, rk29_spi_dma_rxcb)) {\r
+                       dev_err(&dws->master->dev, "rk29_dma_set_buffdone_fn fail\n");\r
+                       return -1;\r
+               }\r
+               if (rk29_dma_devconfig(dws->rx_dmach, RK29_DMASRC_HW,\r
+                                       (unsigned long)dws->sfr_start + SPIM_RXDR)) {\r
+                       dev_err(&dws->master->dev, "rk29_dma_devconfig fail\n");\r
+                       return -1;\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/* Caller already set message->status; dma and pio irqs are blocked */\r
+static void giveback(struct rk29xx_spi *dws)\r
+{\r
+       struct spi_transfer *last_transfer;\r
+       unsigned long flags;\r
+       struct spi_message *msg;\r
+\r
+       spin_lock_irqsave(&dws->lock, flags);\r
+       msg = dws->cur_msg;\r
+       dws->cur_msg = NULL;\r
+       dws->cur_transfer = NULL;\r
+       dws->prev_chip = dws->cur_chip;\r
+       dws->cur_chip = NULL;\r
+       dws->dma_mapped = 0;\r
+       queue_work(dws->workqueue, &dws->pump_messages);\r
+       spin_unlock_irqrestore(&dws->lock, flags);\r
+\r
+       last_transfer = list_entry(msg->transfers.prev,\r
+                                       struct spi_transfer,\r
+                                       transfer_list);\r
+\r
+       if (!last_transfer->cs_change)\r
+               dws->cs_control(dws,msg->spi->chip_select, MRST_SPI_DEASSERT);\r
+\r
+       msg->state = NULL;\r
+       if (msg->complete)\r
+               msg->complete(msg->context);\r
+}\r
+\r
+static void int_error_stop(struct rk29xx_spi *dws, const char *msg)\r
+{\r
+       /* Stop and reset hw */\r
+       flush(dws);\r
+       spi_enable_chip(dws, 0);\r
+\r
+       dev_err(&dws->master->dev, "%s\n", msg);\r
+       dws->cur_msg->state = ERROR_STATE;\r
+       tasklet_schedule(&dws->pump_transfers);\r
+}\r
+\r
+static void transfer_complete(struct rk29xx_spi *dws)\r
+{\r
+       /* Update total byte transfered return count actual bytes read */\r
+       dws->cur_msg->actual_length += dws->len;\r
+\r
+       /* Move to next transfer */\r
+       dws->cur_msg->state = next_transfer(dws);\r
+\r
+       /* Handle end of message */\r
+       if (dws->cur_msg->state == DONE_STATE) {\r
+               dws->cur_msg->status = 0;\r
+               giveback(dws);\r
+       } else\r
+               tasklet_schedule(&dws->pump_transfers);\r
+}\r
+\r
+static irqreturn_t interrupt_transfer(struct rk29xx_spi *dws)\r
+{\r
+       u16 irq_status, irq_mask = 0x3f;\r
+       u32 int_level = dws->fifo_len / 2;\r
+       u32 left;\r
+       \r
+       irq_status = rk29xx_readw(dws, SPIM_ISR) & irq_mask;\r
+       /* Error handling */\r
+       if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {\r
+               rk29xx_writew(dws, SPIM_ICR, SPI_CLEAR_INT_TXOI | SPI_CLEAR_INT_RXOI | SPI_CLEAR_INT_RXUI);\r
+               int_error_stop(dws, "interrupt_transfer: fifo overrun");\r
+               return IRQ_HANDLED;\r
+       }\r
+\r
+       if (irq_status & SPI_INT_TXEI) {\r
+               spi_mask_intr(dws, SPI_INT_TXEI);\r
+\r
+               left = (dws->tx_end - dws->tx) / dws->n_bytes;\r
+               left = (left > int_level) ? int_level : left;\r
+\r
+               while (left--) {\r
+                       dws->write(dws);\r
+                       wait_till_not_busy(dws);\r
+               }\r
+               dws->read(dws);\r
+\r
+               /* Re-enable the IRQ if there is still data left to tx */\r
+               if (dws->tx_end > dws->tx)\r
+                       spi_umask_intr(dws, SPI_INT_TXEI);\r
+               else\r
+                       transfer_complete(dws);\r
+       }\r
+\r
+       return IRQ_HANDLED;\r
+}\r
+\r
+static irqreturn_t rk29xx_spi_irq(int irq, void *dev_id)\r
+{\r
+       struct rk29xx_spi *dws = dev_id;\r
+\r
+       if (!dws->cur_msg) {\r
+               spi_mask_intr(dws, SPI_INT_TXEI);\r
+               /* Never fail */\r
+               return IRQ_HANDLED;\r
+       }\r
+\r
+       return dws->transfer_handler(dws);\r
+}\r
+\r
+/* Must be called inside pump_transfers() */\r
+static void poll_transfer(struct rk29xx_spi *dws)\r
+{\r
+       while (dws->write(dws)) {\r
+               wait_till_not_busy(dws);\r
+               dws->read(dws);\r
+       }\r
+       transfer_complete(dws);\r
+}\r
+static void spi_chip_sel(struct rk29xx_spi *dws, u16 cs)\r
+{\r
+    if(cs >= dws->master->num_chipselect)\r
+               return;\r
+\r
+       if (dws->cs_control){\r
+           dws->cs_control(dws, cs, 1);\r
+       }\r
+       rk29xx_writel(dws, SPIM_SER, 1 << cs);\r
+}\r
+\r
+static void pump_transfers(unsigned long data)\r
+{\r
+       struct rk29xx_spi *dws = (struct rk29xx_spi *)data;\r
+       struct spi_message *message = NULL;\r
+       struct spi_transfer *transfer = NULL;\r
+       struct spi_transfer *previous = NULL;\r
+       struct spi_device *spi = NULL;\r
+       struct chip_data *chip = NULL;\r
+       u8 bits = 0;\r
+       u8 spi_dfs = 0;\r
+       u8 imask = 0;\r
+       u8 cs_change = 0;\r
+       u16 txint_level = 0;\r
+       u16 clk_div = 0;\r
+       u32 speed = 0;\r
+       u32 cr0 = 0;\r
+\r
+       DBG(KERN_INFO "pump_transfers");\r
+\r
+       /* Get current state information */\r
+       message = dws->cur_msg;\r
+       transfer = dws->cur_transfer;\r
+       chip = dws->cur_chip;\r
+       spi = message->spi;     \r
+       if (unlikely(!chip->clk_div))\r
+               //chip->clk_div = clk_get_rate(dws->clock_spim) / chip->speed_hz;       \r
+           chip->clk_div = 40000000 / chip->speed_hz;  \r
+       if (message->state == ERROR_STATE) {\r
+               message->status = -EIO;\r
+               goto early_exit;\r
+       }\r
+\r
+       /* Handle end of message */\r
+       if (message->state == DONE_STATE) {\r
+               message->status = 0;\r
+               goto early_exit;\r
+       }\r
+\r
+       /* Delay if requested at end of transfer*/\r
+       if (message->state == RUNNING_STATE) {\r
+               previous = list_entry(transfer->transfer_list.prev,\r
+                                       struct spi_transfer,\r
+                                       transfer_list);\r
+               if (previous->delay_usecs)\r
+                       udelay(previous->delay_usecs);\r
+       }\r
+\r
+       dws->n_bytes = chip->n_bytes;\r
+       dws->dma_width = chip->dma_width;\r
+       dws->cs_control = chip->cs_control;\r
+\r
+       dws->rx_dma = transfer->rx_dma;\r
+       dws->tx_dma = transfer->tx_dma;\r
+       dws->tx = (void *)transfer->tx_buf;\r
+       dws->tx_end = dws->tx + transfer->len;\r
+       dws->rx = transfer->rx_buf;\r
+       dws->rx_end = dws->rx + transfer->len;\r
+       dws->write = dws->tx ? chip->write : null_writer;\r
+       dws->read = dws->rx ? chip->read : null_reader;\r
+       dws->cs_change = transfer->cs_change;\r
+       dws->len = dws->cur_transfer->len;\r
+       if (chip != dws->prev_chip)\r
+               cs_change = 1;\r
+\r
+       cr0 = chip->cr0;\r
+\r
+       /* Handle per transfer options for bpw and speed */\r
+       if (transfer->speed_hz) {\r
+               speed = chip->speed_hz;\r
+\r
+               if (transfer->speed_hz != speed) {\r
+                       speed = transfer->speed_hz;\r
+                       if (speed > clk_get_rate(dws->clock_spim)) {\r
+                               dev_err(&dws->master->dev, "MRST SPI0: unsupported"\r
+                                       "freq: %dHz\n", speed);\r
+                               message->status = -EIO;\r
+                               goto early_exit;\r
+                       }\r
+\r
+                       /* clk_div doesn't support odd number */\r
+                       clk_div = clk_get_rate(dws->clock_spim) / speed;\r
+                       clk_div = (clk_div + 1) & 0xfffe;\r
+\r
+                       chip->speed_hz = speed;\r
+                       chip->clk_div = clk_div;\r
+               }\r
+       }\r
+       \r
+       if (transfer->bits_per_word) {\r
+               bits = transfer->bits_per_word;\r
+\r
+               switch (bits) {\r
+               case 8:\r
+                       dws->n_bytes = 1;\r
+                       dws->dma_width = 1;\r
+                       dws->read = (dws->read != null_reader) ?\r
+                                       u8_reader : null_reader;\r
+                       dws->write = (dws->write != null_writer) ?\r
+                                       u8_writer : null_writer;\r
+                       spi_dfs = SPI_DFS_8BIT;\r
+                       break;\r
+               case 16:\r
+                       dws->n_bytes = 2;\r
+                       dws->dma_width = 2;\r
+                       dws->read = (dws->read != null_reader) ?\r
+                                       u16_reader : null_reader;\r
+                       dws->write = (dws->write != null_writer) ?\r
+                                       u16_writer : null_writer;\r
+                       spi_dfs = SPI_DFS_16BIT;\r
+                       break;\r
+               default:\r
+                       dev_err(&dws->master->dev, "MRST SPI0: unsupported bits:"\r
+                               "%db\n", bits);\r
+                       message->status = -EIO;\r
+                       goto early_exit;\r
+               }\r
+\r
+               cr0 = (spi_dfs << SPI_DFS_OFFSET)\r
+                       | (SPI_HALF_WORLD_OFF << SPI_HALF_WORLD_TX_OFFSET)\r
+                       | (SPI_SSN_DELAY_ONE << SPI_SSN_DELAY_OFFSET)\r
+                       | (chip->type << SPI_FRF_OFFSET)\r
+                       | (spi->mode << SPI_MODE_OFFSET)\r
+                       | (chip->tmode << SPI_TMOD_OFFSET);\r
+       }\r
+       message->state = RUNNING_STATE;\r
\r
+       /*\r
+        * Adjust transfer mode if necessary. Requires platform dependent\r
+        * chipselect mechanism.\r
+        */\r
+       if (dws->cs_control) {\r
+               if (dws->rx && dws->tx)\r
+                       chip->tmode = SPI_TMOD_TR;\r
+               else if (dws->rx)\r
+                       chip->tmode = SPI_TMOD_RO;\r
+               else\r
+                       chip->tmode = SPI_TMOD_TO;\r
+\r
+               cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
+               cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
+       } \r
+\r
+       /*\r
+        * Interrupt mode\r
+        * we only need set the TXEI IRQ, as TX/RX always happen syncronizely\r
+        */\r
+       if (!dws->dma_mapped && !chip->poll_mode) {\r
+               int templen = dws->len / dws->n_bytes;\r
+               txint_level = dws->fifo_len / 2;\r
+               txint_level = (templen > txint_level) ? txint_level : templen;\r
+\r
+               imask |= SPI_INT_TXEI;\r
+               dws->transfer_handler = interrupt_transfer;\r
+       }\r
+\r
+       /*\r
+        * Reprogram registers only if\r
+        *      1. chip select changes\r
+        *      2. clk_div is changed\r
+        *      3. control value changes\r
+        */\r
+       if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0 || cs_change || clk_div || imask) {\r
+               spi_enable_chip(dws, 0);\r
+               if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0)\r
+                       rk29xx_writew(dws, SPIM_CTRLR0, cr0);\r
+\r
+               spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);            \r
+               spi_chip_sel(dws, spi->chip_select);\r
+               /* Set the interrupt mask, for poll mode just diable all int */\r
+               spi_mask_intr(dws, 0xff);\r
+               if (imask)\r
+                       spi_umask_intr(dws, imask);\r
+               if (txint_level)\r
+                       rk29xx_writew(dws, SPIM_TXFTLR, txint_level);\r
+\r
+        rk29xx_writew(dws, SPIM_CTRLR1, dws->len-1);\r
+               spi_enable_chip(dws, 1);\r
+               if (cs_change)\r
+                       dws->prev_chip = chip;\r
+       } \r
+\r
+       if (chip->poll_mode)\r
+               poll_transfer(dws);\r
+\r
+       return;\r
+\r
+early_exit:\r
+       giveback(dws);\r
+       return;\r
+}\r
+\r
+static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)\r
+{\r
+       struct spi_message *message = NULL;\r
+       struct spi_transfer *transfer = NULL;\r
+       struct spi_transfer *previous = NULL;\r
+       struct spi_device *spi = NULL;\r
+       struct chip_data *chip = NULL;\r
+       unsigned long val;\r
+       int ms;\r
+       int iRet;\r
+       u8 bits = 0;\r
+       u8 spi_dfs = 0;\r
+       u8 cs_change = 0;\r
+       u16 clk_div = 0;\r
+       u32 speed = 0;\r
+       u32 cr0 = 0;\r
+       u32 dmacr = 0;\r
+\r
+       DBG(KERN_INFO "dma_transfer\n");\r
+\r
+       if (acquire_dma(dws)) {\r
+               dev_err(&dws->master->dev, "acquire dma failed\n");\r
+               goto err_out;\r
+       }\r
+\r
+       if (map_dma_buffers(dws)) {\r
+               dev_err(&dws->master->dev, "acquire dma failed\n");\r
+               goto err_out;\r
+       }\r
+\r
+       /* Get current state information */\r
+       message = dws->cur_msg;\r
+       transfer = dws->cur_transfer;\r
+       chip = dws->cur_chip;\r
+       spi = message->spi;     \r
+       if (unlikely(!chip->clk_div))\r
+               chip->clk_div = 40000000 / chip->speed_hz;      \r
+       if (message->state == ERROR_STATE) {\r
+               message->status = -EIO;\r
+               goto err_out;\r
+       }\r
+\r
+       /* Handle end of message */\r
+       if (message->state == DONE_STATE) {\r
+               message->status = 0;\r
+               goto err_out;\r
+       }\r
+\r
+       /* Delay if requested at end of transfer*/\r
+       if (message->state == RUNNING_STATE) {\r
+               previous = list_entry(transfer->transfer_list.prev,\r
+                                       struct spi_transfer,\r
+                                       transfer_list);\r
+               if (previous->delay_usecs)\r
+                       udelay(previous->delay_usecs);\r
+       }\r
+\r
+       dws->n_bytes = chip->n_bytes;\r
+       dws->dma_width = chip->dma_width;\r
+       dws->cs_control = chip->cs_control;\r
+\r
+       dws->rx_dma = transfer->rx_dma;\r
+       dws->tx_dma = transfer->tx_dma;\r
+       dws->tx = (void *)transfer->tx_buf;\r
+       dws->tx_end = dws->tx + transfer->len;\r
+       dws->rx = transfer->rx_buf;\r
+       dws->rx_end = dws->rx + transfer->len;\r
+       dws->write = dws->tx ? chip->write : null_writer;\r
+       dws->read = dws->rx ? chip->read : null_reader;\r
+       dws->cs_change = transfer->cs_change;\r
+       dws->len = dws->cur_transfer->len;\r
+       if (chip != dws->prev_chip)\r
+               cs_change = 1;\r
+\r
+       cr0 = chip->cr0;\r
+\r
+       /* Handle per transfer options for bpw and speed */\r
+       if (transfer->speed_hz) {\r
+               speed = chip->speed_hz;\r
+\r
+               if (transfer->speed_hz != speed) {\r
+                       speed = transfer->speed_hz;\r
+                       if (speed > clk_get_rate(dws->clock_spim)) {\r
+                               dev_err(&dws->master->dev, "MRST SPI0: unsupported"\r
+                                       "freq: %dHz\n", speed);\r
+                               message->status = -EIO;\r
+                               goto err_out;\r
+                       }\r
+\r
+                       /* clk_div doesn't support odd number */\r
+                       clk_div = clk_get_rate(dws->clock_spim) / speed;\r
+                       clk_div = (clk_div + 1) & 0xfffe;\r
+\r
+                       chip->speed_hz = speed;\r
+                       chip->clk_div = clk_div;\r
+               }\r
+       }\r
+\r
+       if (transfer->bits_per_word) {\r
+               bits = transfer->bits_per_word;\r
+\r
+               switch (bits) {\r
+               case 8:\r
+                       dws->n_bytes = 1;\r
+                       dws->dma_width = 1;\r
+                       spi_dfs = SPI_DFS_8BIT;\r
+                       break;\r
+               case 16:\r
+                       dws->n_bytes = 2;\r
+                       dws->dma_width = 2;\r
+                       spi_dfs = SPI_DFS_16BIT;\r
+                       break;\r
+               default:\r
+                       dev_err(&dws->master->dev, "MRST SPI0: unsupported bits:"\r
+                               "%db\n", bits);\r
+                       message->status = -EIO;\r
+                       goto err_out;\r
+               }\r
+\r
+               cr0 = (spi_dfs << SPI_DFS_OFFSET)\r
+                       | (SPI_HALF_WORLD_OFF << SPI_HALF_WORLD_TX_OFFSET)\r
+                       | (SPI_SSN_DELAY_ONE << SPI_SSN_DELAY_OFFSET)\r
+                       | (chip->type << SPI_FRF_OFFSET)\r
+                       | (spi->mode << SPI_MODE_OFFSET)\r
+                       | (chip->tmode << SPI_TMOD_OFFSET);\r
+       }\r
+       message->state = RUNNING_STATE;\r
\r
+       /*\r
+        * Adjust transfer mode if necessary. Requires platform dependent\r
+        * chipselect mechanism.\r
+        */\r
+       if (dws->cs_control) {\r
+               if (dws->rx && dws->tx)\r
+                       chip->tmode = SPI_TMOD_TR;\r
+               else if (dws->rx)\r
+                       chip->tmode = SPI_TMOD_RO;\r
+               else\r
+                       chip->tmode = SPI_TMOD_TO;\r
+\r
+               cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
+               cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
+       }\r
+\r
+       /*\r
+        * Reprogram registers only if\r
+        *      1. chip select changes\r
+        *      2. clk_div is changed\r
+        *      3. control value changes\r
+        */\r
+       if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0 || cs_change || clk_div) {\r
+               spi_enable_chip(dws, 0);\r
+               if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0) {\r
+                       rk29xx_writew(dws, SPIM_CTRLR0, cr0);\r
+               }\r
+\r
+               spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);            \r
+               spi_chip_sel(dws, spi->chip_select);\r
+               /* Set the interrupt mask, for poll mode just diable all int */\r
+               spi_mask_intr(dws, 0xff);\r
+               \r
+               if (transfer->tx_buf != NULL) {\r
+                       dmacr |= SPI_DMACR_TX_ENABLE;\r
+                       rk29xx_writew(dws, SPIM_DMATDLR, 0);\r
+               }\r
+               if (transfer->rx_buf != NULL) {\r
+                       dmacr |= SPI_DMACR_RX_ENABLE;\r
+                       rk29xx_writew(dws, SPIM_DMARDLR, 0);\r
+                       rk29xx_writew(dws, SPIM_CTRLR1, transfer->len-1);\r
+               }\r
+               rk29xx_writew(dws, SPIM_DMACR, dmacr);\r
+               spi_enable_chip(dws, 1);\r
+               if (cs_change)\r
+                       dws->prev_chip = chip;\r
+       } \r
+\r
+       INIT_COMPLETION(dws->xfer_completion);\r
+       \r
+       if (transfer->tx_buf != NULL) {\r
+               dws->state |= TXBUSY;\r
+               if (rk29_dma_config(dws->tx_dmach, 1)) {\r
+                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
+                       goto err_out;\r
+               }\r
+               \r
+               iRet = rk29_dma_enqueue(dws->tx_dmach, (void *)dws,\r
+                                       transfer->tx_dma, transfer->len);\r
+               if (iRet) {\r
+                       dev_err(&dws->master->dev, "function: %s, line: %d, iRet: %d(dws->tx_dmach: %d, transfer->tx_dma: 0x%x)\n", __FUNCTION__, __LINE__, iRet, \r
+                               dws->tx_dmach, (unsigned int)transfer->tx_dma);\r
+                       goto err_out;\r
+               }\r
+               \r
+               if (rk29_dma_ctrl(dws->tx_dmach, RK29_DMAOP_START)) {\r
+                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
+                       goto err_out;\r
+               }\r
+       }\r
+\r
+       if (transfer->rx_buf != NULL) {\r
+               dws->state |= RXBUSY;\r
+               if (rk29_dma_config(dws->rx_dmach, 1)) {\r
+                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
+                       goto err_out;\r
+               }\r
+               \r
+               iRet = rk29_dma_enqueue(dws->rx_dmach, (void *)dws,\r
+                                       transfer->rx_dma, transfer->len);\r
+               if (iRet) {\r
+                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
+                       goto err_out;\r
+               }\r
+               \r
+               if (rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_START)) {\r
+                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
+                       goto err_out;\r
+               }\r
+       }\r
+\r
+       /* millisecs to xfer 'len' bytes @ 'cur_speed' */\r
+       ms = transfer->len * 8 * 1000 / dws->cur_chip->speed_hz;\r
+       ms += 10; \r
+\r
+       val = msecs_to_jiffies(ms) + 500;\r
+       if (!wait_for_completion_timeout(&dws->xfer_completion, val)) {\r
+               if (transfer->rx_buf != NULL && (dws->state & RXBUSY)) {\r
+                       rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_FLUSH);\r
+                       dws->state &= ~RXBUSY;\r
+                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
+                       goto NEXT_TRANSFER;\r
+               }\r
+               if (transfer->tx_buf != NULL && (dws->state & TXBUSY)) {\r
+                       rk29_dma_ctrl(dws->tx_dmach, RK29_DMAOP_FLUSH);\r
+                       dws->state &= ~TXBUSY;\r
+                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
+                       goto NEXT_TRANSFER;\r
+               }\r
+       }\r
+\r
+       wait_till_not_busy(dws);\r
+\r
+NEXT_TRANSFER:\r
+       /* Update total byte transfered return count actual bytes read */\r
+       dws->cur_msg->actual_length += dws->len;\r
+\r
+       /* Move to next transfer */\r
+       dws->cur_msg->state = next_transfer(dws);\r
+\r
+       /* Handle end of message */\r
+       if (dws->cur_msg->state == DONE_STATE) {\r
+               dws->cur_msg->status = 0;\r
+               giveback(dws);\r
+       } else\r
+               dma_transfer(dws);\r
+       \r
+       return;\r
+\r
+err_out:\r
+       giveback(dws);\r
+       return;\r
+\r
+}\r
+\r
+static void pump_messages(struct work_struct *work)\r
+{\r
+       struct rk29xx_spi *dws =\r
+               container_of(work, struct rk29xx_spi, pump_messages);\r
+       unsigned long flags;\r
+\r
+       DBG(KERN_INFO "pump_messages\n");\r
+\r
+       /* Lock queue and check for queue work */\r
+       spin_lock_irqsave(&dws->lock, flags);\r
+       if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {\r
+               dws->busy = 0;\r
+               spin_unlock_irqrestore(&dws->lock, flags);\r
+               return;\r
+       }\r
+\r
+       /* Make sure we are not already running a message */\r
+       if (dws->cur_msg) {\r
+               spin_unlock_irqrestore(&dws->lock, flags);\r
+               return;\r
+       }\r
+\r
+       /* Extract head of queue */\r
+       dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);\r
+       list_del_init(&dws->cur_msg->queue);\r
+\r
+       /* Initial message state*/\r
+       dws->cur_msg->state = START_STATE;\r
+       dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,\r
+                                               struct spi_transfer,\r
+                                               transfer_list);\r
+       dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);\r
+    dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj\r
+    \r
+       /* Mark as busy and launch transfers */\r
+       if(dws->cur_msg->is_dma_mapped && dws->cur_transfer->len > DMA_MIN_BYTES) {\r
+               dws->busy = 1;\r
+           spin_unlock_irqrestore(&dws->lock, flags);\r
+               dma_transfer(dws);\r
+               return;\r
+       }\r
+       else {\r
+               tasklet_schedule(&dws->pump_transfers);\r
+       }\r
+\r
+       dws->busy = 1;\r
+       spin_unlock_irqrestore(&dws->lock, flags);\r
+}\r
+\r
+#if defined(QUICK_TRANSFER)\r
+static void do_read(struct rk29xx_spi *dws)\r
+{\r
+       int count = 0;\r
+\r
+       spi_enable_chip(dws, 0);\r
+       rk29xx_writew(dws, SPIM_CTRLR1, dws->rx_end-dws->rx-1);\r
+       spi_enable_chip(dws, 1);                \r
+       rk29xx_writew(dws, SPIM_TXDR, 0);\r
+       while (1) {\r
+               if (dws->read(dws))\r
+                       break;\r
+               if (count++ == 0x20) {\r
+                       dev_err(&dws->master->dev, "+++++++++++spi receive data time out+++++++++++++\n");\r
+                       break;\r
+               }\r
+               \r
+       }\r
+}\r
+\r
+static void do_write(struct rk29xx_spi *dws)\r
+{\r
+       while (dws->tx<dws->tx_end) {\r
+               dws->write(dws);\r
+       }\r
+}\r
+\r
+/* Caller already set message->status; dma and pio irqs are blocked */\r
+static void msg_giveback(struct rk29xx_spi *dws)\r
+{\r
+       struct spi_transfer *last_transfer;\r
+       struct spi_message *msg;\r
+\r
+       DBG("+++++++++++++++enter %s++++++++++++++++++\n", __func__);\r
+\r
+       msg = dws->cur_msg;\r
+       dws->cur_msg = NULL;\r
+       dws->cur_transfer = NULL;\r
+       dws->prev_chip = dws->cur_chip;\r
+       dws->cur_chip = NULL;\r
+       dws->dma_mapped = 0;\r
+       dws->busy = 0;\r
+\r
+       last_transfer = list_entry(msg->transfers.prev,\r
+                                       struct spi_transfer,\r
+                                       transfer_list);\r
+\r
+       if (!last_transfer->cs_change)\r
+               dws->cs_control(dws,msg->spi->chip_select,MRST_SPI_DEASSERT);\r
+\r
+       msg->state = NULL;      \r
+}\r
+\r
+/* Must be called inside pump_transfers() */\r
+static int do_full_transfer(struct rk29xx_spi *dws)\r
+{\r
+       if ((dws->read(dws))) {\r
+               goto comple;\r
+       }\r
+       \r
+       while (dws->tx<dws->tx_end){\r
+               dws->write(dws);                \r
+               dws->read(dws);\r
+       }\r
+       \r
+       if (dws->rx < dws->rx_end) {\r
+               dws->read(dws);\r
+       }\r
+\r
+comple:\r
+       \r
+       dws->cur_msg->actual_length += dws->len;\r
+       \r
+       /* Move to next transfer */\r
+       dws->cur_msg->state = next_transfer(dws);\r
+                                       \r
+       if (dws->cur_msg->state == DONE_STATE) {\r
+               dws->cur_msg->status = 0;\r
+               //msg_giveback(dws);\r
+               return 0;\r
+       }\r
+       else {\r
+               return -1;\r
+       }\r
+       \r
+}\r
+\r
+\r
+/* Must be called inside pump_transfers() */\r
+static int do_half_transfer(struct rk29xx_spi *dws)\r
+{\r
+       if (dws->rx) {\r
+               if (dws->tx) {\r
+                       do_write(dws);\r
+               }\r
+               wait_till_tf_empty(dws);\r
+               wait_till_not_busy(dws);\r
+               do_read(dws);\r
+       }\r
+       else {\r
+               do_write(dws);\r
+               wait_till_tf_empty(dws);\r
+               wait_till_not_busy(dws);\r
+       }\r
+       \r
+       dws->cur_msg->actual_length += dws->len;\r
+       \r
+       /* Move to next transfer */\r
+       dws->cur_msg->state = next_transfer(dws);\r
+                                       \r
+       if (dws->cur_msg->state == DONE_STATE) {\r
+               dws->cur_msg->status = 0;\r
+               //msg_giveback(dws);\r
+               return 0;\r
+       }\r
+       else {\r
+               return -1;\r
+       }\r
+}\r
+\r
+\r
+static int rk29xx_pump_transfers(struct rk29xx_spi *dws, int mode)\r
+{\r
+       struct spi_message *message = NULL;\r
+       struct spi_transfer *transfer = NULL;\r
+       struct spi_transfer *previous = NULL;\r
+       struct spi_device *spi = NULL;\r
+       struct chip_data *chip = NULL;\r
+       u8 bits = 0;\r
+       u8 spi_dfs = 0;\r
+       u8 cs_change = 0;\r
+       u16 clk_div = 0;\r
+       u32 speed = 0;\r
+       u32 cr0 = 0;\r
+       u32 dmacr = 0;\r
+       \r
+       DBG(KERN_INFO "+++++++++++++++enter %s++++++++++++++++++\n", __func__);\r
+\r
+       /* Get current state information */\r
+       message = dws->cur_msg;\r
+       transfer = dws->cur_transfer;\r
+       chip = dws->cur_chip;\r
+       spi = message->spi;     \r
+\r
+       if (unlikely(!chip->clk_div))\r
+               chip->clk_div = clk_get_rate(dws->clock_spim) / chip->speed_hz;\r
+       if (message->state == ERROR_STATE) {\r
+               message->status = -EIO;\r
+               goto early_exit;\r
+       }\r
+\r
+       /* Handle end of message */\r
+       if (message->state == DONE_STATE) {\r
+               message->status = 0;\r
+               goto early_exit;\r
+       }\r
+\r
+       /* Delay if requested at end of transfer*/\r
+       if (message->state == RUNNING_STATE) {\r
+               previous = list_entry(transfer->transfer_list.prev,\r
+                                       struct spi_transfer,\r
+                                       transfer_list);\r
+               if (previous->delay_usecs)\r
+                       udelay(previous->delay_usecs);\r
+       }\r
+\r
+       dws->n_bytes = chip->n_bytes;\r
+       dws->dma_width = chip->dma_width;\r
+       dws->cs_control = chip->cs_control;\r
+\r
+       dws->rx_dma = transfer->rx_dma;\r
+       dws->tx_dma = transfer->tx_dma;\r
+       dws->tx = (void *)transfer->tx_buf;\r
+       dws->tx_end = dws->tx + transfer->len;\r
+       dws->rx = transfer->rx_buf;\r
+       dws->rx_end = dws->rx + transfer->len;\r
+       dws->write = dws->tx ? chip->write : null_writer;\r
+       dws->read = dws->rx ? chip->read : null_reader;\r
+       if (dws->rx && dws->tx) {\r
+               int temp_len = transfer->len;\r
+               int len;\r
+               unsigned char *tx_buf;\r
+               for (len=0; *tx_buf++ != 0; len++);\r
+               dws->tx_end = dws->tx + len;\r
+               dws->rx_end = dws->rx + temp_len - len;\r
+       }\r
+       dws->cs_change = transfer->cs_change;\r
+       dws->len = dws->cur_transfer->len;\r
+       if (chip != dws->prev_chip)\r
+               cs_change = 1;\r
+\r
+       cr0 = chip->cr0;\r
+\r
+       /* Handle per transfer options for bpw and speed */\r
+       if (transfer->speed_hz) {\r
+               speed = chip->speed_hz;\r
+\r
+               if (transfer->speed_hz != speed) {\r
+                       speed = transfer->speed_hz;\r
+                       if (speed > clk_get_rate(dws->clock_spim)) {\r
+                               dev_err(&dws->master->dev, "MRST SPI0: unsupported"\r
+                                       "freq: %dHz\n", speed);\r
+                               message->status = -EIO;\r
+                               goto early_exit;\r
+                       }\r
+\r
+                       /* clk_div doesn't support odd number */\r
+                       clk_div = clk_get_rate(dws->clock_spim) / speed;\r
+                       clk_div = (clk_div + 1) & 0xfffe;\r
+\r
+                       chip->speed_hz = speed;\r
+                       chip->clk_div = clk_div;\r
+               }\r
+       }\r
+       if (transfer->bits_per_word) {\r
+               bits = transfer->bits_per_word;\r
+\r
+               switch (bits) {\r
+               case 8:\r
+                       dws->n_bytes = 1;\r
+                       dws->dma_width = 1;\r
+                       dws->read = (dws->read != null_reader) ?\r
+                                       u8_reader : null_reader;\r
+                       dws->write = (dws->write != null_writer) ?\r
+                                       u8_writer : null_writer;\r
+                       spi_dfs = SPI_DFS_8BIT;\r
+                       break;\r
+               case 16:\r
+                       dws->n_bytes = 2;\r
+                       dws->dma_width = 2;\r
+                       dws->read = (dws->read != null_reader) ?\r
+                                       u16_reader : null_reader;\r
+                       dws->write = (dws->write != null_writer) ?\r
+                                       u16_writer : null_writer;\r
+                       spi_dfs = SPI_DFS_16BIT;\r
+                       break;\r
+               default:\r
+                       dev_err(&dws->master->dev, "MRST SPI0: unsupported bits:"\r
+                               "%db\n", bits);\r
+                       message->status = -EIO;\r
+                       goto early_exit;\r
+               }\r
+\r
+               cr0 = (spi_dfs << SPI_DFS_OFFSET)\r
+                       | (chip->type << SPI_FRF_OFFSET)\r
+                       | (spi->mode << SPI_MODE_OFFSET)\r
+                       | (chip->tmode << SPI_TMOD_OFFSET);\r
+       }\r
+       message->state = RUNNING_STATE;\r
\r
+       /*\r
+        * Adjust transfer mode if necessary. Requires platform dependent\r
+        * chipselect mechanism.\r
+        */\r
+       if (dws->cs_control) {\r
+               if (dws->rx && dws->tx)\r
+                       chip->tmode = SPI_TMOD_TR;\r
+               else if (dws->rx)\r
+                       chip->tmode = SPI_TMOD_RO;\r
+               else\r
+                       chip->tmode = SPI_TMOD_TO;\r
+\r
+               cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
+               cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
+       }\r
+       \r
+       /* Check if current transfer is a DMA transaction */\r
+       dws->dma_mapped = map_dma_buffers(dws);\r
+\r
+       /*\r
+        * Reprogram registers only if\r
+        *      1. chip select changes\r
+        *      2. clk_div is changed\r
+        *      3. control value changes\r
+        */\r
+       spi_enable_chip(dws, 0);\r
+       if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0)\r
+               rk29xx_writew(dws, SPIM_CTRLR0, cr0);\r
+\r
+    DBG(KERN_INFO "clk_div: 0x%x, chip->clk_div: 0x%x\n", clk_div, chip->clk_div);\r
+       spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);            \r
+       spi_chip_sel(dws, spi->chip_select);            \r
+       rk29xx_writew(dws, SPIM_CTRLR1, 0);//add by lyx\r
+       if(dws->dma_mapped ) {\r
+               dmacr = rk29xx_readw(dws, SPIM_DMACR);\r
+               dmacr = dmacr | SPI_DMACR_TX_ENABLE;\r
+               if (mode) \r
+                       dmacr = dmacr | SPI_DMACR_RX_ENABLE;\r
+               rk29xx_writew(dws, SPIM_DMACR, dmacr);\r
+       }\r
+       spi_enable_chip(dws, 1);\r
+       if (cs_change)\r
+               dws->prev_chip = chip;\r
+       \r
+       if (mode)\r
+               return do_full_transfer(dws);\r
+       else\r
+               return do_half_transfer(dws);   \r
+       \r
+early_exit:\r
+       \r
+       //msg_giveback(dws);\r
+       \r
+       return 0;\r
+}\r
+\r
+static void rk29xx_pump_messages(struct rk29xx_spi *dws, int mode)\r
+{\r
+       DBG(KERN_INFO "+++++++++++++++enter %s++++++++++++++++++\n", __func__);\r
+       \r
+       while (!acquire_dma(dws))\r
+                       msleep(10);\r
+\r
+       if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {\r
+               dws->busy = 0;\r
+               return;\r
+       }\r
+\r
+       /* Make sure we are not already running a message */\r
+       if (dws->cur_msg) {\r
+               return;\r
+       }\r
+\r
+       /* Extract head of queue */\r
+       dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);\r
+       list_del_init(&dws->cur_msg->queue);\r
+\r
+       /* Initial message state*/\r
+       dws->cur_msg->state = START_STATE;\r
+       dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,\r
+                                               struct spi_transfer,\r
+                                               transfer_list);\r
+       dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);\r
+    dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj\r
+    \r
+       /* Mark as busy and launch transfers */\r
+       dws->busy = 1;\r
+\r
+       while (rk29xx_pump_transfers(dws, mode)) ;\r
+}\r
+\r
+/* spi_device use this to queue in their spi_msg */\r
+static int rk29xx_spi_quick_transfer(struct spi_device *spi, struct spi_message *msg)\r
+{\r
+       struct rk29xx_spi *dws = spi_master_get_devdata(spi->master);\r
+       unsigned long flags;\r
+       struct rk29xx_spi_chip *chip_info = spi->controller_data;\r
+       struct spi_message *mmsg;\r
+       \r
+       DBG(KERN_INFO "+++++++++++++++enter %s++++++++++++++++++\n", __func__);\r
+       \r
+       spin_lock_irqsave(&dws->lock, flags);\r
+\r
+       if (dws->run == QUEUE_STOPPED) {\r
+               spin_unlock_irqrestore(&dws->lock, flags);\r
+               return -ESHUTDOWN;\r
+       }\r
+\r
+       msg->actual_length = 0;\r
+       msg->status = -EINPROGRESS;\r
+       msg->state = START_STATE;\r
+\r
+       list_add_tail(&msg->queue, &dws->queue);\r
+\r
+       if (chip_info && (chip_info->transfer_mode == rk29xx_SPI_FULL_DUPLEX)) {\r
+               rk29xx_pump_messages(dws,1);\r
+       }\r
+       else {          \r
+               rk29xx_pump_messages(dws,0);\r
+       }\r
+\r
+       mmsg = dws->cur_msg;\r
+       msg_giveback(dws);\r
+       \r
+       spin_unlock_irqrestore(&dws->lock, flags);\r
+\r
+       if (mmsg->complete)\r
+               mmsg->complete(mmsg->context);\r
+       \r
+       return 0;\r
+}\r
+\r
+#else\r
+\r
+/* spi_device use this to queue in their spi_msg */\r
+static int rk29xx_spi_transfer(struct spi_device *spi, struct spi_message *msg)\r
+{\r
+       struct rk29xx_spi *dws = spi_master_get_devdata(spi->master);\r
+       unsigned long flags;\r
+\r
+       spin_lock_irqsave(&dws->lock, flags);\r
+\r
+       if (dws->run == QUEUE_STOPPED) {\r
+               spin_unlock_irqrestore(&dws->lock, flags);\r
+               return -ESHUTDOWN;\r
+       }\r
+\r
+       msg->actual_length = 0;\r
+       msg->status = -EINPROGRESS;\r
+       msg->state = START_STATE;\r
+\r
+       list_add_tail(&msg->queue, &dws->queue);\r
+\r
+       if (dws->run == QUEUE_RUNNING && !dws->busy) {\r
+\r
+               if (dws->cur_transfer || dws->cur_msg)\r
+                       queue_work(dws->workqueue,\r
+                                       &dws->pump_messages);\r
+               else {\r
+                       /* If no other data transaction in air, just go */\r
+                       spin_unlock_irqrestore(&dws->lock, flags);\r
+                       pump_messages(&dws->pump_messages);\r
+                       return 0;\r
+               }\r
+       }\r
+\r
+       spin_unlock_irqrestore(&dws->lock, flags);\r
+       \r
+       return 0;\r
+}\r
+\r
+#endif\r
+\r
+/* This may be called twice for each spi dev */\r
+static int rk29xx_spi_setup(struct spi_device *spi)\r
+{\r
+       struct rk29xx_spi_chip *chip_info = NULL;\r
+       struct chip_data *chip;\r
+       u8 spi_dfs = 0;\r
+\r
+       if (spi->bits_per_word != 8 && spi->bits_per_word != 16)\r
+               return -EINVAL;\r
+\r
+       /* Only alloc on first setup */\r
+       chip = spi_get_ctldata(spi);\r
+       if (!chip) {\r
+               chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);\r
+               if (!chip)\r
+                       return -ENOMEM;\r
+\r
+               chip->cs_control = NULL;\r
+               chip->enable_dma = 1;  //0;\r
+       }\r
+\r
+       /*\r
+        * Protocol drivers may change the chip settings, so...\r
+        * if chip_info exists, use it\r
+        */\r
+       chip_info = spi->controller_data;\r
+\r
+       /* chip_info doesn't always exist */\r
+       if (chip_info) {\r
+               if (chip_info->cs_control)\r
+                       chip->cs_control = chip_info->cs_control;\r
+\r
+               chip->poll_mode = chip_info->poll_mode;\r
+               chip->type = chip_info->type;\r
+\r
+               chip->rx_threshold = 0;\r
+               chip->tx_threshold = 0;\r
+\r
+               chip->enable_dma = chip_info->enable_dma;\r
+       }\r
+\r
+       if (spi->bits_per_word == 8) {\r
+               chip->n_bytes = 1;\r
+               chip->dma_width = 1;\r
+               chip->read = u8_reader;\r
+               chip->write = u8_writer;\r
+               spi_dfs = SPI_DFS_8BIT;\r
+       } else if (spi->bits_per_word == 16) {\r
+               chip->n_bytes = 2;\r
+               chip->dma_width = 2;\r
+               chip->read = u16_reader;\r
+               chip->write = u16_writer;\r
+               spi_dfs = SPI_DFS_16BIT;\r
+       } else {\r
+               /* Never take >16b case for MRST SPIC */\r
+               dev_err(&spi->dev, "invalid wordsize\n");\r
+               return -EINVAL;\r
+       }\r
+       chip->bits_per_word = spi->bits_per_word;\r
+\r
+       if (!spi->max_speed_hz) {\r
+               dev_err(&spi->dev, "No max speed HZ parameter\n");\r
+               return -EINVAL;\r
+       }\r
+       chip->speed_hz = spi->max_speed_hz;\r
+\r
+       chip->tmode = 0; /* Tx & Rx */\r
+       /* Default SPI mode is SCPOL = 0, SCPH = 0 */\r
+       chip->cr0 = (spi_dfs << SPI_DFS_OFFSET)\r
+               | (SPI_HALF_WORLD_OFF << SPI_HALF_WORLD_TX_OFFSET)\r
+                       | (SPI_SSN_DELAY_ONE << SPI_SSN_DELAY_OFFSET)\r
+                       | (chip->type << SPI_FRF_OFFSET)\r
+                       | (spi->mode  << SPI_MODE_OFFSET)\r
+                       | (chip->tmode << SPI_TMOD_OFFSET);\r
+\r
+       spi_set_ctldata(spi, chip);\r
+       return 0;\r
+}\r
+\r
+static void rk29xx_spi_cleanup(struct spi_device *spi)\r
+{\r
+       struct chip_data *chip = spi_get_ctldata(spi);\r
+       kfree(chip);\r
+}\r
+\r
+static int __devinit init_queue(struct rk29xx_spi *dws)\r
+{\r
+       INIT_LIST_HEAD(&dws->queue);\r
+       spin_lock_init(&dws->lock);\r
+\r
+       dws->run = QUEUE_STOPPED;\r
+       dws->busy = 0;\r
+\r
+       init_completion(&dws->xfer_completion);\r
+\r
+       tasklet_init(&dws->pump_transfers,\r
+                       pump_transfers, (unsigned long)dws);\r
+\r
+       INIT_WORK(&dws->pump_messages, pump_messages);\r
+       dws->workqueue = create_singlethread_workqueue(\r
+                                       dev_name(dws->master->dev.parent));\r
+       if (dws->workqueue == NULL)\r
+               return -EBUSY;\r
+\r
+       return 0;\r
+}\r
+\r
+static int start_queue(struct rk29xx_spi *dws)\r
+{\r
+       unsigned long flags;\r
+\r
+       spin_lock_irqsave(&dws->lock, flags);\r
+\r
+       if (dws->run == QUEUE_RUNNING || dws->busy) {\r
+               spin_unlock_irqrestore(&dws->lock, flags);\r
+               return -EBUSY;\r
+       }\r
+\r
+       dws->run = QUEUE_RUNNING;\r
+       dws->cur_msg = NULL;\r
+       dws->cur_transfer = NULL;\r
+       dws->cur_chip = NULL;\r
+       dws->prev_chip = NULL;\r
+       spin_unlock_irqrestore(&dws->lock, flags);\r
+\r
+       queue_work(dws->workqueue, &dws->pump_messages);\r
+\r
+       return 0;\r
+}\r
+\r
+static int stop_queue(struct rk29xx_spi *dws)\r
+{\r
+       unsigned long flags;\r
+       unsigned limit = 50;\r
+       int status = 0;\r
+\r
+       spin_lock_irqsave(&dws->lock, flags);\r
+       dws->run = QUEUE_STOPPED;\r
+       while (!list_empty(&dws->queue) && dws->busy && limit--) {\r
+               spin_unlock_irqrestore(&dws->lock, flags);\r
+               msleep(10);\r
+               spin_lock_irqsave(&dws->lock, flags);\r
+       }\r
+\r
+       if (!list_empty(&dws->queue) || dws->busy)\r
+               status = -EBUSY;\r
+       spin_unlock_irqrestore(&dws->lock, flags);\r
+\r
+       return status;\r
+}\r
+\r
+static int destroy_queue(struct rk29xx_spi *dws)\r
+{\r
+       int status;\r
+\r
+       status = stop_queue(dws);\r
+       if (status != 0)\r
+               return status;\r
+       destroy_workqueue(dws->workqueue);\r
+       return 0;\r
+}\r
+\r
+/* Restart the controller, disable all interrupts, clean rx fifo */\r
+static void spi_hw_init(struct rk29xx_spi *dws)\r
+{\r
+       spi_enable_chip(dws, 0);\r
+       spi_mask_intr(dws, 0xff);\r
+       spi_enable_chip(dws, 1);\r
+       flush(dws);\r
+\r
+       /*\r
+        * Try to detect the FIFO depth if not set by interface driver,\r
+        * the depth could be from 2 to 32 from HW spec\r
+        */\r
+       if (!dws->fifo_len) {\r
+               u32 fifo;\r
+               for (fifo = 2; fifo <= 31; fifo++) {\r
+                       rk29xx_writew(dws, SPIM_TXFTLR, fifo);\r
+                       if (fifo != rk29xx_readw(dws, SPIM_TXFTLR))\r
+                               break;\r
+               }\r
+\r
+               dws->fifo_len = (fifo == 31) ? 0 : fifo;\r
+               rk29xx_writew(dws, SPIM_TXFTLR, 0);\r
+       }\r
+}\r
+\r
+/* cpufreq driver support */\r
+#ifdef CONFIG_CPU_FREQ\r
+\r
+static int rk29xx_spim_cpufreq_transition(struct notifier_block *nb, unsigned long val, void *data)\r
+{\r
+        struct rk29xx_spi *info;\r
+        unsigned long newclk;\r
+\r
+        info = container_of(nb, struct rk29xx_spi, freq_transition);\r
+        newclk = clk_get_rate(info->clock_spim);\r
+\r
+        return 0;\r
+}\r
+\r
+static inline int rk29xx_spim_cpufreq_register(struct rk29xx_spi *info)\r
+{\r
+        info->freq_transition.notifier_call = rk29xx_spim_cpufreq_transition;\r
+\r
+        return cpufreq_register_notifier(&info->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);\r
+}\r
+\r
+static inline void rk29xx_spim_cpufreq_deregister(struct rk29xx_spi *info)\r
+{\r
+        cpufreq_unregister_notifier(&info->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);\r
+}\r
+\r
+#else\r
+static inline int rk29xx_spim_cpufreq_register(struct rk29xx_spi *info)\r
+{\r
+        return 0;\r
+}\r
+\r
+static inline void rk29xx_spim_cpufreq_deregister(struct rk29xx_spi *info)\r
+{\r
+}\r
+#endif\r
+static int __init rk29xx_spim_probe(struct platform_device *pdev)\r
+{\r
+       struct resource         *regs, *dmatx_res, *dmarx_res;\r
+       struct rk29xx_spi   *dws;\r
+       struct spi_master   *master;\r
+       int                     irq; \r
+       int ret;\r
+       struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data;\r
+       char szBuf[8];\r
+\r
+       if (pdata && pdata->io_init) {\r
+               ret = pdata->io_init(pdata->chipselect_gpios, pdata->num_chipselect);\r
+               if (ret) {                      \r
+                       return -ENXIO;  \r
+               }\r
+       }\r
+       \r
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+       if (!regs)\r
+               return -ENXIO;\r
+       dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);\r
+       if (dmatx_res == NULL) {\r
+               dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");\r
+               return -ENXIO;\r
+       }\r
+\r
+       dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);\r
+       if (dmarx_res == NULL) {\r
+               dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");\r
+               return -ENXIO;\r
+       }\r
+       irq = platform_get_irq(pdev, 0);\r
+       if (irq < 0)\r
+               return irq;                     \r
+       /* setup spi core then atmel-specific driver state */\r
+       ret = -ENOMEM;  \r
+       master = spi_alloc_master(&pdev->dev, sizeof *dws);\r
+       if (!master) {\r
+               ret = -ENOMEM;\r
+               goto exit;\r
+       }\r
+\r
+       platform_set_drvdata(pdev, master);\r
+       dws = spi_master_get_devdata(master);\r
+       memset(szBuf, 0, sizeof(szBuf));\r
+       sprintf(szBuf, "%s%d", "spi", pdev->id);\r
+    dws->clock_spim = clk_get(&pdev->dev, szBuf);\r
+       clk_enable(dws->clock_spim);\r
+       if (IS_ERR(dws->clock_spim)) {\r
+               dev_err(&pdev->dev, "clk_get for %s fail(%p)\n", szBuf, dws->clock_spim);\r
+               return PTR_ERR(dws->clock_spim);\r
+       }\r
+       \r
+       dws->regs = ioremap(regs->start, (regs->end - regs->start) + 1);\r
+       if (!dws->regs){\r
+       release_mem_region(regs->start, (regs->end - regs->start) + 1);\r
+               return -EBUSY;\r
+       }\r
+       DBG(KERN_INFO "dws->regs: %p\n", dws->regs);\r
+    dws->irq = irq;\r
+       dws->irq_polarity = IRQF_TRIGGER_NONE;\r
+       dws->master = master;\r
+       dws->type = SSI_MOTO_SPI;\r
+       dws->prev_chip = NULL;\r
+       dws->sfr_start = regs->start;\r
+       dws->tx_dmach = dmatx_res->start;\r
+       dws->rx_dmach = dmarx_res->start;\r
+       dws->dma_inited = 0;  ///0;\r
+       ///dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);\r
+       ret = request_irq(dws->irq, rk29xx_spi_irq, dws->irq_polarity,\r
+                       "rk29xx_spim", dws);\r
+       if (ret < 0) {\r
+               dev_err(&master->dev, "can not get IRQ\n");\r
+               goto err_free_master;\r
+       }\r
+\r
+       master->mode_bits = SPI_CPOL | SPI_CPHA;\r
+       master->bus_num = pdev->id;\r
+       master->num_chipselect = pdata->num_chipselect;\r
+       master->dev.platform_data = pdata;\r
+       master->cleanup = rk29xx_spi_cleanup;\r
+       master->setup = rk29xx_spi_setup;\r
+       #if defined(QUICK_TRANSFER)\r
+       master->transfer = rk29xx_spi_quick_transfer;\r
+       #else\r
+       master->transfer = rk29xx_spi_transfer;\r
+       #endif\r
+       \r
+       dws->pdev = pdev;\r
+       /* Basic HW init */\r
+       spi_hw_init(dws);\r
+       /* Initial and start queue */\r
+       ret = init_queue(dws);\r
+       if (ret) {\r
+               dev_err(&master->dev, "problem initializing queue\n");\r
+               goto err_diable_hw;\r
+       }\r
+\r
+       ret = start_queue(dws);\r
+       if (ret) {\r
+               dev_err(&master->dev, "problem starting queue\n");\r
+               goto err_diable_hw;\r
+       }\r
+\r
+       spi_master_set_devdata(master, dws);\r
+       ret = spi_register_master(master);\r
+       if (ret) {\r
+               dev_err(&master->dev, "problem registering spi master\n");\r
+               goto err_queue_alloc;\r
+       }\r
+\r
+    ret =rk29xx_spim_cpufreq_register(dws);\r
+    if (ret < 0) {\r
+        dev_err(&master->dev, "rk29xx spim failed to init cpufreq support\n");\r
+        goto err_queue_alloc;\r
+    }\r
+       DBG(KERN_INFO "rk29xx_spim: driver initialized\n");\r
+       mrst_spi_debugfs_init(dws);\r
+       return 0;\r
+\r
+err_queue_alloc:\r
+       destroy_queue(dws);\r
+err_diable_hw:\r
+       spi_enable_chip(dws, 0);\r
+       free_irq(dws->irq, dws);\r
+err_free_master:\r
+       spi_master_put(master);\r
+       iounmap(dws->regs);\r
+exit:\r
+       return ret;\r
+}\r
+\r
+static void __exit rk29xx_spim_remove(struct platform_device *pdev)\r
+{\r
+       struct spi_master *master = platform_get_drvdata(pdev);\r
+       struct rk29xx_spi *dws = spi_master_get_devdata(master);\r
+       int status = 0;\r
+\r
+       if (!dws)\r
+               return;\r
+       rk29xx_spim_cpufreq_deregister(dws);\r
+       mrst_spi_debugfs_remove(dws);\r
+\r
+       release_dma(dws);\r
+\r
+       /* Remove the queue */\r
+       status = destroy_queue(dws);\r
+       if (status != 0)\r
+               dev_err(&dws->master->dev, "rk29xx_spi_remove: workqueue will not "\r
+                       "complete, message memory not freed\n");\r
+       clk_put(dws->clock_spim);\r
+       clk_disable(dws->clock_spim);\r
+       spi_enable_chip(dws, 0);\r
+       /* Disable clk */\r
+       spi_set_clk(dws, 0);\r
+       free_irq(dws->irq, dws);\r
+\r
+       /* Disconnect from the SPI framework */\r
+       spi_unregister_master(dws->master);\r
+       iounmap(dws->regs);\r
+}\r
+\r
+\r
+#ifdef CONFIG_PM\r
+\r
+static int rk29xx_spim_suspend(struct platform_device *pdev, pm_message_t mesg)\r
+{\r
+       struct spi_master *master = platform_get_drvdata(pdev);\r
+       struct rk29xx_spi *dws = spi_master_get_devdata(master);\r
+       struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data;\r
+       int status;\r
+\r
+       status = stop_queue(dws);\r
+       if (status != 0)\r
+               return status;\r
+       clk_disable(dws->clock_spim);\r
+       if (pdata && pdata->io_fix_leakage_bug)\r
+       {\r
+               pdata->io_fix_leakage_bug( );\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int rk29xx_spim_resume(struct platform_device *pdev)\r
+{\r
+       struct spi_master *master = platform_get_drvdata(pdev);\r
+       struct rk29xx_spi *dws = spi_master_get_devdata(master);\r
+       struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data;\r
+       int ret;\r
+       \r
+       clk_enable(dws->clock_spim);    \r
+       spi_hw_init(dws);\r
+       ret = start_queue(dws);\r
+       if (ret)\r
+               dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);\r
+       if (pdata && pdata->io_resume_leakage_bug)\r
+       {\r
+               pdata->io_resume_leakage_bug( ); \r
+       }\r
+       return ret;\r
+}\r
+\r
+#else\r
+#define        rk29xx_spim_suspend     NULL\r
+#define        rk29xx_spim_resume      NULL\r
+#endif\r
+\r
+static struct platform_driver rk29xx_platform_spim_driver = {\r
+       .remove         = __exit_p(rk29xx_spim_remove),\r
+       .driver         = {\r
+               .name   = "rk29xx_spim",\r
+               .owner  = THIS_MODULE,\r
+       },\r
+       .suspend        = rk29xx_spim_suspend,\r
+       .resume         = rk29xx_spim_resume,\r
+};\r
+\r
+static int __init rk29xx_spim_init(void)\r
+{\r
+       int ret;\r
+       ret = platform_driver_probe(&rk29xx_platform_spim_driver, rk29xx_spim_probe);   \r
+       return ret;\r
+}\r
+\r
+static void __exit rk29xx_spim_exit(void)\r
+{\r
+       platform_driver_unregister(&rk29xx_platform_spim_driver);\r
+}\r
+\r
+subsys_initcall(rk29xx_spim_init);\r
+module_exit(rk29xx_spim_exit);\r
+\r
+MODULE_AUTHOR("www.rock-chips.com");\r
+MODULE_DESCRIPTION("Rockchip RK29xx spim port driver");\r
+MODULE_LICENSE("GPL");;\r
+\r
diff --git a/drivers/spi/rk29_spim.h b/drivers/spi/rk29_spim.h
new file mode 100755 (executable)
index 0000000..fb3ab62
--- /dev/null
@@ -0,0 +1,248 @@
+/* drivers/spi/rk29xx_spim.h\r
+ *\r
+ * Copyright (C) 2010 ROCKCHIP, Inc.\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ */\r
+#ifndef __DRIVERS_SPIM_RK29XX_HEADER_H\r
+#define __DRIVERS_SPIM_RK29XX_HEADER_H\r
+#include <linux/io.h>\r
+#include <mach/rk29-dma-pl330.h>\r
+\r
+/* SPI register offsets */\r
+#define SPIM_CTRLR0                            0x0000\r
+#define SPIM_CTRLR1                            0x0004\r
+#define SPIM_ENR                               0x0008\r
+#define SPIM_SER                               0x000c\r
+#define SPIM_BAUDR                             0x0010\r
+#define SPIM_TXFTLR                            0x0014\r
+#define SPIM_RXFTLR                            0x0018\r
+#define SPIM_TXFLR                             0x001c\r
+#define SPIM_RXFLR                             0x0020\r
+#define SPIM_SR                                        0x0024\r
+#define SPIM_IPR                0x0028\r
+#define SPIM_IMR                               0x002c\r
+#define SPIM_ISR                               0x0030\r
+#define SPIM_RISR                              0x0034\r
+#define SPIM_ICR                               0x0038\r
+#define SPIM_DMACR                             0x003c\r
+#define SPIM_DMATDLR                   0x0040\r
+#define SPIM_DMARDLR                   0x0044\r
+#define SPIM_TXDR                              0x0400\r
+#define SPIM_RXDR               0x0800\r
+\r
+/* --------Bit fields in CTRLR0--------begin */\r
+\r
+#define SPI_DFS_OFFSET                 0                  /* Data Frame Size */\r
+#define SPI_DFS_4BIT            0x00\r
+#define SPI_DFS_8BIT            0x01\r
+#define SPI_DFS_16BIT           0x02\r
+#define SPI_DFS_RESV            0x03\r
+\r
+#define SPI_FRF_OFFSET                 16                 /* Frame Format */\r
+#define SPI_FRF_SPI                        0x00               /* motorola spi */\r
+#define SPI_FRF_SSP                        0x01               /* Texas Instruments SSP*/\r
+#define SPI_FRF_MICROWIRE              0x02               /*  National Semiconductors Microwire */\r
+#define SPI_FRF_RESV                   0x03\r
+\r
+#define SPI_MODE_OFFSET                    6                 /* SCPH & SCOL */\r
+\r
+#define SPI_SCPH_OFFSET                        6                  /* Serial Clock Phase */\r
+#define SPI_SCPH_TOGMID         0                  /* Serial clock toggles in middle of first data bit */\r
+#define SPI_SCPH_TOGSTA         1                  /* Serial clock toggles at start of first data bit */\r
+\r
+#define SPI_SCOL_OFFSET                        7                  /* Serial Clock Polarity */\r
+\r
+#define SPI_TMOD_OFFSET                        18                 /* Transfer Mode */\r
+#define        SPI_TMOD_TR                         0x00                       /* xmit & recv */\r
+#define SPI_TMOD_TO                        0x01                       /* xmit only */\r
+#define SPI_TMOD_RO                        0x02                       /* recv only */\r
+#define SPI_TMOD_RESV              0x03\r
+\r
+#define SPI_CFS_OFFSET                 2                  /* Control Frame Size */\r
+\r
+#define SPI_CSM_OFFSET          8                  /* Chip Select Mode */\r
+#define SPI_CSM_KEEP            0x00               /* ss_n keep low after every frame data is transferred */\r
+#define SPI_CSM_HALF            0x01               /* ss_n be high for half sclk_out cycles after every frame data is transferred */\r
+#define SPI_CSM_ONE             0x02               /* ss_n be high for one sclk_out cycle after every frame data is transferred */\r
+\r
+#define SPI_SSN_DELAY_OFFSET    10\r
+#define SPI_SSN_DELAY_HALF      0x00\r
+#define SPI_SSN_DELAY_ONE       0x01\r
+\r
+#define SPI_HALF_WORLD_TX_OFFSET       13\r
+#define SPI_HALF_WORLD_ON       0x00\r
+#define SPI_HALF_WORLD_OFF      0x01\r
+\r
+\r
+/* --------Bit fields in CTRLR0--------end */\r
+\r
+\r
+/* Bit fields in SR, 7 bits */\r
+#define SR_MASK                                0x7f            /* cover 7 bits */\r
+#define SR_BUSY                                (1 << 0)\r
+#define SR_TF_FULL                 (1 << 1)\r
+#define SR_TF_EMPT                     (1 << 2)\r
+#define SR_RF_EMPT                 (1 << 3)\r
+#define SR_RF_FULL                     (1 << 4)\r
+\r
+/* Bit fields in ISR, IMR, RISR, 7 bits */\r
+#define SPI_INT_TXEI                   (1 << 0)\r
+#define SPI_INT_TXOI                   (1 << 1)\r
+#define SPI_INT_RXUI                   (1 << 2)\r
+#define SPI_INT_RXOI                   (1 << 3)\r
+#define SPI_INT_RXFI                   (1 << 4)\r
+\r
+/* Bit fields in DMACR */\r
+#define SPI_DMACR_TX_ENABLE     (1 << 1)\r
+#define SPI_DMACR_RX_ENABLE     (1 << 0)\r
+\r
+/* Bit fields in ICR */\r
+#define SPI_CLEAR_INT_ALL       (1<< 0)\r
+#define SPI_CLEAR_INT_RXUI      (1 << 1)\r
+#define SPI_CLEAR_INT_RXOI      (1 << 2)\r
+#define SPI_CLEAR_INT_TXOI      (1 << 3)\r
+\r
+enum rk29xx_ssi_type {\r
+       SSI_MOTO_SPI = 0,\r
+       SSI_TI_SSP,\r
+       SSI_NS_MICROWIRE,\r
+};\r
+\r
+struct rk29xx_spi {\r
+       struct spi_master       *master;\r
+       struct spi_device       *cur_dev;\r
+       enum rk29xx_ssi_type    type;\r
+\r
+       void __iomem            *regs;\r
+       unsigned long           paddr;\r
+       u32                     iolen;\r
+       int                     irq;\r
+       u32         irq_polarity;\r
+       u32                     fifo_len;       /* depth of the FIFO buffer */\r
+       struct clk              *clock_spim;    /* clk apb */\r
+       struct platform_device  *pdev;\r
+       \r
+       /* Driver message queue */\r
+       struct workqueue_struct *workqueue;\r
+       struct work_struct      pump_messages;\r
+       spinlock_t              lock;\r
+       struct list_head        queue;\r
+       int                     busy;\r
+       int                     run;\r
+\r
+       /* Message Transfer pump */\r
+       struct tasklet_struct   pump_transfers;\r
+\r
+       /* Current message transfer state info */\r
+       struct spi_message      *cur_msg;\r
+       struct spi_transfer     *cur_transfer;\r
+       struct chip_data        *cur_chip;\r
+       struct chip_data        *prev_chip;\r
+       size_t                  len;\r
+       void                    *tx;\r
+       void                    *tx_end;\r
+       void                    *rx;\r
+       void                    *rx_end;\r
+       int                     dma_mapped;\r
+       dma_addr_t              rx_dma;\r
+       dma_addr_t              tx_dma;\r
+       size_t                  rx_map_len;\r
+       size_t                  tx_map_len;\r
+       u8                      n_bytes;        /* current is a 1/2 bytes op */\r
+       u8                      max_bits_per_word;      /* maxim is 16b */\r
+       u32                     dma_width;\r
+       int                     cs_change;\r
+       int                     (*write)(struct rk29xx_spi *dws);\r
+       int                     (*read)(struct rk29xx_spi *dws);\r
+       irqreturn_t             (*transfer_handler)(struct rk29xx_spi *dws);\r
+       void (*cs_control)(struct rk29xx_spi *dws, u32 cs, u8 flag);\r
+\r
+       /* Dma info */\r
+       struct completion               xfer_completion;\r
+       unsigned    state;\r
+       unsigned                        cur_speed;\r
+       unsigned long                   sfr_start;\r
+       int                     dma_inited;\r
+       enum dma_ch rx_dmach;\r
+       enum dma_ch tx_dmach;\r
+       int                     txdma_done;\r
+       int                     rxdma_done;\r
+       u64                     tx_param;\r
+       u64                     rx_param;\r
+       struct device           *dma_dev;\r
+       dma_addr_t              dma_addr;\r
+\r
+       /* Bus interface info */\r
+       void                    *priv;\r
+#ifdef CONFIG_DEBUG_FS\r
+       struct dentry *debugfs;\r
+#endif\r
+#ifdef CONFIG_CPU_FREQ\r
+        struct notifier_block   freq_transition;\r
+#endif\r
+};\r
+\r
+#define rk29xx_readl(dw, off) \\r
+       __raw_readl(dw->regs + off)\r
+#define rk29xx_writel(dw,off,val) \\r
+       __raw_writel(val, dw->regs + off)\r
+#define rk29xx_readw(dw, off) \\r
+       __raw_readw(dw->regs + off)\r
+#define rk29xx_writew(dw,off,val) \\r
+       __raw_writel(val, dw->regs + off)\r
+\r
+static inline void spi_enable_chip(struct rk29xx_spi *dws, int enable)\r
+{\r
+       rk29xx_writel(dws, SPIM_ENR, (enable ? 1 : 0));\r
+}\r
+\r
+static inline void spi_set_clk(struct rk29xx_spi *dws, u16 div)\r
+{\r
+       rk29xx_writel(dws, SPIM_BAUDR, div);\r
+}\r
+\r
+/* Disable IRQ bits */\r
+static inline void spi_mask_intr(struct rk29xx_spi *dws, u32 mask)\r
+{\r
+       u32 new_mask;\r
+\r
+       new_mask = rk29xx_readl(dws, SPIM_IMR) & ~mask;\r
+       rk29xx_writel(dws, SPIM_IMR, new_mask);\r
+}\r
+\r
+/* Enable IRQ bits */\r
+static inline void spi_umask_intr(struct rk29xx_spi *dws, u32 mask)\r
+{\r
+       u32 new_mask;\r
+\r
+       new_mask = rk29xx_readl(dws, SPIM_IMR) | mask;\r
+       rk29xx_writel(dws, SPIM_IMR, new_mask);\r
+}\r
+\r
+//spi transfer mode                   add by lyx\r
+#define rk29xx_SPI_HALF_DUPLEX 0\r
+#define rk29xx_SPI_FULL_DUPLEX 1\r
+\r
+/*\r
+ * Each SPI slave device to work with rk29xx spi controller should\r
+ * has such a structure claiming its working mode (PIO/DMA etc),\r
+ * which can be save in the "controller_data" member of the\r
+ * struct spi_device\r
+ */\r
+struct rk29xx_spi_chip {\r
+       u8 transfer_mode;/*full or half duplex*/\r
+       u8 poll_mode;   /* 0 for contoller polling mode */\r
+       u8 type;        /* SPI/SSP/Micrwire */\r
+       u8 enable_dma;\r
+       void (*cs_control)(struct rk29xx_spi *dws, u32 cs, u8 flag);\r
+};\r
+\r
+#endif /* __DRIVERS_SPIM_RK29XX_HEADER_H */\r
diff --git a/drivers/spi/rk29xx_spim.c b/drivers/spi/rk29xx_spim.c
deleted file mode 100755 (executable)
index 9d15abc..0000000
+++ /dev/null
@@ -1,1955 +0,0 @@
-/*drivers/serial/rk29xx_spim.c - driver for rk29xx spim device \r
- *\r
- * Copyright (C) 2010 ROCKCHIP, Inc.\r
- *\r
- * This software is licensed under the terms of the GNU General Public\r
- * License version 2, as published by the Free Software Foundation, and\r
- * may be copied, distributed, and modified under those terms.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- */\r
-\r
-#include <linux/dma-mapping.h>\r
-#include <linux/interrupt.h>\r
-#include <linux/highmem.h>\r
-#include <linux/delay.h>\r
-#include <linux/slab.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/clk.h>\r
-#include <linux/cpufreq.h>\r
-#include <mach/gpio.h>\r
-#include <linux/dma-mapping.h>\r
-#include <asm/dma.h>\r
-\r
-#include "rk29xx_spim.h"\r
-#include <linux/spi/spi.h>\r
-#include <mach/board.h>\r
-\r
-#ifdef CONFIG_DEBUG_FS\r
-#include <linux/debugfs.h>\r
-#endif\r
-\r
-/*Ô­ÓеÄspiÇý¶¯Ð§ÂʱȽϵͣ¬\r
-ÎÞ·¨Âú×ã´óÊý¾ÝÁ¿µÄ´«Ê䣻\r
-QUICK_TRANSFERÓÃÓÚ¿ìËÙ´«Ê䣬ͬʱ¿ÉÖ¸¶¨°ëË«¹¤»òÈ«Ë«¹¤£¬\r
-ĬÈÏʹÓðëË«¹¤\r
-*/\r
-\r
-//#define QUICK_TRANSFER         \r
-\r
-#if 1\r
-#define DBG   printk\r
-#else\r
-#define DBG(x...)\r
-#endif\r
-\r
-#define DMA_MIN_BYTES 8\r
-\r
-\r
-#define START_STATE    ((void *)0)\r
-#define RUNNING_STATE  ((void *)1)\r
-#define DONE_STATE     ((void *)2)\r
-#define ERROR_STATE    ((void *)-1)\r
-\r
-#define QUEUE_RUNNING  0\r
-#define QUEUE_STOPPED  1\r
-\r
-#define MRST_SPI_DEASSERT      0\r
-#define MRST_SPI_ASSERT                1  ///CS0\r
-#define MRST_SPI_ASSERT1       2  ///CS1\r
-\r
-/* Slave spi_dev related */\r
-struct chip_data {\r
-       u16 cr0;\r
-       u8 cs;                  /* chip select pin */\r
-       u8 n_bytes;             /* current is a 1/2/4 byte op */\r
-       u8 tmode;               /* TR/TO/RO/EEPROM */\r
-       u8 type;                /* SPI/SSP/MicroWire */\r
-\r
-       u8 poll_mode;           /* 1 means use poll mode */\r
-\r
-       u32 dma_width;\r
-       u32 rx_threshold;\r
-       u32 tx_threshold;\r
-       u8 enable_dma:1;\r
-       u8 bits_per_word;\r
-       u16 clk_div;            /* baud rate divider */\r
-       u32 speed_hz;           /* baud rate */\r
-       int (*write)(struct rk29xx_spi *dws);\r
-       int (*read)(struct rk29xx_spi *dws);\r
-       void (*cs_control)(struct rk29xx_spi *dws, u32 cs, u8 flag);\r
-};\r
-\r
-#define SUSPND    (1<<0)\r
-#define SPIBUSY   (1<<1)\r
-#define RXBUSY    (1<<2)\r
-#define TXBUSY    (1<<3)\r
-\r
-#ifdef CONFIG_DEBUG_FS\r
-static int spi_show_regs_open(struct inode *inode, struct file *file)\r
-{\r
-       file->private_data = inode->i_private;\r
-       return 0;\r
-}\r
-\r
-#define SPI_REGS_BUFSIZE       1024\r
-static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,\r
-                               size_t count, loff_t *ppos)\r
-{\r
-       struct rk29xx_spi *dws;\r
-       char *buf;\r
-       u32 len = 0;\r
-       ssize_t ret;\r
-\r
-       dws = file->private_data;\r
-\r
-       buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);\r
-       if (!buf)\r
-               return 0;\r
-\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "MRST SPI0 registers:\n");\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "=================================\n");\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "CTRL0: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_CTRLR0));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "CTRL1: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_CTRLR1));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "SSIENR: \t0x%08x\n", rk29xx_readl(dws, SPIM_ENR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "SER: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_SER));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "BAUDR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_BAUDR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "TXFTLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_TXFTLR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "RXFTLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_RXFTLR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "TXFLR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_TXFLR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "RXFLR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_RXFLR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "SR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_SR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "IMR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_IMR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "ISR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_ISR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "DMACR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_DMACR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "DMATDLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_DMATDLR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "DMARDLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_DMARDLR));\r
-       len += printk(buf + len, SPI_REGS_BUFSIZE - len,\r
-                       "=================================\n");\r
-\r
-       ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);\r
-       kfree(buf);\r
-       return ret;\r
-}\r
-\r
-static const struct file_operations mrst_spi_regs_ops = {\r
-       .owner          = THIS_MODULE,\r
-       .open           = spi_show_regs_open,\r
-       .read           = spi_show_regs,\r
-};\r
-\r
-static int mrst_spi_debugfs_init(struct rk29xx_spi *dws)\r
-{\r
-       dws->debugfs = debugfs_create_dir("mrst_spi", NULL);\r
-       if (!dws->debugfs)\r
-               return -ENOMEM;\r
-\r
-       debugfs_create_file("registers", S_IFREG | S_IRUGO,\r
-               dws->debugfs, (void *)dws, &mrst_spi_regs_ops);\r
-       return 0;\r
-}\r
-\r
-static void mrst_spi_debugfs_remove(struct rk29xx_spi *dws)\r
-{\r
-       if (dws->debugfs)\r
-               debugfs_remove_recursive(dws->debugfs);\r
-}\r
-\r
-#else\r
-static inline int mrst_spi_debugfs_init(struct rk29xx_spi *dws)\r
-{\r
-       return 0;\r
-}\r
-\r
-static inline void mrst_spi_debugfs_remove(struct rk29xx_spi *dws)\r
-{\r
-}\r
-#endif /* CONFIG_DEBUG_FS */\r
-\r
-static void wait_till_not_busy(struct rk29xx_spi *dws)\r
-{\r
-       unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);\r
-\r
-       while (time_before(jiffies, end)) {\r
-               if (!(rk29xx_readw(dws, SPIM_SR) & SR_BUSY))\r
-                       return;\r
-       }\r
-       dev_err(&dws->master->dev,\r
-               "DW SPI: Status keeps busy for 1000us after a read/write!\n");\r
-}\r
-\r
-#if defined(QUICK_TRANSFER)\r
-static void wait_till_tf_empty(struct rk29xx_spi *dws)\r
-{\r
-       unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);\r
-\r
-       while (time_before(jiffies, end)) {\r
-               if (rk29xx_readw(dws, SPIM_SR) & SR_TF_EMPT)\r
-                       return;\r
-       }\r
-       dev_err(&dws->master->dev,\r
-               "DW SPI: Status keeps busy for 1000us after a read/write!\n");\r
-}\r
-#endif\r
-\r
-static void flush(struct rk29xx_spi *dws)\r
-{\r
-       while (!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT))\r
-               rk29xx_readw(dws, SPIM_RXDR);\r
-\r
-       wait_till_not_busy(dws);\r
-}\r
-\r
-#if 0\r
-static void spi_cs_control(struct rk29xx_spi *dws, u32 cs, u8 flag)\r
-{\r
-       struct rk29xx_spi_platform_data *pdata = dws->master->dev.platform_data;\r
-       struct spi_cs_gpio *cs_gpios = pdata->chipselect_gpios;\r
-\r
-       if (flag == 0)\r
-               gpio_direction_output(cs_gpios[cs].cs_gpio, GPIO_HIGH);\r
-       else\r
-               gpio_direction_output(cs_gpios[cs].cs_gpio, GPIO_LOW);\r
-}\r
-#endif\r
-\r
-static int null_writer(struct rk29xx_spi *dws)\r
-{\r
-       u8 n_bytes = dws->n_bytes;\r
-\r
-       if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
-               || (dws->tx == dws->tx_end))\r
-               return 0;\r
-       rk29xx_writew(dws, SPIM_TXDR, 0);\r
-       dws->tx += n_bytes;\r
-       //wait_till_not_busy(dws);\r
-\r
-       return 1;\r
-}\r
-\r
-static int null_reader(struct rk29xx_spi *dws)\r
-{\r
-       u8 n_bytes = dws->n_bytes;\r
-       while ((!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT))\r
-               && (dws->rx < dws->rx_end)) {\r
-               rk29xx_readw(dws, SPIM_RXDR);\r
-               dws->rx += n_bytes;\r
-       }\r
-       wait_till_not_busy(dws);\r
-       return dws->rx == dws->rx_end;\r
-}\r
-\r
-static int u8_writer(struct rk29xx_spi *dws)\r
-{      \r
-       if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
-               || (dws->tx == dws->tx_end))\r
-               return 0;\r
-       rk29xx_writew(dws, SPIM_TXDR, *(u8 *)(dws->tx));\r
-       ++dws->tx;\r
-       //wait_till_not_busy(dws);\r
-\r
-       return 1;\r
-}\r
-\r
-static int u8_reader(struct rk29xx_spi *dws)\r
-{\r
-       while (!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT)\r
-               && (dws->rx < dws->rx_end)) {\r
-               *(u8 *)(dws->rx) = rk29xx_readw(dws, SPIM_RXDR) & 0xFFU;\r
-               ++dws->rx;\r
-       }\r
-\r
-       wait_till_not_busy(dws);\r
-       return dws->rx == dws->rx_end;\r
-}\r
-\r
-static int u16_writer(struct rk29xx_spi *dws)\r
-{\r
-       if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
-               || (dws->tx == dws->tx_end))\r
-               return 0;\r
-\r
-       rk29xx_writew(dws, SPIM_TXDR, *(u16 *)(dws->tx));\r
-       dws->tx += 2;\r
-       //wait_till_not_busy(dws);\r
-\r
-       return 1;\r
-}\r
-\r
-static int u16_reader(struct rk29xx_spi *dws)\r
-{\r
-       u16 temp;\r
-\r
-       while (!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT)\r
-               && (dws->rx < dws->rx_end)) {\r
-               temp = rk29xx_readw(dws, SPIM_RXDR);\r
-               *(u16 *)(dws->rx) = temp;\r
-               dws->rx += 2;\r
-       }\r
-\r
-       wait_till_not_busy(dws);\r
-       return dws->rx == dws->rx_end;\r
-}\r
-\r
-static void *next_transfer(struct rk29xx_spi *dws)\r
-{\r
-       struct spi_message *msg = dws->cur_msg;\r
-       struct spi_transfer *trans = dws->cur_transfer;\r
-\r
-       /* Move to next transfer */\r
-       if (trans->transfer_list.next != &msg->transfers) {\r
-               dws->cur_transfer =\r
-                       list_entry(trans->transfer_list.next,\r
-                                       struct spi_transfer,\r
-                                       transfer_list);\r
-               return RUNNING_STATE;\r
-       } else\r
-               return DONE_STATE;\r
-}\r
-\r
-static void rk29_spi_dma_rxcb(void *buf_id,\r
-                                int size, enum rk29_dma_buffresult res)\r
-{\r
-       struct rk29xx_spi *dws = buf_id;\r
-       unsigned long flags;\r
-\r
-       spin_lock_irqsave(&dws->lock, flags);\r
-\r
-       if (res == RK29_RES_OK)\r
-               dws->state &= ~RXBUSY;\r
-       else\r
-               dev_err(&dws->master->dev, "DmaAbrtRx-%d, size: %d\n", res, size);\r
-\r
-       /* If the other done */\r
-       if (!(dws->state & TXBUSY))\r
-               complete(&dws->xfer_completion);\r
-\r
-       spin_unlock_irqrestore(&dws->lock, flags);\r
-}\r
-\r
-static void rk29_spi_dma_txcb(void *buf_id,\r
-                                int size, enum rk29_dma_buffresult res)\r
-{\r
-       struct rk29xx_spi *dws = buf_id;\r
-       unsigned long flags;\r
-\r
-       spin_lock_irqsave(&dws->lock, flags);\r
-\r
-       if (res == RK29_RES_OK)\r
-               dws->state &= ~TXBUSY;\r
-       else\r
-               dev_err(&dws->master->dev, "DmaAbrtTx-%d \n", size);\r
-\r
-       /* If the other done */\r
-       if (!(dws->state & RXBUSY)) \r
-               complete(&dws->xfer_completion);\r
-\r
-       spin_unlock_irqrestore(&dws->lock, flags);\r
-}\r
-\r
-\r
-static struct rk29_dma_client rk29_spi_dma_client = {\r
-       .name = "rk29xx-spi-dma",\r
-};\r
-\r
-static int acquire_dma(struct rk29xx_spi *dws)\r
-{      \r
-       if (dws->dma_inited) {\r
-               return 0;\r
-       }\r
-\r
-       if(rk29_dma_request(dws->rx_dmach, \r
-               &rk29_spi_dma_client, NULL) < 0) {\r
-               dev_err(&dws->master->dev, "dws->rx_dmach : %d, cannot get RxDMA\n", dws->rx_dmach);\r
-               return -1;\r
-       }\r
-\r
-       if (rk29_dma_request(dws->tx_dmach,\r
-                                       &rk29_spi_dma_client, NULL) < 0) {\r
-               dev_err(&dws->master->dev, "dws->tx_dmach : %d, cannot get TxDMA\n", dws->tx_dmach);\r
-               rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client);\r
-               return -1;\r
-       }\r
-       \r
-    dws->dma_inited = 1;\r
-       return 0;\r
-}\r
-\r
-static void release_dma(struct rk29xx_spi *dws)\r
-{\r
-       if(!dws && dws->dma_inited) {\r
-               rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client);\r
-               rk29_dma_free(dws->tx_dmach, &rk29_spi_dma_client);\r
-       }\r
-}\r
-\r
-/*\r
- * Note: first step is the protocol driver prepares\r
- * a dma-capable memory, and this func just need translate\r
- * the virt addr to physical\r
- */\r
-static int map_dma_buffers(struct rk29xx_spi *dws)\r
-{\r
-       if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited\r
-               || !dws->cur_chip->enable_dma)\r
-               return -1;\r
-\r
-       if (dws->cur_transfer->tx_dma) {\r
-               dws->tx_dma = dws->cur_transfer->tx_dma;\r
-               if (rk29_dma_set_buffdone_fn(dws->tx_dmach, rk29_spi_dma_txcb)) {\r
-                       dev_err(&dws->master->dev, "rk29_dma_set_buffdone_fn fail\n");\r
-                       return -1;\r
-               }\r
-               if (rk29_dma_devconfig(dws->tx_dmach, RK29_DMASRC_MEM,\r
-                                       (unsigned long)dws->sfr_start + SPIM_TXDR)) {\r
-                       dev_err(&dws->master->dev, "rk29_dma_devconfig fail\n");\r
-                       return -1;\r
-               }\r
-       }\r
-\r
-       if (dws->cur_transfer->rx_dma) {\r
-               dws->rx_dma = dws->cur_transfer->rx_dma;\r
-               if (rk29_dma_set_buffdone_fn(dws->rx_dmach, rk29_spi_dma_rxcb)) {\r
-                       dev_err(&dws->master->dev, "rk29_dma_set_buffdone_fn fail\n");\r
-                       return -1;\r
-               }\r
-               if (rk29_dma_devconfig(dws->rx_dmach, RK29_DMASRC_HW,\r
-                                       (unsigned long)dws->sfr_start + SPIM_RXDR)) {\r
-                       dev_err(&dws->master->dev, "rk29_dma_devconfig fail\n");\r
-                       return -1;\r
-               }\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-/* Caller already set message->status; dma and pio irqs are blocked */\r
-static void giveback(struct rk29xx_spi *dws)\r
-{\r
-       struct spi_transfer *last_transfer;\r
-       unsigned long flags;\r
-       struct spi_message *msg;\r
-\r
-       spin_lock_irqsave(&dws->lock, flags);\r
-       msg = dws->cur_msg;\r
-       dws->cur_msg = NULL;\r
-       dws->cur_transfer = NULL;\r
-       dws->prev_chip = dws->cur_chip;\r
-       dws->cur_chip = NULL;\r
-       dws->dma_mapped = 0;\r
-       queue_work(dws->workqueue, &dws->pump_messages);\r
-       spin_unlock_irqrestore(&dws->lock, flags);\r
-\r
-       last_transfer = list_entry(msg->transfers.prev,\r
-                                       struct spi_transfer,\r
-                                       transfer_list);\r
-\r
-       if (!last_transfer->cs_change)\r
-               dws->cs_control(dws,msg->spi->chip_select, MRST_SPI_DEASSERT);\r
-\r
-       msg->state = NULL;\r
-       if (msg->complete)\r
-               msg->complete(msg->context);\r
-}\r
-\r
-static void int_error_stop(struct rk29xx_spi *dws, const char *msg)\r
-{\r
-       /* Stop and reset hw */\r
-       flush(dws);\r
-       spi_enable_chip(dws, 0);\r
-\r
-       dev_err(&dws->master->dev, "%s\n", msg);\r
-       dws->cur_msg->state = ERROR_STATE;\r
-       tasklet_schedule(&dws->pump_transfers);\r
-}\r
-\r
-static void transfer_complete(struct rk29xx_spi *dws)\r
-{\r
-       /* Update total byte transfered return count actual bytes read */\r
-       dws->cur_msg->actual_length += dws->len;\r
-\r
-       /* Move to next transfer */\r
-       dws->cur_msg->state = next_transfer(dws);\r
-\r
-       /* Handle end of message */\r
-       if (dws->cur_msg->state == DONE_STATE) {\r
-               dws->cur_msg->status = 0;\r
-               giveback(dws);\r
-       } else\r
-               tasklet_schedule(&dws->pump_transfers);\r
-}\r
-\r
-static irqreturn_t interrupt_transfer(struct rk29xx_spi *dws)\r
-{\r
-       u16 irq_status, irq_mask = 0x3f;\r
-       u32 int_level = dws->fifo_len / 2;\r
-       u32 left;\r
-       \r
-       irq_status = rk29xx_readw(dws, SPIM_ISR) & irq_mask;\r
-       /* Error handling */\r
-       if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {\r
-               rk29xx_writew(dws, SPIM_ICR, SPI_CLEAR_INT_TXOI | SPI_CLEAR_INT_RXOI | SPI_CLEAR_INT_RXUI);\r
-               int_error_stop(dws, "interrupt_transfer: fifo overrun");\r
-               return IRQ_HANDLED;\r
-       }\r
-\r
-       if (irq_status & SPI_INT_TXEI) {\r
-               spi_mask_intr(dws, SPI_INT_TXEI);\r
-\r
-               left = (dws->tx_end - dws->tx) / dws->n_bytes;\r
-               left = (left > int_level) ? int_level : left;\r
-\r
-               while (left--) {\r
-                       dws->write(dws);\r
-                       wait_till_not_busy(dws);\r
-               }\r
-               dws->read(dws);\r
-\r
-               /* Re-enable the IRQ if there is still data left to tx */\r
-               if (dws->tx_end > dws->tx)\r
-                       spi_umask_intr(dws, SPI_INT_TXEI);\r
-               else\r
-                       transfer_complete(dws);\r
-       }\r
-\r
-       return IRQ_HANDLED;\r
-}\r
-\r
-static irqreturn_t rk29xx_spi_irq(int irq, void *dev_id)\r
-{\r
-       struct rk29xx_spi *dws = dev_id;\r
-\r
-       if (!dws->cur_msg) {\r
-               spi_mask_intr(dws, SPI_INT_TXEI);\r
-               /* Never fail */\r
-               return IRQ_HANDLED;\r
-       }\r
-\r
-       return dws->transfer_handler(dws);\r
-}\r
-\r
-/* Must be called inside pump_transfers() */\r
-static void poll_transfer(struct rk29xx_spi *dws)\r
-{\r
-       while (dws->write(dws)) {\r
-               wait_till_not_busy(dws);\r
-               dws->read(dws);\r
-       }\r
-       transfer_complete(dws);\r
-}\r
-static void spi_chip_sel(struct rk29xx_spi *dws, u16 cs)\r
-{\r
-    if(cs >= dws->master->num_chipselect)\r
-               return;\r
-\r
-       if (dws->cs_control){\r
-           dws->cs_control(dws, cs, 1);\r
-       }\r
-       rk29xx_writel(dws, SPIM_SER, 1 << cs);\r
-}\r
-\r
-static void pump_transfers(unsigned long data)\r
-{\r
-       struct rk29xx_spi *dws = (struct rk29xx_spi *)data;\r
-       struct spi_message *message = NULL;\r
-       struct spi_transfer *transfer = NULL;\r
-       struct spi_transfer *previous = NULL;\r
-       struct spi_device *spi = NULL;\r
-       struct chip_data *chip = NULL;\r
-       u8 bits = 0;\r
-       u8 spi_dfs = 0;\r
-       u8 imask = 0;\r
-       u8 cs_change = 0;\r
-       u16 txint_level = 0;\r
-       u16 clk_div = 0;\r
-       u32 speed = 0;\r
-       u32 cr0 = 0;\r
-\r
-       DBG(KERN_INFO "pump_transfers");\r
-\r
-       /* Get current state information */\r
-       message = dws->cur_msg;\r
-       transfer = dws->cur_transfer;\r
-       chip = dws->cur_chip;\r
-       spi = message->spi;     \r
-       if (unlikely(!chip->clk_div))\r
-               //chip->clk_div = clk_get_rate(dws->clock_spim) / chip->speed_hz;       \r
-           chip->clk_div = 40000000 / chip->speed_hz;  \r
-       if (message->state == ERROR_STATE) {\r
-               message->status = -EIO;\r
-               goto early_exit;\r
-       }\r
-\r
-       /* Handle end of message */\r
-       if (message->state == DONE_STATE) {\r
-               message->status = 0;\r
-               goto early_exit;\r
-       }\r
-\r
-       /* Delay if requested at end of transfer*/\r
-       if (message->state == RUNNING_STATE) {\r
-               previous = list_entry(transfer->transfer_list.prev,\r
-                                       struct spi_transfer,\r
-                                       transfer_list);\r
-               if (previous->delay_usecs)\r
-                       udelay(previous->delay_usecs);\r
-       }\r
-\r
-       dws->n_bytes = chip->n_bytes;\r
-       dws->dma_width = chip->dma_width;\r
-       dws->cs_control = chip->cs_control;\r
-\r
-       dws->rx_dma = transfer->rx_dma;\r
-       dws->tx_dma = transfer->tx_dma;\r
-       dws->tx = (void *)transfer->tx_buf;\r
-       dws->tx_end = dws->tx + transfer->len;\r
-       dws->rx = transfer->rx_buf;\r
-       dws->rx_end = dws->rx + transfer->len;\r
-       dws->write = dws->tx ? chip->write : null_writer;\r
-       dws->read = dws->rx ? chip->read : null_reader;\r
-       dws->cs_change = transfer->cs_change;\r
-       dws->len = dws->cur_transfer->len;\r
-       if (chip != dws->prev_chip)\r
-               cs_change = 1;\r
-\r
-       cr0 = chip->cr0;\r
-\r
-       /* Handle per transfer options for bpw and speed */\r
-       if (transfer->speed_hz) {\r
-               speed = chip->speed_hz;\r
-\r
-               if (transfer->speed_hz != speed) {\r
-                       speed = transfer->speed_hz;\r
-                       if (speed > clk_get_rate(dws->clock_spim)) {\r
-                               dev_err(&dws->master->dev, "MRST SPI0: unsupported"\r
-                                       "freq: %dHz\n", speed);\r
-                               message->status = -EIO;\r
-                               goto early_exit;\r
-                       }\r
-\r
-                       /* clk_div doesn't support odd number */\r
-                       clk_div = clk_get_rate(dws->clock_spim) / speed;\r
-                       clk_div = (clk_div + 1) & 0xfffe;\r
-\r
-                       chip->speed_hz = speed;\r
-                       chip->clk_div = clk_div;\r
-               }\r
-       }\r
-       \r
-       if (transfer->bits_per_word) {\r
-               bits = transfer->bits_per_word;\r
-\r
-               switch (bits) {\r
-               case 8:\r
-                       dws->n_bytes = 1;\r
-                       dws->dma_width = 1;\r
-                       dws->read = (dws->read != null_reader) ?\r
-                                       u8_reader : null_reader;\r
-                       dws->write = (dws->write != null_writer) ?\r
-                                       u8_writer : null_writer;\r
-                       spi_dfs = SPI_DFS_8BIT;\r
-                       break;\r
-               case 16:\r
-                       dws->n_bytes = 2;\r
-                       dws->dma_width = 2;\r
-                       dws->read = (dws->read != null_reader) ?\r
-                                       u16_reader : null_reader;\r
-                       dws->write = (dws->write != null_writer) ?\r
-                                       u16_writer : null_writer;\r
-                       spi_dfs = SPI_DFS_16BIT;\r
-                       break;\r
-               default:\r
-                       dev_err(&dws->master->dev, "MRST SPI0: unsupported bits:"\r
-                               "%db\n", bits);\r
-                       message->status = -EIO;\r
-                       goto early_exit;\r
-               }\r
-\r
-               cr0 = (spi_dfs << SPI_DFS_OFFSET)\r
-                       | (SPI_HALF_WORLD_OFF << SPI_HALF_WORLD_TX_OFFSET)\r
-                       | (SPI_SSN_DELAY_ONE << SPI_SSN_DELAY_OFFSET)\r
-                       | (chip->type << SPI_FRF_OFFSET)\r
-                       | (spi->mode << SPI_MODE_OFFSET)\r
-                       | (chip->tmode << SPI_TMOD_OFFSET);\r
-       }\r
-       message->state = RUNNING_STATE;\r
\r
-       /*\r
-        * Adjust transfer mode if necessary. Requires platform dependent\r
-        * chipselect mechanism.\r
-        */\r
-       if (dws->cs_control) {\r
-               if (dws->rx && dws->tx)\r
-                       chip->tmode = SPI_TMOD_TR;\r
-               else if (dws->rx)\r
-                       chip->tmode = SPI_TMOD_RO;\r
-               else\r
-                       chip->tmode = SPI_TMOD_TO;\r
-\r
-               cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
-               cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
-       } \r
-\r
-       /*\r
-        * Interrupt mode\r
-        * we only need set the TXEI IRQ, as TX/RX always happen syncronizely\r
-        */\r
-       if (!dws->dma_mapped && !chip->poll_mode) {\r
-               int templen = dws->len / dws->n_bytes;\r
-               txint_level = dws->fifo_len / 2;\r
-               txint_level = (templen > txint_level) ? txint_level : templen;\r
-\r
-               imask |= SPI_INT_TXEI;\r
-               dws->transfer_handler = interrupt_transfer;\r
-       }\r
-\r
-       /*\r
-        * Reprogram registers only if\r
-        *      1. chip select changes\r
-        *      2. clk_div is changed\r
-        *      3. control value changes\r
-        */\r
-       if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0 || cs_change || clk_div || imask) {\r
-               spi_enable_chip(dws, 0);\r
-               if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0)\r
-                       rk29xx_writew(dws, SPIM_CTRLR0, cr0);\r
-\r
-               spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);            \r
-               spi_chip_sel(dws, spi->chip_select);\r
-               /* Set the interrupt mask, for poll mode just diable all int */\r
-               spi_mask_intr(dws, 0xff);\r
-               if (imask)\r
-                       spi_umask_intr(dws, imask);\r
-               if (txint_level)\r
-                       rk29xx_writew(dws, SPIM_TXFTLR, txint_level);\r
-\r
-        rk29xx_writew(dws, SPIM_CTRLR1, dws->len-1);\r
-               spi_enable_chip(dws, 1);\r
-               if (cs_change)\r
-                       dws->prev_chip = chip;\r
-       } \r
-\r
-       if (chip->poll_mode)\r
-               poll_transfer(dws);\r
-\r
-       return;\r
-\r
-early_exit:\r
-       giveback(dws);\r
-       return;\r
-}\r
-\r
-static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)\r
-{\r
-       struct spi_message *message = NULL;\r
-       struct spi_transfer *transfer = NULL;\r
-       struct spi_transfer *previous = NULL;\r
-       struct spi_device *spi = NULL;\r
-       struct chip_data *chip = NULL;\r
-       unsigned long val;\r
-       int ms;\r
-       int iRet;\r
-       u8 bits = 0;\r
-       u8 spi_dfs = 0;\r
-       u8 cs_change = 0;\r
-       u16 clk_div = 0;\r
-       u32 speed = 0;\r
-       u32 cr0 = 0;\r
-       u32 dmacr = 0;\r
-\r
-       DBG(KERN_INFO "dma_transfer\n");\r
-\r
-       if (acquire_dma(dws)) {\r
-               dev_err(&dws->master->dev, "acquire dma failed\n");\r
-               goto err_out;\r
-       }\r
-\r
-       if (map_dma_buffers(dws)) {\r
-               dev_err(&dws->master->dev, "acquire dma failed\n");\r
-               goto err_out;\r
-       }\r
-\r
-       /* Get current state information */\r
-       message = dws->cur_msg;\r
-       transfer = dws->cur_transfer;\r
-       chip = dws->cur_chip;\r
-       spi = message->spi;     \r
-       if (unlikely(!chip->clk_div))\r
-               chip->clk_div = 40000000 / chip->speed_hz;      \r
-       if (message->state == ERROR_STATE) {\r
-               message->status = -EIO;\r
-               goto err_out;\r
-       }\r
-\r
-       /* Handle end of message */\r
-       if (message->state == DONE_STATE) {\r
-               message->status = 0;\r
-               goto err_out;\r
-       }\r
-\r
-       /* Delay if requested at end of transfer*/\r
-       if (message->state == RUNNING_STATE) {\r
-               previous = list_entry(transfer->transfer_list.prev,\r
-                                       struct spi_transfer,\r
-                                       transfer_list);\r
-               if (previous->delay_usecs)\r
-                       udelay(previous->delay_usecs);\r
-       }\r
-\r
-       dws->n_bytes = chip->n_bytes;\r
-       dws->dma_width = chip->dma_width;\r
-       dws->cs_control = chip->cs_control;\r
-\r
-       dws->rx_dma = transfer->rx_dma;\r
-       dws->tx_dma = transfer->tx_dma;\r
-       dws->tx = (void *)transfer->tx_buf;\r
-       dws->tx_end = dws->tx + transfer->len;\r
-       dws->rx = transfer->rx_buf;\r
-       dws->rx_end = dws->rx + transfer->len;\r
-       dws->write = dws->tx ? chip->write : null_writer;\r
-       dws->read = dws->rx ? chip->read : null_reader;\r
-       dws->cs_change = transfer->cs_change;\r
-       dws->len = dws->cur_transfer->len;\r
-       if (chip != dws->prev_chip)\r
-               cs_change = 1;\r
-\r
-       cr0 = chip->cr0;\r
-\r
-       /* Handle per transfer options for bpw and speed */\r
-       if (transfer->speed_hz) {\r
-               speed = chip->speed_hz;\r
-\r
-               if (transfer->speed_hz != speed) {\r
-                       speed = transfer->speed_hz;\r
-                       if (speed > clk_get_rate(dws->clock_spim)) {\r
-                               dev_err(&dws->master->dev, "MRST SPI0: unsupported"\r
-                                       "freq: %dHz\n", speed);\r
-                               message->status = -EIO;\r
-                               goto err_out;\r
-                       }\r
-\r
-                       /* clk_div doesn't support odd number */\r
-                       clk_div = clk_get_rate(dws->clock_spim) / speed;\r
-                       clk_div = (clk_div + 1) & 0xfffe;\r
-\r
-                       chip->speed_hz = speed;\r
-                       chip->clk_div = clk_div;\r
-               }\r
-       }\r
-\r
-       if (transfer->bits_per_word) {\r
-               bits = transfer->bits_per_word;\r
-\r
-               switch (bits) {\r
-               case 8:\r
-                       dws->n_bytes = 1;\r
-                       dws->dma_width = 1;\r
-                       spi_dfs = SPI_DFS_8BIT;\r
-                       break;\r
-               case 16:\r
-                       dws->n_bytes = 2;\r
-                       dws->dma_width = 2;\r
-                       spi_dfs = SPI_DFS_16BIT;\r
-                       break;\r
-               default:\r
-                       dev_err(&dws->master->dev, "MRST SPI0: unsupported bits:"\r
-                               "%db\n", bits);\r
-                       message->status = -EIO;\r
-                       goto err_out;\r
-               }\r
-\r
-               cr0 = (spi_dfs << SPI_DFS_OFFSET)\r
-                       | (SPI_HALF_WORLD_OFF << SPI_HALF_WORLD_TX_OFFSET)\r
-                       | (SPI_SSN_DELAY_ONE << SPI_SSN_DELAY_OFFSET)\r
-                       | (chip->type << SPI_FRF_OFFSET)\r
-                       | (spi->mode << SPI_MODE_OFFSET)\r
-                       | (chip->tmode << SPI_TMOD_OFFSET);\r
-       }\r
-       message->state = RUNNING_STATE;\r
\r
-       /*\r
-        * Adjust transfer mode if necessary. Requires platform dependent\r
-        * chipselect mechanism.\r
-        */\r
-       if (dws->cs_control) {\r
-               if (dws->rx && dws->tx)\r
-                       chip->tmode = SPI_TMOD_TR;\r
-               else if (dws->rx)\r
-                       chip->tmode = SPI_TMOD_RO;\r
-               else\r
-                       chip->tmode = SPI_TMOD_TO;\r
-\r
-               cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
-               cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
-       }\r
-\r
-       /*\r
-        * Reprogram registers only if\r
-        *      1. chip select changes\r
-        *      2. clk_div is changed\r
-        *      3. control value changes\r
-        */\r
-       if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0 || cs_change || clk_div) {\r
-               spi_enable_chip(dws, 0);\r
-               if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0) {\r
-                       rk29xx_writew(dws, SPIM_CTRLR0, cr0);\r
-               }\r
-\r
-               spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);            \r
-               spi_chip_sel(dws, spi->chip_select);\r
-               /* Set the interrupt mask, for poll mode just diable all int */\r
-               spi_mask_intr(dws, 0xff);\r
-               \r
-               if (transfer->tx_buf != NULL) {\r
-                       dmacr |= SPI_DMACR_TX_ENABLE;\r
-                       rk29xx_writew(dws, SPIM_DMATDLR, 0);\r
-               }\r
-               if (transfer->rx_buf != NULL) {\r
-                       dmacr |= SPI_DMACR_RX_ENABLE;\r
-                       rk29xx_writew(dws, SPIM_DMARDLR, 0);\r
-                       rk29xx_writew(dws, SPIM_CTRLR1, transfer->len-1);\r
-               }\r
-               rk29xx_writew(dws, SPIM_DMACR, dmacr);\r
-               spi_enable_chip(dws, 1);\r
-               if (cs_change)\r
-                       dws->prev_chip = chip;\r
-       } \r
-\r
-       INIT_COMPLETION(dws->xfer_completion);\r
-       \r
-       if (transfer->tx_buf != NULL) {\r
-               dws->state |= TXBUSY;\r
-               if (rk29_dma_config(dws->tx_dmach, 1)) {\r
-                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
-                       goto err_out;\r
-               }\r
-               \r
-               iRet = rk29_dma_enqueue(dws->tx_dmach, (void *)dws,\r
-                                       transfer->tx_dma, transfer->len);\r
-               if (iRet) {\r
-                       dev_err(&dws->master->dev, "function: %s, line: %d, iRet: %d(dws->tx_dmach: %d, transfer->tx_dma: 0x%x)\n", __FUNCTION__, __LINE__, iRet, \r
-                               dws->tx_dmach, (unsigned int)transfer->tx_dma);\r
-                       goto err_out;\r
-               }\r
-               \r
-               if (rk29_dma_ctrl(dws->tx_dmach, RK29_DMAOP_START)) {\r
-                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
-                       goto err_out;\r
-               }\r
-       }\r
-\r
-       if (transfer->rx_buf != NULL) {\r
-               dws->state |= RXBUSY;\r
-               if (rk29_dma_config(dws->rx_dmach, 1)) {\r
-                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
-                       goto err_out;\r
-               }\r
-               \r
-               iRet = rk29_dma_enqueue(dws->rx_dmach, (void *)dws,\r
-                                       transfer->rx_dma, transfer->len);\r
-               if (iRet) {\r
-                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
-                       goto err_out;\r
-               }\r
-               \r
-               if (rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_START)) {\r
-                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
-                       goto err_out;\r
-               }\r
-       }\r
-\r
-       /* millisecs to xfer 'len' bytes @ 'cur_speed' */\r
-       ms = transfer->len * 8 * 1000 / dws->cur_chip->speed_hz;\r
-       ms += 10; \r
-\r
-       val = msecs_to_jiffies(ms) + 500;\r
-       if (!wait_for_completion_timeout(&dws->xfer_completion, val)) {\r
-               if (transfer->rx_buf != NULL && (dws->state & RXBUSY)) {\r
-                       rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_FLUSH);\r
-                       dws->state &= ~RXBUSY;\r
-                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
-                       goto NEXT_TRANSFER;\r
-               }\r
-               if (transfer->tx_buf != NULL && (dws->state & TXBUSY)) {\r
-                       rk29_dma_ctrl(dws->tx_dmach, RK29_DMAOP_FLUSH);\r
-                       dws->state &= ~TXBUSY;\r
-                       dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
-                       goto NEXT_TRANSFER;\r
-               }\r
-       }\r
-\r
-       wait_till_not_busy(dws);\r
-\r
-NEXT_TRANSFER:\r
-       /* Update total byte transfered return count actual bytes read */\r
-       dws->cur_msg->actual_length += dws->len;\r
-\r
-       /* Move to next transfer */\r
-       dws->cur_msg->state = next_transfer(dws);\r
-\r
-       /* Handle end of message */\r
-       if (dws->cur_msg->state == DONE_STATE) {\r
-               dws->cur_msg->status = 0;\r
-               giveback(dws);\r
-       } else\r
-               dma_transfer(dws);\r
-       \r
-       return;\r
-\r
-err_out:\r
-       giveback(dws);\r
-       return;\r
-\r
-}\r
-\r
-static void pump_messages(struct work_struct *work)\r
-{\r
-       struct rk29xx_spi *dws =\r
-               container_of(work, struct rk29xx_spi, pump_messages);\r
-       unsigned long flags;\r
-\r
-       DBG(KERN_INFO "pump_messages\n");\r
-\r
-       /* Lock queue and check for queue work */\r
-       spin_lock_irqsave(&dws->lock, flags);\r
-       if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {\r
-               dws->busy = 0;\r
-               spin_unlock_irqrestore(&dws->lock, flags);\r
-               return;\r
-       }\r
-\r
-       /* Make sure we are not already running a message */\r
-       if (dws->cur_msg) {\r
-               spin_unlock_irqrestore(&dws->lock, flags);\r
-               return;\r
-       }\r
-\r
-       /* Extract head of queue */\r
-       dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);\r
-       list_del_init(&dws->cur_msg->queue);\r
-\r
-       /* Initial message state*/\r
-       dws->cur_msg->state = START_STATE;\r
-       dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,\r
-                                               struct spi_transfer,\r
-                                               transfer_list);\r
-       dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);\r
-    dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj\r
-    \r
-       /* Mark as busy and launch transfers */\r
-       if(dws->cur_msg->is_dma_mapped && dws->cur_transfer->len > DMA_MIN_BYTES) {\r
-               dws->busy = 1;\r
-           spin_unlock_irqrestore(&dws->lock, flags);\r
-               dma_transfer(dws);\r
-               return;\r
-       }\r
-       else {\r
-               tasklet_schedule(&dws->pump_transfers);\r
-       }\r
-\r
-       dws->busy = 1;\r
-       spin_unlock_irqrestore(&dws->lock, flags);\r
-}\r
-\r
-#if defined(QUICK_TRANSFER)\r
-static void do_read(struct rk29xx_spi *dws)\r
-{\r
-       int count = 0;\r
-\r
-       spi_enable_chip(dws, 0);\r
-       rk29xx_writew(dws, SPIM_CTRLR1, dws->rx_end-dws->rx-1);\r
-       spi_enable_chip(dws, 1);                \r
-       rk29xx_writew(dws, SPIM_TXDR, 0);\r
-       while (1) {\r
-               if (dws->read(dws))\r
-                       break;\r
-               if (count++ == 0x20) {\r
-                       dev_err(&dws->master->dev, "+++++++++++spi receive data time out+++++++++++++\n");\r
-                       break;\r
-               }\r
-               \r
-       }\r
-}\r
-\r
-static void do_write(struct rk29xx_spi *dws)\r
-{\r
-       while (dws->tx<dws->tx_end) {\r
-               dws->write(dws);\r
-       }\r
-}\r
-\r
-/* Caller already set message->status; dma and pio irqs are blocked */\r
-static void msg_giveback(struct rk29xx_spi *dws)\r
-{\r
-       struct spi_transfer *last_transfer;\r
-       struct spi_message *msg;\r
-\r
-       DBG("+++++++++++++++enter %s++++++++++++++++++\n", __func__);\r
-\r
-       msg = dws->cur_msg;\r
-       dws->cur_msg = NULL;\r
-       dws->cur_transfer = NULL;\r
-       dws->prev_chip = dws->cur_chip;\r
-       dws->cur_chip = NULL;\r
-       dws->dma_mapped = 0;\r
-       dws->busy = 0;\r
-\r
-       last_transfer = list_entry(msg->transfers.prev,\r
-                                       struct spi_transfer,\r
-                                       transfer_list);\r
-\r
-       if (!last_transfer->cs_change)\r
-               dws->cs_control(dws,msg->spi->chip_select,MRST_SPI_DEASSERT);\r
-\r
-       msg->state = NULL;      \r
-}\r
-\r
-/* Must be called inside pump_transfers() */\r
-static int do_full_transfer(struct rk29xx_spi *dws)\r
-{\r
-       if ((dws->read(dws))) {\r
-               goto comple;\r
-       }\r
-       \r
-       while (dws->tx<dws->tx_end){\r
-               dws->write(dws);                \r
-               dws->read(dws);\r
-       }\r
-       \r
-       if (dws->rx < dws->rx_end) {\r
-               dws->read(dws);\r
-       }\r
-\r
-comple:\r
-       \r
-       dws->cur_msg->actual_length += dws->len;\r
-       \r
-       /* Move to next transfer */\r
-       dws->cur_msg->state = next_transfer(dws);\r
-                                       \r
-       if (dws->cur_msg->state == DONE_STATE) {\r
-               dws->cur_msg->status = 0;\r
-               //msg_giveback(dws);\r
-               return 0;\r
-       }\r
-       else {\r
-               return -1;\r
-       }\r
-       \r
-}\r
-\r
-\r
-/* Must be called inside pump_transfers() */\r
-static int do_half_transfer(struct rk29xx_spi *dws)\r
-{\r
-       if (dws->rx) {\r
-               if (dws->tx) {\r
-                       do_write(dws);\r
-               }\r
-               wait_till_tf_empty(dws);\r
-               wait_till_not_busy(dws);\r
-               do_read(dws);\r
-       }\r
-       else {\r
-               do_write(dws);\r
-               wait_till_tf_empty(dws);\r
-               wait_till_not_busy(dws);\r
-       }\r
-       \r
-       dws->cur_msg->actual_length += dws->len;\r
-       \r
-       /* Move to next transfer */\r
-       dws->cur_msg->state = next_transfer(dws);\r
-                                       \r
-       if (dws->cur_msg->state == DONE_STATE) {\r
-               dws->cur_msg->status = 0;\r
-               //msg_giveback(dws);\r
-               return 0;\r
-       }\r
-       else {\r
-               return -1;\r
-       }\r
-}\r
-\r
-\r
-static int rk29xx_pump_transfers(struct rk29xx_spi *dws, int mode)\r
-{\r
-       struct spi_message *message = NULL;\r
-       struct spi_transfer *transfer = NULL;\r
-       struct spi_transfer *previous = NULL;\r
-       struct spi_device *spi = NULL;\r
-       struct chip_data *chip = NULL;\r
-       u8 bits = 0;\r
-       u8 spi_dfs = 0;\r
-       u8 cs_change = 0;\r
-       u16 clk_div = 0;\r
-       u32 speed = 0;\r
-       u32 cr0 = 0;\r
-       u32 dmacr = 0;\r
-       \r
-       DBG(KERN_INFO "+++++++++++++++enter %s++++++++++++++++++\n", __func__);\r
-\r
-       /* Get current state information */\r
-       message = dws->cur_msg;\r
-       transfer = dws->cur_transfer;\r
-       chip = dws->cur_chip;\r
-       spi = message->spi;     \r
-\r
-       if (unlikely(!chip->clk_div))\r
-               chip->clk_div = clk_get_rate(dws->clock_spim) / chip->speed_hz;\r
-       if (message->state == ERROR_STATE) {\r
-               message->status = -EIO;\r
-               goto early_exit;\r
-       }\r
-\r
-       /* Handle end of message */\r
-       if (message->state == DONE_STATE) {\r
-               message->status = 0;\r
-               goto early_exit;\r
-       }\r
-\r
-       /* Delay if requested at end of transfer*/\r
-       if (message->state == RUNNING_STATE) {\r
-               previous = list_entry(transfer->transfer_list.prev,\r
-                                       struct spi_transfer,\r
-                                       transfer_list);\r
-               if (previous->delay_usecs)\r
-                       udelay(previous->delay_usecs);\r
-       }\r
-\r
-       dws->n_bytes = chip->n_bytes;\r
-       dws->dma_width = chip->dma_width;\r
-       dws->cs_control = chip->cs_control;\r
-\r
-       dws->rx_dma = transfer->rx_dma;\r
-       dws->tx_dma = transfer->tx_dma;\r
-       dws->tx = (void *)transfer->tx_buf;\r
-       dws->tx_end = dws->tx + transfer->len;\r
-       dws->rx = transfer->rx_buf;\r
-       dws->rx_end = dws->rx + transfer->len;\r
-       dws->write = dws->tx ? chip->write : null_writer;\r
-       dws->read = dws->rx ? chip->read : null_reader;\r
-       if (dws->rx && dws->tx) {\r
-               int temp_len = transfer->len;\r
-               int len;\r
-               unsigned char *tx_buf;\r
-               for (len=0; *tx_buf++ != 0; len++);\r
-               dws->tx_end = dws->tx + len;\r
-               dws->rx_end = dws->rx + temp_len - len;\r
-       }\r
-       dws->cs_change = transfer->cs_change;\r
-       dws->len = dws->cur_transfer->len;\r
-       if (chip != dws->prev_chip)\r
-               cs_change = 1;\r
-\r
-       cr0 = chip->cr0;\r
-\r
-       /* Handle per transfer options for bpw and speed */\r
-       if (transfer->speed_hz) {\r
-               speed = chip->speed_hz;\r
-\r
-               if (transfer->speed_hz != speed) {\r
-                       speed = transfer->speed_hz;\r
-                       if (speed > clk_get_rate(dws->clock_spim)) {\r
-                               dev_err(&dws->master->dev, "MRST SPI0: unsupported"\r
-                                       "freq: %dHz\n", speed);\r
-                               message->status = -EIO;\r
-                               goto early_exit;\r
-                       }\r
-\r
-                       /* clk_div doesn't support odd number */\r
-                       clk_div = clk_get_rate(dws->clock_spim) / speed;\r
-                       clk_div = (clk_div + 1) & 0xfffe;\r
-\r
-                       chip->speed_hz = speed;\r
-                       chip->clk_div = clk_div;\r
-               }\r
-       }\r
-       if (transfer->bits_per_word) {\r
-               bits = transfer->bits_per_word;\r
-\r
-               switch (bits) {\r
-               case 8:\r
-                       dws->n_bytes = 1;\r
-                       dws->dma_width = 1;\r
-                       dws->read = (dws->read != null_reader) ?\r
-                                       u8_reader : null_reader;\r
-                       dws->write = (dws->write != null_writer) ?\r
-                                       u8_writer : null_writer;\r
-                       spi_dfs = SPI_DFS_8BIT;\r
-                       break;\r
-               case 16:\r
-                       dws->n_bytes = 2;\r
-                       dws->dma_width = 2;\r
-                       dws->read = (dws->read != null_reader) ?\r
-                                       u16_reader : null_reader;\r
-                       dws->write = (dws->write != null_writer) ?\r
-                                       u16_writer : null_writer;\r
-                       spi_dfs = SPI_DFS_16BIT;\r
-                       break;\r
-               default:\r
-                       dev_err(&dws->master->dev, "MRST SPI0: unsupported bits:"\r
-                               "%db\n", bits);\r
-                       message->status = -EIO;\r
-                       goto early_exit;\r
-               }\r
-\r
-               cr0 = (spi_dfs << SPI_DFS_OFFSET)\r
-                       | (chip->type << SPI_FRF_OFFSET)\r
-                       | (spi->mode << SPI_MODE_OFFSET)\r
-                       | (chip->tmode << SPI_TMOD_OFFSET);\r
-       }\r
-       message->state = RUNNING_STATE;\r
\r
-       /*\r
-        * Adjust transfer mode if necessary. Requires platform dependent\r
-        * chipselect mechanism.\r
-        */\r
-       if (dws->cs_control) {\r
-               if (dws->rx && dws->tx)\r
-                       chip->tmode = SPI_TMOD_TR;\r
-               else if (dws->rx)\r
-                       chip->tmode = SPI_TMOD_RO;\r
-               else\r
-                       chip->tmode = SPI_TMOD_TO;\r
-\r
-               cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
-               cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
-       }\r
-       \r
-       /* Check if current transfer is a DMA transaction */\r
-       dws->dma_mapped = map_dma_buffers(dws);\r
-\r
-       /*\r
-        * Reprogram registers only if\r
-        *      1. chip select changes\r
-        *      2. clk_div is changed\r
-        *      3. control value changes\r
-        */\r
-       spi_enable_chip(dws, 0);\r
-       if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0)\r
-               rk29xx_writew(dws, SPIM_CTRLR0, cr0);\r
-\r
-    DBG(KERN_INFO "clk_div: 0x%x, chip->clk_div: 0x%x\n", clk_div, chip->clk_div);\r
-       spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);            \r
-       spi_chip_sel(dws, spi->chip_select);            \r
-       rk29xx_writew(dws, SPIM_CTRLR1, 0);//add by lyx\r
-       if(dws->dma_mapped ) {\r
-               dmacr = rk29xx_readw(dws, SPIM_DMACR);\r
-               dmacr = dmacr | SPI_DMACR_TX_ENABLE;\r
-               if (mode) \r
-                       dmacr = dmacr | SPI_DMACR_RX_ENABLE;\r
-               rk29xx_writew(dws, SPIM_DMACR, dmacr);\r
-       }\r
-       spi_enable_chip(dws, 1);\r
-       if (cs_change)\r
-               dws->prev_chip = chip;\r
-       \r
-       if (mode)\r
-               return do_full_transfer(dws);\r
-       else\r
-               return do_half_transfer(dws);   \r
-       \r
-early_exit:\r
-       \r
-       //msg_giveback(dws);\r
-       \r
-       return 0;\r
-}\r
-\r
-static void rk29xx_pump_messages(struct rk29xx_spi *dws, int mode)\r
-{\r
-       DBG(KERN_INFO "+++++++++++++++enter %s++++++++++++++++++\n", __func__);\r
-       \r
-       while (!acquire_dma(dws))\r
-                       msleep(10);\r
-\r
-       if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {\r
-               dws->busy = 0;\r
-               return;\r
-       }\r
-\r
-       /* Make sure we are not already running a message */\r
-       if (dws->cur_msg) {\r
-               return;\r
-       }\r
-\r
-       /* Extract head of queue */\r
-       dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);\r
-       list_del_init(&dws->cur_msg->queue);\r
-\r
-       /* Initial message state*/\r
-       dws->cur_msg->state = START_STATE;\r
-       dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,\r
-                                               struct spi_transfer,\r
-                                               transfer_list);\r
-       dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);\r
-    dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj\r
-    \r
-       /* Mark as busy and launch transfers */\r
-       dws->busy = 1;\r
-\r
-       while (rk29xx_pump_transfers(dws, mode)) ;\r
-}\r
-\r
-/* spi_device use this to queue in their spi_msg */\r
-static int rk29xx_spi_quick_transfer(struct spi_device *spi, struct spi_message *msg)\r
-{\r
-       struct rk29xx_spi *dws = spi_master_get_devdata(spi->master);\r
-       unsigned long flags;\r
-       struct rk29xx_spi_chip *chip_info = spi->controller_data;\r
-       struct spi_message *mmsg;\r
-       \r
-       DBG(KERN_INFO "+++++++++++++++enter %s++++++++++++++++++\n", __func__);\r
-       \r
-       spin_lock_irqsave(&dws->lock, flags);\r
-\r
-       if (dws->run == QUEUE_STOPPED) {\r
-               spin_unlock_irqrestore(&dws->lock, flags);\r
-               return -ESHUTDOWN;\r
-       }\r
-\r
-       msg->actual_length = 0;\r
-       msg->status = -EINPROGRESS;\r
-       msg->state = START_STATE;\r
-\r
-       list_add_tail(&msg->queue, &dws->queue);\r
-\r
-       if (chip_info && (chip_info->transfer_mode == rk29xx_SPI_FULL_DUPLEX)) {\r
-               rk29xx_pump_messages(dws,1);\r
-       }\r
-       else {          \r
-               rk29xx_pump_messages(dws,0);\r
-       }\r
-\r
-       mmsg = dws->cur_msg;\r
-       msg_giveback(dws);\r
-       \r
-       spin_unlock_irqrestore(&dws->lock, flags);\r
-\r
-       if (mmsg->complete)\r
-               mmsg->complete(mmsg->context);\r
-       \r
-       return 0;\r
-}\r
-\r
-#else\r
-\r
-/* spi_device use this to queue in their spi_msg */\r
-static int rk29xx_spi_transfer(struct spi_device *spi, struct spi_message *msg)\r
-{\r
-       struct rk29xx_spi *dws = spi_master_get_devdata(spi->master);\r
-       unsigned long flags;\r
-\r
-       spin_lock_irqsave(&dws->lock, flags);\r
-\r
-       if (dws->run == QUEUE_STOPPED) {\r
-               spin_unlock_irqrestore(&dws->lock, flags);\r
-               return -ESHUTDOWN;\r
-       }\r
-\r
-       msg->actual_length = 0;\r
-       msg->status = -EINPROGRESS;\r
-       msg->state = START_STATE;\r
-\r
-       list_add_tail(&msg->queue, &dws->queue);\r
-\r
-       if (dws->run == QUEUE_RUNNING && !dws->busy) {\r
-\r
-               if (dws->cur_transfer || dws->cur_msg)\r
-                       queue_work(dws->workqueue,\r
-                                       &dws->pump_messages);\r
-               else {\r
-                       /* If no other data transaction in air, just go */\r
-                       spin_unlock_irqrestore(&dws->lock, flags);\r
-                       pump_messages(&dws->pump_messages);\r
-                       return 0;\r
-               }\r
-       }\r
-\r
-       spin_unlock_irqrestore(&dws->lock, flags);\r
-       \r
-       return 0;\r
-}\r
-\r
-#endif\r
-\r
-/* This may be called twice for each spi dev */\r
-static int rk29xx_spi_setup(struct spi_device *spi)\r
-{\r
-       struct rk29xx_spi_chip *chip_info = NULL;\r
-       struct chip_data *chip;\r
-       u8 spi_dfs = 0;\r
-\r
-       if (spi->bits_per_word != 8 && spi->bits_per_word != 16)\r
-               return -EINVAL;\r
-\r
-       /* Only alloc on first setup */\r
-       chip = spi_get_ctldata(spi);\r
-       if (!chip) {\r
-               chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);\r
-               if (!chip)\r
-                       return -ENOMEM;\r
-\r
-               chip->cs_control = NULL;\r
-               chip->enable_dma = 1;  //0;\r
-       }\r
-\r
-       /*\r
-        * Protocol drivers may change the chip settings, so...\r
-        * if chip_info exists, use it\r
-        */\r
-       chip_info = spi->controller_data;\r
-\r
-       /* chip_info doesn't always exist */\r
-       if (chip_info) {\r
-               if (chip_info->cs_control)\r
-                       chip->cs_control = chip_info->cs_control;\r
-\r
-               chip->poll_mode = chip_info->poll_mode;\r
-               chip->type = chip_info->type;\r
-\r
-               chip->rx_threshold = 0;\r
-               chip->tx_threshold = 0;\r
-\r
-               chip->enable_dma = chip_info->enable_dma;\r
-       }\r
-\r
-       if (spi->bits_per_word == 8) {\r
-               chip->n_bytes = 1;\r
-               chip->dma_width = 1;\r
-               chip->read = u8_reader;\r
-               chip->write = u8_writer;\r
-               spi_dfs = SPI_DFS_8BIT;\r
-       } else if (spi->bits_per_word == 16) {\r
-               chip->n_bytes = 2;\r
-               chip->dma_width = 2;\r
-               chip->read = u16_reader;\r
-               chip->write = u16_writer;\r
-               spi_dfs = SPI_DFS_16BIT;\r
-       } else {\r
-               /* Never take >16b case for MRST SPIC */\r
-               dev_err(&spi->dev, "invalid wordsize\n");\r
-               return -EINVAL;\r
-       }\r
-       chip->bits_per_word = spi->bits_per_word;\r
-\r
-       if (!spi->max_speed_hz) {\r
-               dev_err(&spi->dev, "No max speed HZ parameter\n");\r
-               return -EINVAL;\r
-       }\r
-       chip->speed_hz = spi->max_speed_hz;\r
-\r
-       chip->tmode = 0; /* Tx & Rx */\r
-       /* Default SPI mode is SCPOL = 0, SCPH = 0 */\r
-       chip->cr0 = (spi_dfs << SPI_DFS_OFFSET)\r
-               | (SPI_HALF_WORLD_OFF << SPI_HALF_WORLD_TX_OFFSET)\r
-                       | (SPI_SSN_DELAY_ONE << SPI_SSN_DELAY_OFFSET)\r
-                       | (chip->type << SPI_FRF_OFFSET)\r
-                       | (spi->mode  << SPI_MODE_OFFSET)\r
-                       | (chip->tmode << SPI_TMOD_OFFSET);\r
-\r
-       spi_set_ctldata(spi, chip);\r
-       return 0;\r
-}\r
-\r
-static void rk29xx_spi_cleanup(struct spi_device *spi)\r
-{\r
-       struct chip_data *chip = spi_get_ctldata(spi);\r
-       kfree(chip);\r
-}\r
-\r
-static int __devinit init_queue(struct rk29xx_spi *dws)\r
-{\r
-       INIT_LIST_HEAD(&dws->queue);\r
-       spin_lock_init(&dws->lock);\r
-\r
-       dws->run = QUEUE_STOPPED;\r
-       dws->busy = 0;\r
-\r
-       init_completion(&dws->xfer_completion);\r
-\r
-       tasklet_init(&dws->pump_transfers,\r
-                       pump_transfers, (unsigned long)dws);\r
-\r
-       INIT_WORK(&dws->pump_messages, pump_messages);\r
-       dws->workqueue = create_singlethread_workqueue(\r
-                                       dev_name(dws->master->dev.parent));\r
-       if (dws->workqueue == NULL)\r
-               return -EBUSY;\r
-\r
-       return 0;\r
-}\r
-\r
-static int start_queue(struct rk29xx_spi *dws)\r
-{\r
-       unsigned long flags;\r
-\r
-       spin_lock_irqsave(&dws->lock, flags);\r
-\r
-       if (dws->run == QUEUE_RUNNING || dws->busy) {\r
-               spin_unlock_irqrestore(&dws->lock, flags);\r
-               return -EBUSY;\r
-       }\r
-\r
-       dws->run = QUEUE_RUNNING;\r
-       dws->cur_msg = NULL;\r
-       dws->cur_transfer = NULL;\r
-       dws->cur_chip = NULL;\r
-       dws->prev_chip = NULL;\r
-       spin_unlock_irqrestore(&dws->lock, flags);\r
-\r
-       queue_work(dws->workqueue, &dws->pump_messages);\r
-\r
-       return 0;\r
-}\r
-\r
-static int stop_queue(struct rk29xx_spi *dws)\r
-{\r
-       unsigned long flags;\r
-       unsigned limit = 50;\r
-       int status = 0;\r
-\r
-       spin_lock_irqsave(&dws->lock, flags);\r
-       dws->run = QUEUE_STOPPED;\r
-       while (!list_empty(&dws->queue) && dws->busy && limit--) {\r
-               spin_unlock_irqrestore(&dws->lock, flags);\r
-               msleep(10);\r
-               spin_lock_irqsave(&dws->lock, flags);\r
-       }\r
-\r
-       if (!list_empty(&dws->queue) || dws->busy)\r
-               status = -EBUSY;\r
-       spin_unlock_irqrestore(&dws->lock, flags);\r
-\r
-       return status;\r
-}\r
-\r
-static int destroy_queue(struct rk29xx_spi *dws)\r
-{\r
-       int status;\r
-\r
-       status = stop_queue(dws);\r
-       if (status != 0)\r
-               return status;\r
-       destroy_workqueue(dws->workqueue);\r
-       return 0;\r
-}\r
-\r
-/* Restart the controller, disable all interrupts, clean rx fifo */\r
-static void spi_hw_init(struct rk29xx_spi *dws)\r
-{\r
-       spi_enable_chip(dws, 0);\r
-       spi_mask_intr(dws, 0xff);\r
-       spi_enable_chip(dws, 1);\r
-       flush(dws);\r
-\r
-       /*\r
-        * Try to detect the FIFO depth if not set by interface driver,\r
-        * the depth could be from 2 to 32 from HW spec\r
-        */\r
-       if (!dws->fifo_len) {\r
-               u32 fifo;\r
-               for (fifo = 2; fifo <= 31; fifo++) {\r
-                       rk29xx_writew(dws, SPIM_TXFTLR, fifo);\r
-                       if (fifo != rk29xx_readw(dws, SPIM_TXFTLR))\r
-                               break;\r
-               }\r
-\r
-               dws->fifo_len = (fifo == 31) ? 0 : fifo;\r
-               rk29xx_writew(dws, SPIM_TXFTLR, 0);\r
-       }\r
-}\r
-\r
-/* cpufreq driver support */\r
-#ifdef CONFIG_CPU_FREQ\r
-\r
-static int rk29xx_spim_cpufreq_transition(struct notifier_block *nb, unsigned long val, void *data)\r
-{\r
-        struct rk29xx_spi *info;\r
-        unsigned long newclk;\r
-\r
-        info = container_of(nb, struct rk29xx_spi, freq_transition);\r
-        newclk = clk_get_rate(info->clock_spim);\r
-\r
-        return 0;\r
-}\r
-\r
-static inline int rk29xx_spim_cpufreq_register(struct rk29xx_spi *info)\r
-{\r
-        info->freq_transition.notifier_call = rk29xx_spim_cpufreq_transition;\r
-\r
-        return cpufreq_register_notifier(&info->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);\r
-}\r
-\r
-static inline void rk29xx_spim_cpufreq_deregister(struct rk29xx_spi *info)\r
-{\r
-        cpufreq_unregister_notifier(&info->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);\r
-}\r
-\r
-#else\r
-static inline int rk29xx_spim_cpufreq_register(struct rk29xx_spi *info)\r
-{\r
-        return 0;\r
-}\r
-\r
-static inline void rk29xx_spim_cpufreq_deregister(struct rk29xx_spi *info)\r
-{\r
-}\r
-#endif\r
-static int __init rk29xx_spim_probe(struct platform_device *pdev)\r
-{\r
-       struct resource         *regs, *dmatx_res, *dmarx_res;\r
-       struct rk29xx_spi   *dws;\r
-       struct spi_master   *master;\r
-       int                     irq; \r
-       int ret;\r
-       struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data;\r
-       char szBuf[8];\r
-\r
-       if (pdata && pdata->io_init) {\r
-               ret = pdata->io_init(pdata->chipselect_gpios, pdata->num_chipselect);\r
-               if (ret) {                      \r
-                       return -ENXIO;  \r
-               }\r
-       }\r
-       \r
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
-       if (!regs)\r
-               return -ENXIO;\r
-       dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);\r
-       if (dmatx_res == NULL) {\r
-               dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");\r
-               return -ENXIO;\r
-       }\r
-\r
-       dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);\r
-       if (dmarx_res == NULL) {\r
-               dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");\r
-               return -ENXIO;\r
-       }\r
-       irq = platform_get_irq(pdev, 0);\r
-       if (irq < 0)\r
-               return irq;                     \r
-       /* setup spi core then atmel-specific driver state */\r
-       ret = -ENOMEM;  \r
-       master = spi_alloc_master(&pdev->dev, sizeof *dws);\r
-       if (!master) {\r
-               ret = -ENOMEM;\r
-               goto exit;\r
-       }\r
-\r
-       platform_set_drvdata(pdev, master);\r
-       dws = spi_master_get_devdata(master);\r
-       memset(szBuf, 0, sizeof(szBuf));\r
-       sprintf(szBuf, "%s%d", "spi", pdev->id);\r
-    dws->clock_spim = clk_get(&pdev->dev, szBuf);\r
-       clk_enable(dws->clock_spim);\r
-       if (IS_ERR(dws->clock_spim)) {\r
-               dev_err(&pdev->dev, "clk_get for %s fail(%p)\n", szBuf, dws->clock_spim);\r
-               return PTR_ERR(dws->clock_spim);\r
-       }\r
-       \r
-       dws->regs = ioremap(regs->start, (regs->end - regs->start) + 1);\r
-       if (!dws->regs){\r
-       release_mem_region(regs->start, (regs->end - regs->start) + 1);\r
-               return -EBUSY;\r
-       }\r
-       DBG(KERN_INFO "dws->regs: %p\n", dws->regs);\r
-    dws->irq = irq;\r
-       dws->irq_polarity = IRQF_TRIGGER_NONE;\r
-       dws->master = master;\r
-       dws->type = SSI_MOTO_SPI;\r
-       dws->prev_chip = NULL;\r
-       dws->sfr_start = regs->start;\r
-       dws->tx_dmach = dmatx_res->start;\r
-       dws->rx_dmach = dmarx_res->start;\r
-       dws->dma_inited = 0;  ///0;\r
-       ///dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);\r
-       ret = request_irq(dws->irq, rk29xx_spi_irq, dws->irq_polarity,\r
-                       "rk29xx_spim", dws);\r
-       if (ret < 0) {\r
-               dev_err(&master->dev, "can not get IRQ\n");\r
-               goto err_free_master;\r
-       }\r
-\r
-       master->mode_bits = SPI_CPOL | SPI_CPHA;\r
-       master->bus_num = pdev->id;\r
-       master->num_chipselect = pdata->num_chipselect;\r
-       master->dev.platform_data = pdata;\r
-       master->cleanup = rk29xx_spi_cleanup;\r
-       master->setup = rk29xx_spi_setup;\r
-       #if defined(QUICK_TRANSFER)\r
-       master->transfer = rk29xx_spi_quick_transfer;\r
-       #else\r
-       master->transfer = rk29xx_spi_transfer;\r
-       #endif\r
-       \r
-       dws->pdev = pdev;\r
-       /* Basic HW init */\r
-       spi_hw_init(dws);\r
-       /* Initial and start queue */\r
-       ret = init_queue(dws);\r
-       if (ret) {\r
-               dev_err(&master->dev, "problem initializing queue\n");\r
-               goto err_diable_hw;\r
-       }\r
-\r
-       ret = start_queue(dws);\r
-       if (ret) {\r
-               dev_err(&master->dev, "problem starting queue\n");\r
-               goto err_diable_hw;\r
-       }\r
-\r
-       spi_master_set_devdata(master, dws);\r
-       ret = spi_register_master(master);\r
-       if (ret) {\r
-               dev_err(&master->dev, "problem registering spi master\n");\r
-               goto err_queue_alloc;\r
-       }\r
-\r
-    ret =rk29xx_spim_cpufreq_register(dws);\r
-    if (ret < 0) {\r
-        dev_err(&master->dev, "rk29xx spim failed to init cpufreq support\n");\r
-        goto err_queue_alloc;\r
-    }\r
-       DBG(KERN_INFO "rk29xx_spim: driver initialized\n");\r
-       mrst_spi_debugfs_init(dws);\r
-       return 0;\r
-\r
-err_queue_alloc:\r
-       destroy_queue(dws);\r
-err_diable_hw:\r
-       spi_enable_chip(dws, 0);\r
-       free_irq(dws->irq, dws);\r
-err_free_master:\r
-       spi_master_put(master);\r
-       iounmap(dws->regs);\r
-exit:\r
-       return ret;\r
-}\r
-\r
-static void __exit rk29xx_spim_remove(struct platform_device *pdev)\r
-{\r
-       struct spi_master *master = platform_get_drvdata(pdev);\r
-       struct rk29xx_spi *dws = spi_master_get_devdata(master);\r
-       int status = 0;\r
-\r
-       if (!dws)\r
-               return;\r
-       rk29xx_spim_cpufreq_deregister(dws);\r
-       mrst_spi_debugfs_remove(dws);\r
-\r
-       release_dma(dws);\r
-\r
-       /* Remove the queue */\r
-       status = destroy_queue(dws);\r
-       if (status != 0)\r
-               dev_err(&dws->master->dev, "rk29xx_spi_remove: workqueue will not "\r
-                       "complete, message memory not freed\n");\r
-       clk_put(dws->clock_spim);\r
-       clk_disable(dws->clock_spim);\r
-       spi_enable_chip(dws, 0);\r
-       /* Disable clk */\r
-       spi_set_clk(dws, 0);\r
-       free_irq(dws->irq, dws);\r
-\r
-       /* Disconnect from the SPI framework */\r
-       spi_unregister_master(dws->master);\r
-       iounmap(dws->regs);\r
-}\r
-\r
-\r
-#ifdef CONFIG_PM\r
-\r
-static int rk29xx_spim_suspend(struct platform_device *pdev, pm_message_t mesg)\r
-{\r
-       struct spi_master *master = platform_get_drvdata(pdev);\r
-       struct rk29xx_spi *dws = spi_master_get_devdata(master);\r
-       struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data;\r
-       int status;\r
-\r
-       status = stop_queue(dws);\r
-       if (status != 0)\r
-               return status;\r
-       clk_disable(dws->clock_spim);\r
-       if (pdata && pdata->io_fix_leakage_bug)\r
-       {\r
-               pdata->io_fix_leakage_bug( );\r
-       }\r
-       return 0;\r
-}\r
-\r
-static int rk29xx_spim_resume(struct platform_device *pdev)\r
-{\r
-       struct spi_master *master = platform_get_drvdata(pdev);\r
-       struct rk29xx_spi *dws = spi_master_get_devdata(master);\r
-       struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data;\r
-       int ret;\r
-       \r
-       clk_enable(dws->clock_spim);    \r
-       spi_hw_init(dws);\r
-       ret = start_queue(dws);\r
-       if (ret)\r
-               dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);\r
-       if (pdata && pdata->io_resume_leakage_bug)\r
-       {\r
-               pdata->io_resume_leakage_bug( ); \r
-       }\r
-       return ret;\r
-}\r
-\r
-#else\r
-#define        rk29xx_spim_suspend     NULL\r
-#define        rk29xx_spim_resume      NULL\r
-#endif\r
-\r
-static struct platform_driver rk29xx_platform_spim_driver = {\r
-       .remove         = __exit_p(rk29xx_spim_remove),\r
-       .driver         = {\r
-               .name   = "rk29xx_spim",\r
-               .owner  = THIS_MODULE,\r
-       },\r
-       .suspend        = rk29xx_spim_suspend,\r
-       .resume         = rk29xx_spim_resume,\r
-};\r
-\r
-static int __init rk29xx_spim_init(void)\r
-{\r
-       int ret;\r
-       ret = platform_driver_probe(&rk29xx_platform_spim_driver, rk29xx_spim_probe);   \r
-       return ret;\r
-}\r
-\r
-static void __exit rk29xx_spim_exit(void)\r
-{\r
-       platform_driver_unregister(&rk29xx_platform_spim_driver);\r
-}\r
-\r
-subsys_initcall(rk29xx_spim_init);\r
-module_exit(rk29xx_spim_exit);\r
-\r
-MODULE_AUTHOR("www.rock-chips.com");\r
-MODULE_DESCRIPTION("Rockchip RK29xx spim port driver");\r
-MODULE_LICENSE("GPL");;\r
-\r
diff --git a/drivers/spi/rk29xx_spim.h b/drivers/spi/rk29xx_spim.h
deleted file mode 100755 (executable)
index fb3ab62..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/* drivers/spi/rk29xx_spim.h\r
- *\r
- * Copyright (C) 2010 ROCKCHIP, Inc.\r
- *\r
- * This software is licensed under the terms of the GNU General Public\r
- * License version 2, as published by the Free Software Foundation, and\r
- * may be copied, distributed, and modified under those terms.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- */\r
-#ifndef __DRIVERS_SPIM_RK29XX_HEADER_H\r
-#define __DRIVERS_SPIM_RK29XX_HEADER_H\r
-#include <linux/io.h>\r
-#include <mach/rk29-dma-pl330.h>\r
-\r
-/* SPI register offsets */\r
-#define SPIM_CTRLR0                            0x0000\r
-#define SPIM_CTRLR1                            0x0004\r
-#define SPIM_ENR                               0x0008\r
-#define SPIM_SER                               0x000c\r
-#define SPIM_BAUDR                             0x0010\r
-#define SPIM_TXFTLR                            0x0014\r
-#define SPIM_RXFTLR                            0x0018\r
-#define SPIM_TXFLR                             0x001c\r
-#define SPIM_RXFLR                             0x0020\r
-#define SPIM_SR                                        0x0024\r
-#define SPIM_IPR                0x0028\r
-#define SPIM_IMR                               0x002c\r
-#define SPIM_ISR                               0x0030\r
-#define SPIM_RISR                              0x0034\r
-#define SPIM_ICR                               0x0038\r
-#define SPIM_DMACR                             0x003c\r
-#define SPIM_DMATDLR                   0x0040\r
-#define SPIM_DMARDLR                   0x0044\r
-#define SPIM_TXDR                              0x0400\r
-#define SPIM_RXDR               0x0800\r
-\r
-/* --------Bit fields in CTRLR0--------begin */\r
-\r
-#define SPI_DFS_OFFSET                 0                  /* Data Frame Size */\r
-#define SPI_DFS_4BIT            0x00\r
-#define SPI_DFS_8BIT            0x01\r
-#define SPI_DFS_16BIT           0x02\r
-#define SPI_DFS_RESV            0x03\r
-\r
-#define SPI_FRF_OFFSET                 16                 /* Frame Format */\r
-#define SPI_FRF_SPI                        0x00               /* motorola spi */\r
-#define SPI_FRF_SSP                        0x01               /* Texas Instruments SSP*/\r
-#define SPI_FRF_MICROWIRE              0x02               /*  National Semiconductors Microwire */\r
-#define SPI_FRF_RESV                   0x03\r
-\r
-#define SPI_MODE_OFFSET                    6                 /* SCPH & SCOL */\r
-\r
-#define SPI_SCPH_OFFSET                        6                  /* Serial Clock Phase */\r
-#define SPI_SCPH_TOGMID         0                  /* Serial clock toggles in middle of first data bit */\r
-#define SPI_SCPH_TOGSTA         1                  /* Serial clock toggles at start of first data bit */\r
-\r
-#define SPI_SCOL_OFFSET                        7                  /* Serial Clock Polarity */\r
-\r
-#define SPI_TMOD_OFFSET                        18                 /* Transfer Mode */\r
-#define        SPI_TMOD_TR                         0x00                       /* xmit & recv */\r
-#define SPI_TMOD_TO                        0x01                       /* xmit only */\r
-#define SPI_TMOD_RO                        0x02                       /* recv only */\r
-#define SPI_TMOD_RESV              0x03\r
-\r
-#define SPI_CFS_OFFSET                 2                  /* Control Frame Size */\r
-\r
-#define SPI_CSM_OFFSET          8                  /* Chip Select Mode */\r
-#define SPI_CSM_KEEP            0x00               /* ss_n keep low after every frame data is transferred */\r
-#define SPI_CSM_HALF            0x01               /* ss_n be high for half sclk_out cycles after every frame data is transferred */\r
-#define SPI_CSM_ONE             0x02               /* ss_n be high for one sclk_out cycle after every frame data is transferred */\r
-\r
-#define SPI_SSN_DELAY_OFFSET    10\r
-#define SPI_SSN_DELAY_HALF      0x00\r
-#define SPI_SSN_DELAY_ONE       0x01\r
-\r
-#define SPI_HALF_WORLD_TX_OFFSET       13\r
-#define SPI_HALF_WORLD_ON       0x00\r
-#define SPI_HALF_WORLD_OFF      0x01\r
-\r
-\r
-/* --------Bit fields in CTRLR0--------end */\r
-\r
-\r
-/* Bit fields in SR, 7 bits */\r
-#define SR_MASK                                0x7f            /* cover 7 bits */\r
-#define SR_BUSY                                (1 << 0)\r
-#define SR_TF_FULL                 (1 << 1)\r
-#define SR_TF_EMPT                     (1 << 2)\r
-#define SR_RF_EMPT                 (1 << 3)\r
-#define SR_RF_FULL                     (1 << 4)\r
-\r
-/* Bit fields in ISR, IMR, RISR, 7 bits */\r
-#define SPI_INT_TXEI                   (1 << 0)\r
-#define SPI_INT_TXOI                   (1 << 1)\r
-#define SPI_INT_RXUI                   (1 << 2)\r
-#define SPI_INT_RXOI                   (1 << 3)\r
-#define SPI_INT_RXFI                   (1 << 4)\r
-\r
-/* Bit fields in DMACR */\r
-#define SPI_DMACR_TX_ENABLE     (1 << 1)\r
-#define SPI_DMACR_RX_ENABLE     (1 << 0)\r
-\r
-/* Bit fields in ICR */\r
-#define SPI_CLEAR_INT_ALL       (1<< 0)\r
-#define SPI_CLEAR_INT_RXUI      (1 << 1)\r
-#define SPI_CLEAR_INT_RXOI      (1 << 2)\r
-#define SPI_CLEAR_INT_TXOI      (1 << 3)\r
-\r
-enum rk29xx_ssi_type {\r
-       SSI_MOTO_SPI = 0,\r
-       SSI_TI_SSP,\r
-       SSI_NS_MICROWIRE,\r
-};\r
-\r
-struct rk29xx_spi {\r
-       struct spi_master       *master;\r
-       struct spi_device       *cur_dev;\r
-       enum rk29xx_ssi_type    type;\r
-\r
-       void __iomem            *regs;\r
-       unsigned long           paddr;\r
-       u32                     iolen;\r
-       int                     irq;\r
-       u32         irq_polarity;\r
-       u32                     fifo_len;       /* depth of the FIFO buffer */\r
-       struct clk              *clock_spim;    /* clk apb */\r
-       struct platform_device  *pdev;\r
-       \r
-       /* Driver message queue */\r
-       struct workqueue_struct *workqueue;\r
-       struct work_struct      pump_messages;\r
-       spinlock_t              lock;\r
-       struct list_head        queue;\r
-       int                     busy;\r
-       int                     run;\r
-\r
-       /* Message Transfer pump */\r
-       struct tasklet_struct   pump_transfers;\r
-\r
-       /* Current message transfer state info */\r
-       struct spi_message      *cur_msg;\r
-       struct spi_transfer     *cur_transfer;\r
-       struct chip_data        *cur_chip;\r
-       struct chip_data        *prev_chip;\r
-       size_t                  len;\r
-       void                    *tx;\r
-       void                    *tx_end;\r
-       void                    *rx;\r
-       void                    *rx_end;\r
-       int                     dma_mapped;\r
-       dma_addr_t              rx_dma;\r
-       dma_addr_t              tx_dma;\r
-       size_t                  rx_map_len;\r
-       size_t                  tx_map_len;\r
-       u8                      n_bytes;        /* current is a 1/2 bytes op */\r
-       u8                      max_bits_per_word;      /* maxim is 16b */\r
-       u32                     dma_width;\r
-       int                     cs_change;\r
-       int                     (*write)(struct rk29xx_spi *dws);\r
-       int                     (*read)(struct rk29xx_spi *dws);\r
-       irqreturn_t             (*transfer_handler)(struct rk29xx_spi *dws);\r
-       void (*cs_control)(struct rk29xx_spi *dws, u32 cs, u8 flag);\r
-\r
-       /* Dma info */\r
-       struct completion               xfer_completion;\r
-       unsigned    state;\r
-       unsigned                        cur_speed;\r
-       unsigned long                   sfr_start;\r
-       int                     dma_inited;\r
-       enum dma_ch rx_dmach;\r
-       enum dma_ch tx_dmach;\r
-       int                     txdma_done;\r
-       int                     rxdma_done;\r
-       u64                     tx_param;\r
-       u64                     rx_param;\r
-       struct device           *dma_dev;\r
-       dma_addr_t              dma_addr;\r
-\r
-       /* Bus interface info */\r
-       void                    *priv;\r
-#ifdef CONFIG_DEBUG_FS\r
-       struct dentry *debugfs;\r
-#endif\r
-#ifdef CONFIG_CPU_FREQ\r
-        struct notifier_block   freq_transition;\r
-#endif\r
-};\r
-\r
-#define rk29xx_readl(dw, off) \\r
-       __raw_readl(dw->regs + off)\r
-#define rk29xx_writel(dw,off,val) \\r
-       __raw_writel(val, dw->regs + off)\r
-#define rk29xx_readw(dw, off) \\r
-       __raw_readw(dw->regs + off)\r
-#define rk29xx_writew(dw,off,val) \\r
-       __raw_writel(val, dw->regs + off)\r
-\r
-static inline void spi_enable_chip(struct rk29xx_spi *dws, int enable)\r
-{\r
-       rk29xx_writel(dws, SPIM_ENR, (enable ? 1 : 0));\r
-}\r
-\r
-static inline void spi_set_clk(struct rk29xx_spi *dws, u16 div)\r
-{\r
-       rk29xx_writel(dws, SPIM_BAUDR, div);\r
-}\r
-\r
-/* Disable IRQ bits */\r
-static inline void spi_mask_intr(struct rk29xx_spi *dws, u32 mask)\r
-{\r
-       u32 new_mask;\r
-\r
-       new_mask = rk29xx_readl(dws, SPIM_IMR) & ~mask;\r
-       rk29xx_writel(dws, SPIM_IMR, new_mask);\r
-}\r
-\r
-/* Enable IRQ bits */\r
-static inline void spi_umask_intr(struct rk29xx_spi *dws, u32 mask)\r
-{\r
-       u32 new_mask;\r
-\r
-       new_mask = rk29xx_readl(dws, SPIM_IMR) | mask;\r
-       rk29xx_writel(dws, SPIM_IMR, new_mask);\r
-}\r
-\r
-//spi transfer mode                   add by lyx\r
-#define rk29xx_SPI_HALF_DUPLEX 0\r
-#define rk29xx_SPI_FULL_DUPLEX 1\r
-\r
-/*\r
- * Each SPI slave device to work with rk29xx spi controller should\r
- * has such a structure claiming its working mode (PIO/DMA etc),\r
- * which can be save in the "controller_data" member of the\r
- * struct spi_device\r
- */\r
-struct rk29xx_spi_chip {\r
-       u8 transfer_mode;/*full or half duplex*/\r
-       u8 poll_mode;   /* 0 for contoller polling mode */\r
-       u8 type;        /* SPI/SSP/Micrwire */\r
-       u8 enable_dma;\r
-       void (*cs_control)(struct rk29xx_spi *dws, u32 cs, u8 flag);\r
-};\r
-\r
-#endif /* __DRIVERS_SPIM_RK29XX_HEADER_H */\r