add dma support for spim driver
authorlw <lw@rock-chips.com>
Fri, 17 Feb 2012 07:26:18 +0000 (15:26 +0800)
committerlw <lw@rock-chips.com>
Fri, 17 Feb 2012 07:26:18 +0000 (15:26 +0800)
arch/arm/mach-rk30/board-rk30-sdk.c
arch/arm/mach-rk30/devices.c
drivers/input/touchscreen/xpt2046_ts.h
drivers/spi/rk29_spim.c
drivers/spi/rk29_spim.h

index 1ed255ab2091ab4e96dea39fede8c94c3e79b1c3..e1c4b1ea21b75eb90445751ba96ad0e91040b410 100755 (executable)
@@ -45,6 +45,9 @@
 #elif defined(CONFIG_TOUCHSCREEN_XPT2046_CBN_SPI)
 #include "../../../drivers/input/touchscreen/xpt2046_cbn_ts.h"
 #endif
+#if defined(CONFIG_SPIM_RK29)
+#include "../../../drivers/spi/rk29_spim.h"
+#endif
 
 
 /*****************************************************************************************
@@ -141,7 +144,12 @@ static struct xpt2046_platform_data xpt2046_info = {
 #endif 
 };
 #endif
-
+#if defined(CONFIG_TOUCHSCREEN_XPT2046_SPI)
+static struct rk29xx_spi_chip xpt2046_chip = {
+       //.poll_mode = 1,
+       .enable_dma = 1,
+};
+#endif
 static struct spi_board_info board_spi_devices[] = {
 #if defined(CONFIG_TOUCHSCREEN_XPT2046_SPI)
        {
@@ -151,6 +159,7 @@ static struct spi_board_info board_spi_devices[] = {
                .bus_num        = 0,
                .irq            = XPT2046_GPIO_INT,
                .platform_data = &xpt2046_info,
+               .controller_data = &xpt2046_chip,
        },
 #endif
 
index f587b07398257e87e7b1a4d5b076414340642d63..ac3be39e6c32627c38ec75667616bd067f61d7a6 100755 (executable)
@@ -615,6 +615,8 @@ struct platform_device rk29xx_device_spi0m = {
        .num_resources  = ARRAY_SIZE(rk29_spi0_resources),
        .resource       = rk29_spi0_resources,
        .dev                    = {
+               .dma_mask = &dma_dmamask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data  = &rk29xx_spi0_platdata,
        },
 };
@@ -650,6 +652,8 @@ struct platform_device rk29xx_device_spi1m = {
        .num_resources  = ARRAY_SIZE(rk29_spi1_resources),
        .resource       = rk29_spi1_resources,
        .dev                    = {
+               .dma_mask = &dma_dmamask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data  = &rk29xx_spi1_platdata,
        },
 };
index 3c3b90f2bbf95c634177d217dfdceb0cec0d2e94..1a04afec62d4f1f5bd35bd4e8a3925a3366b0a18 100755 (executable)
@@ -16,7 +16,7 @@
 #ifndef __DRIVERS_TOUCHSCREEN_XPT2046_TS_H
 #define __DRIVERS_TOUCHSCREEN_XPT2046_TS_H
 
-#define IOMUX_NAME_SIZE 20
+#define IOMUX_NAME_SIZE 40
 
 enum xpt2046_filter {
        XPT2046_FILTER_OK,
index a74996db72134f4f335a8e0d98c1cc08a6e5aa55..8b3dfd300d7cf6cf14dc5043b01747066b80b496 100755 (executable)
@@ -47,7 +47,8 @@ QUICK_TRANSFER
 #define DBG(x...)\r
 #endif\r
 \r
-#define DMA_MIN_BYTES 8\r
+#define DMA_BUFFER_SIZE PAGE_SIZE\r
+#define DMA_MIN_BYTES 32 //>32x16bits FIFO\r
 \r
 \r
 #define START_STATE    ((void *)0)\r
@@ -249,6 +250,9 @@ static inline void mrst_spi_debugfs_remove(struct rk29xx_spi *dws)
 }\r
 #endif /* CONFIG_DEBUG_FS */\r
 \r
+static void dma_transfer(struct rk29xx_spi *dws) ;\r
+static void transfer_complete(struct rk29xx_spi *dws);\r
+\r
 static void wait_till_not_busy(struct rk29xx_spi *dws)\r
 {\r
        unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);\r
@@ -410,16 +414,21 @@ static void rk29_spi_dma_rxcb(void *buf_id,
        struct rk29xx_spi *dws = buf_id;\r
        unsigned long flags;\r
 \r
+       DBG("func: %s, line: %d\n", __FUNCTION__, __LINE__);\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
+               dev_err(&dws->master->dev, "DmaAbrtRx-%d, size: %d,res=%d\n", res, size,res);\r
 \r
        /* If the other done */\r
-       if (!(dws->state & TXBUSY))\r
-               complete(&dws->xfer_completion);\r
+       //if (!(dws->state & TXBUSY))\r
+       //      complete(&dws->rx_completion);\r
+       \r
+       //DMA could not lose intterupt\r
+       transfer_complete(dws);\r
 \r
        spin_unlock_irqrestore(&dws->lock, flags);\r
 }\r
@@ -431,17 +440,20 @@ static void rk29_spi_dma_txcb(void *buf_id,
        unsigned long flags;\r
 \r
        DBG("func: %s, line: %d\n", __FUNCTION__, __LINE__);\r
-\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, size: %d \n", res, size);\r
+               dev_err(&dws->master->dev, "DmaAbrtTx-%d, size: %d,res=%d \n", res, size,res);\r
 \r
        /* If the other done */\r
-       if (!(dws->state & RXBUSY)) \r
-               complete(&dws->xfer_completion);\r
+       //if (!(dws->state & RXBUSY)) \r
+       //      complete(&dws->tx_completion);\r
+\r
+       //DMA could not lose intterupt\r
+       transfer_complete(dws);\r
 \r
        spin_unlock_irqrestore(&dws->lock, flags);\r
 }\r
@@ -469,8 +481,32 @@ static int acquire_dma(struct rk29xx_spi *dws)
                rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client);\r
                return -1;\r
        }\r
+\r
+       if (dws->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
+                                       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->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
+                                       dws->sfr_start + SPIM_RXDR)) {\r
+                       dev_err(&dws->master->dev, "rk29_dma_devconfig fail\n");\r
+                       return -1;\r
+               }\r
+       }\r
        \r
-    dws->dma_inited = 1;\r
+       dws->dma_inited = 1;\r
        return 0;\r
 }\r
 \r
@@ -489,36 +525,27 @@ static void release_dma(struct rk29xx_spi *dws)
  */\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
+       if (!dws->dma_inited || !dws->cur_chip->enable_dma)\r
+       {\r
+               printk("%s:error\n",__func__);\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
-                                       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
-                                       dws->sfr_start + SPIM_RXDR)) {\r
-                       dev_err(&dws->master->dev, "rk29_dma_devconfig fail\n");\r
-                       return -1;\r
-               }\r
+       if(dws->cur_transfer->tx_buf)\r
+       {\r
+               memcpy(dws->buffer_tx_dma,dws->cur_transfer->tx_buf,dws->cur_transfer->len);\r
+               dws->cur_transfer->tx_buf = dws->buffer_tx_dma; \r
        }\r
 \r
+       if(dws->cur_transfer->rx_buf)\r
+       {\r
+               //memcpy(dws->buffer_rx_dma,dws->cur_transfer->rx_buf,dws->cur_transfer->len);\r
+               dws->cur_transfer->rx_buf = dws->buffer_rx_dma; \r
+       }\r
+       \r
+       dws->cur_transfer->tx_dma = dws->tx_dma;\r
+       dws->cur_transfer->rx_dma = dws->rx_dma;\r
+       \r
        return 0;\r
 }\r
 \r
@@ -536,6 +563,11 @@ static void giveback(struct rk29xx_spi *dws)
        dws->prev_chip = dws->cur_chip;\r
        dws->cur_chip = NULL;\r
        dws->dma_mapped = 0;\r
+       \r
+       /*it is important to close intterrupt*/\r
+       spi_umask_intr(dws, 0);\r
+       rk29xx_writew(dws, SPIM_DMACR, 0);\r
+       \r
        queue_work(dws->workqueue, &dws->pump_messages);\r
        spin_unlock_irqrestore(&dws->lock, flags);\r
 \r
@@ -549,6 +581,7 @@ static void giveback(struct rk29xx_spi *dws)
        msg->state = NULL;\r
        if (msg->complete)\r
                msg->complete(msg->context);\r
+\r
 }\r
 \r
 static void int_error_stop(struct rk29xx_spi *dws, const char *msg)\r
@@ -583,12 +616,13 @@ static irqreturn_t interrupt_transfer(struct rk29xx_spi *dws)
        u16 irq_status, irq_mask = 0x1f;\r
        u32 int_level = dws->fifo_len / 2;\r
        u32 left;\r
-       \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
+               mutex_unlock(&dws->dma_lock);   \r
                return IRQ_HANDLED;\r
        }\r
 \r
@@ -629,7 +663,8 @@ static irqreturn_t interrupt_transfer(struct rk29xx_spi *dws)
                else {\r
                        transfer_complete(dws);\r
                }\r
-       }\r
+               \r
+       }       \r
 \r
        return IRQ_HANDLED;\r
 }\r
@@ -650,6 +685,7 @@ static irqreturn_t rk29xx_spi_irq(int irq, void *dev_id)
 /* Must be called inside pump_transfers() */\r
 static void poll_transfer(struct rk29xx_spi *dws)\r
 {\r
+       DBG("%s\n",__func__);\r
        while (dws->write(dws)) {\r
                wait_till_not_busy(dws);\r
                dws->read(dws);\r
@@ -685,7 +721,12 @@ static void pump_transfers(unsigned long data)
        u32 speed = 0;\r
        u32 cr0 = 0;\r
 \r
-       DBG(KERN_INFO "pump_transfers\n");\r
+       if((dws->cur_chip->enable_dma) && (dws->cur_transfer->len > DMA_MIN_BYTES) && (dws->cur_transfer->len < DMA_BUFFER_SIZE)){      \r
+               dma_transfer(dws);\r
+               return;\r
+       }       \r
+       \r
+       DBG(KERN_INFO "pump_transfers,len=%d\n",dws->cur_transfer->len);\r
 \r
        /* Get current state information */\r
        message = dws->cur_msg;\r
@@ -718,11 +759,11 @@ static void pump_transfers(unsigned long data)
        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->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 = (void *)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
@@ -813,7 +854,7 @@ static void pump_transfers(unsigned long data)
         * 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
+       if (!dws->dma_mapped && !chip->poll_mode) {     \r
                int templen ;\r
                \r
                if (chip->tmode == SPI_TMOD_RO) {\r
@@ -871,17 +912,18 @@ early_exit:
        return;\r
 }\r
 \r
-static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)\r
+static void dma_transfer(struct rk29xx_spi *dws) \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
+       //unsigned long val;    \r
+       //unsigned long flags;\r
+       //int ms;\r
        int iRet;\r
-       int burst;\r
+       //int burst;\r
        u8 bits = 0;\r
        u8 spi_dfs = 0;\r
        u8 cs_change = 0;\r
@@ -889,9 +931,9 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
        u32 speed = 0;\r
        u32 cr0 = 0;\r
        u32 dmacr = 0;\r
-\r
-       DBG(KERN_INFO "dma_transfer\n");\r
-\r
+       \r
+       DBG(KERN_INFO "dma_transfer,len=%d\n",dws->cur_transfer->len);  \r
+       \r
        if (acquire_dma(dws)) {\r
                dev_err(&dws->master->dev, "acquire dma failed\n");\r
                goto err_out;\r
@@ -933,11 +975,11 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
        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->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 = (void *)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
@@ -947,11 +989,10 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
                cs_change = 1;\r
 \r
        cr0 = chip->cr0;\r
-\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
@@ -970,6 +1011,7 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
                }\r
        }\r
 \r
+       \r
        if (transfer->bits_per_word) {\r
                bits = transfer->bits_per_word;\r
 \r
@@ -1048,7 +1090,7 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
                        dws->prev_chip = chip;\r
        } \r
 \r
-       INIT_COMPLETION(dws->xfer_completion);\r
+       //INIT_COMPLETION(dws->xfer_completion);\r
 \r
        spi_dump_regs(dws);\r
        DBG("dws->tx_dmach: %d, dws->rx_dmach: %d, transfer->tx_dma: 0x%x\n", dws->tx_dmach, dws->rx_dmach, (unsigned int)transfer->tx_dma);\r
@@ -1082,8 +1124,8 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
                }\r
        }\r
 \r
-       wait_till_not_busy(dws);\r
-\r
+       //wait_till_not_busy(dws);\r
+       \r
        if (transfer->rx_buf != NULL) {\r
                dws->state |= RXBUSY;\r
                if (rk29_dma_config(dws->rx_dmach, 1, 1)) {\r
@@ -1105,42 +1147,6 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
                        goto err_out;\r
                }\r
        }\r
-\r
-       /* millisecs to xfer 'len' bytes @ 'cur_speed' */\r
-       ms = transfer->len * 8 / dws->cur_chip->speed_hz;\r
-       ms += 10; \r
-\r
-       val = msecs_to_jiffies(ms) + 10;\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
@@ -1157,18 +1163,20 @@ static void pump_messages(struct work_struct *work)
        unsigned long flags;\r
 \r
        DBG(KERN_INFO "pump_messages\n");\r
-\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
+               mutex_unlock(&dws->dma_lock);\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
+               mutex_unlock(&dws->dma_lock);\r
                return;\r
        }\r
 \r
@@ -1182,21 +1190,13 @@ static void pump_messages(struct work_struct *work)
                                                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
+       dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj\r
 \r
+       /* Mark as busy and launch transfers */\r
+       tasklet_schedule(&dws->pump_transfers);\r
        dws->busy = 1;\r
        spin_unlock_irqrestore(&dws->lock, flags);\r
+       \r
 }\r
 \r
 #if defined(QUICK_TRANSFER)\r
@@ -1610,7 +1610,7 @@ static int rk29xx_spi_transfer(struct spi_device *spi, struct spi_message *msg)
                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
+                       pump_messages(&dws->pump_messages);                     \r
                        return 0;\r
                }\r
        }\r
@@ -1726,6 +1726,7 @@ static int __devinit init_queue(struct rk29xx_spi *dws)
        if (dws->workqueue == NULL)\r
                return -EBUSY;\r
 \r
+\r
        return 0;\r
 }\r
 \r
@@ -1895,6 +1896,23 @@ static int __init rk29xx_spim_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "clk_get for spi fail(%p)\n", dws->clock_spim);\r
                return PTR_ERR(dws->clock_spim);\r
        }\r
+\r
+       \r
+       dws->buffer_tx_dma = dma_alloc_coherent(&pdev->dev, DMA_BUFFER_SIZE, &dws->tx_dma, GFP_KERNEL | GFP_DMA);\r
+       if (!dws->buffer_tx_dma)\r
+       {\r
+               dev_err(&pdev->dev, "fail to dma tx buffer alloc\n");\r
+               goto exit;\r
+       }\r
+\r
+       dws->buffer_rx_dma = dma_alloc_coherent(&pdev->dev, DMA_BUFFER_SIZE, &dws->rx_dma, GFP_KERNEL | GFP_DMA);\r
+       if (!dws->buffer_rx_dma)\r
+       {\r
+               dev_err(&pdev->dev, "fail to dma rx buffer alloc\n");\r
+               goto exit;\r
+       }\r
+       \r
+       mutex_init(&dws->dma_lock);\r
        \r
        dws->regs = ioremap(regs->start, (regs->end - regs->start) + 1);\r
        if (!dws->regs){\r
@@ -1971,6 +1989,8 @@ err_diable_hw:
        free_irq(dws->irq, dws);\r
 err_free_master:\r
        spi_master_put(master);\r
+       dma_free_coherent(&pdev->dev, DMA_BUFFER_SIZE, dws->buffer_tx_dma, dws->tx_dma);        \r
+       dma_free_coherent(&pdev->dev, DMA_BUFFER_SIZE, dws->buffer_rx_dma, dws->rx_dma);\r
        iounmap(dws->regs);\r
 exit:\r
        return ret;\r
@@ -1987,6 +2007,9 @@ static void __exit rk29xx_spim_remove(struct platform_device *pdev)
        rk29xx_spim_cpufreq_deregister(dws);\r
        mrst_spi_debugfs_remove(dws);\r
 \r
+       \r
+       dma_free_coherent(&pdev->dev, DMA_BUFFER_SIZE, dws->buffer_tx_dma, dws->tx_dma);        \r
+       dma_free_coherent(&pdev->dev, DMA_BUFFER_SIZE, dws->buffer_rx_dma, dws->rx_dma);\r
        release_dma(dws);\r
 \r
        /* Remove the queue */\r
index 6ac3853150389c7a538c7f961a3fa44112edfee8..6c396abfacb7d0e4371882dd1d740ad8a60c42ac 100755 (executable)
@@ -137,13 +137,15 @@ struct rk29xx_spi {
        /* Driver message queue */\r
        struct workqueue_struct *workqueue;\r
        struct work_struct      pump_messages;\r
-       spinlock_t              lock;\r
+       spinlock_t              lock;   \r
+       struct mutex            dma_lock;\r
        struct list_head        queue;\r
        int                     busy;\r
        int                     run;\r
 \r
        /* Message Transfer pump */\r
-       struct tasklet_struct   pump_transfers;\r
+       struct tasklet_struct   pump_transfers; \r
+       struct tasklet_struct   dma_transfers;  \r
 \r
        /* Current message transfer state info */\r
        struct spi_message      *cur_msg;\r
@@ -158,6 +160,8 @@ struct rk29xx_spi {
        int                     dma_mapped;\r
        dma_addr_t              rx_dma;\r
        dma_addr_t              tx_dma;\r
+       void                    *buffer_tx_dma;\r
+       void                    *buffer_rx_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
@@ -171,6 +175,9 @@ struct rk29xx_spi {
 \r
        /* Dma info */\r
        struct completion               xfer_completion;\r
+       \r
+       struct completion               tx_completion;\r
+       struct completion               rx_completion;\r
        unsigned    state;\r
        unsigned                        cur_speed;\r
        unsigned long                   sfr_start;\r