rk30:fix spim dma transfer bug and enable dma mode of td8803
authorlw@rock-chips.com <lw@rock-chips.com>
Wed, 16 May 2012 09:15:16 +0000 (17:15 +0800)
committerlw <lw@rock-chips.com>
Wed, 16 May 2012 09:15:52 +0000 (17:15 +0800)
arch/arm/mach-rk30/board-rk30-phone-loquat.c
drivers/spi/rk29_spim.c
drivers/spi/rk29_spim.h

index b971944747855a1a5d70d765ff9b1aeb933b7b40..6dd35d7afc864b6ba3110bdb5a2cfecbd88f21a0 100755 (executable)
@@ -781,7 +781,7 @@ static struct plat_sc8800 sc8800_plat_data = {
 };
 static struct rk29xx_spi_chip sc8800_spi_chip = {
        //.poll_mode = 1,
-       .enable_dma = 0,
+       .enable_dma = 1,
 };
 
 #endif
index 04331a242b1e1cde18a024e4926ad1a0d9dce308..8fca6a8042976e6d7ff3f62ec67df05012401ee4 100755 (executable)
@@ -40,9 +40,9 @@ QUICK_TRANSFER
 */\r
 \r
 //#define QUICK_TRANSFER         \r
-\r
 #if 0\r
 #define DBG   printk\r
+//#define PRINT_TRANS_DATA\r
 #else\r
 #define DBG(x...)\r
 #endif\r
@@ -129,6 +129,17 @@ void rk29_lcd_spim_spin_unlock(void)
 }\r
 #endif\r
 \r
+#if defined(PRINT_TRANS_DATA)\r
+static void printk_transfer_data(unsigned char *buf, int len)\r
+{\r
+       int i = 0;\r
+       for(i=0; i<len; i++)\r
+               printk("0x%x,",*buf++);\r
+\r
+       printk("\n");\r
+\r
+}\r
+#endif\r
 \r
 static void spi_dump_regs(struct rk29xx_spi *dws) {\r
        DBG("MRST SPI0 registers:\n");\r
@@ -337,8 +348,10 @@ static int null_reader(struct rk29xx_spi *dws)
 \r
 static int u8_writer(struct rk29xx_spi *dws)\r
 {      \r
-       spi_dump_regs(dws);\r
+       //spi_dump_regs(dws)\r
+#if defined(PRINT_TRANS_DATA)\r
        DBG("tx: 0x%02x\n", *(u8 *)(dws->tx));\r
+#endif\r
        if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
                || (dws->tx == dws->tx_end))\r
                return 0;\r
@@ -351,11 +364,13 @@ static int u8_writer(struct rk29xx_spi *dws)
 \r
 static int u8_reader(struct rk29xx_spi *dws)\r
 {\r
-    spi_dump_regs(dws);\r
+    //spi_dump_regs(dws);\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
+#if defined(PRINT_TRANS_DATA)\r
                DBG("rx: 0x%02x\n", *(u8 *)(dws->rx));\r
+#endif\r
                ++dws->rx;\r
        }\r
 \r
@@ -364,7 +379,10 @@ static int u8_reader(struct rk29xx_spi *dws)
 }\r
 \r
 static int u16_writer(struct rk29xx_spi *dws)\r
-{\r
+{      \r
+#if defined(PRINT_TRANS_DATA)\r
+       DBG("tx: 0x%04x\n", *(u16 *)(dws->tx));\r
+#endif\r
        if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
                || (dws->tx == dws->tx_end))\r
                return 0;\r
@@ -384,7 +402,9 @@ static int u16_reader(struct rk29xx_spi *dws)
                && (dws->rx < dws->rx_end)) {\r
                temp = rk29xx_readw(dws, SPIM_RXDR);\r
                *(u16 *)(dws->rx) = temp;\r
-               //DBG("rx: 0x%04x\n", *(u16 *)(dws->rx));\r
+#if defined(PRINT_TRANS_DATA)\r
+               DBG("rx: 0x%04x\n", *(u16 *)(dws->rx));\r
+#endif\r
                dws->rx += 2;\r
        }\r
 \r
@@ -421,16 +441,29 @@ static void rk29_spi_dma_rxcb(void *buf_id,
        if (res == RK29_RES_OK)\r
                dws->state &= ~RXBUSY;\r
        else\r
-               dev_err(&dws->master->dev, "DmaAbrtRx-%d, size: %d,res=%d\n", res, size,res);\r
+               dev_err(&dws->master->dev, "error:DmaAbrtRx-%d, size: %d,res=%d\n", res, size,res);\r
 \r
-       /* If the other done */\r
-       //if (!(dws->state & TXBUSY))\r
-       //      complete(&dws->rx_completion);\r
+       //copy data from dma to transfer buf\r
+       if(dws->cur_transfer && (dws->cur_transfer->rx_buf != NULL))\r
+       {\r
+               memcpy(dws->cur_transfer->rx_buf, dws->buffer_rx_dma, dws->cur_transfer->len);\r
+               \r
+               #if defined(PRINT_TRANS_DATA)\r
+               printk("dma rx:");\r
+               printk_transfer_data(dws->cur_transfer->rx_buf, dws->cur_transfer->len);\r
+               #endif\r
+       }\r
        \r
        spin_unlock_irqrestore(&dws->lock, flags);\r
        \r
-       //DMA could not lose intterupt\r
-       transfer_complete(dws);\r
+       /* If the other done */\r
+       if (!(dws->state & TXBUSY))\r
+       {\r
+               //complete(&dws->xfer_completion);      \r
+               DBG("func: %s, line: %d,dma transfer complete\n", __FUNCTION__, __LINE__);\r
+               //DMA could not lose intterupt\r
+               transfer_complete(dws);\r
+       }\r
 \r
 }\r
 \r
@@ -447,16 +480,19 @@ static void rk29_spi_dma_txcb(void *buf_id,
        if (res == RK29_RES_OK)\r
                dws->state &= ~TXBUSY;\r
        else\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->tx_completion);\r
+               dev_err(&dws->master->dev, "error:DmaAbrtTx-%d, size: %d,res=%d \n", res, size,res);\r
 \r
        spin_unlock_irqrestore(&dws->lock, flags);\r
        \r
-       //DMA could not lose intterupt\r
-       transfer_complete(dws);\r
+       /* If the other done */\r
+       if (!(dws->state & RXBUSY)) \r
+       {\r
+               //complete(&dws->xfer_completion);\r
+               \r
+               DBG("func: %s, line: %d,dma transfer complete\n", __FUNCTION__, __LINE__);\r
+               //DMA could not lose intterupt\r
+               transfer_complete(dws);\r
+       }\r
 \r
 }\r
 \r
@@ -550,13 +586,6 @@ static int map_dma_buffers(struct rk29xx_spi *dws)
        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
@@ -581,7 +610,7 @@ static void giveback(struct rk29xx_spi *dws)
        dws->dma_mapped = 0;\r
        \r
        /*it is important to close intterrupt*/\r
-       spi_umask_intr(dws, 0);\r
+       spi_mask_intr(dws, 0xff);\r
        rk29xx_writew(dws, SPIM_DMACR, 0);\r
        \r
        queue_work(dws->workqueue, &dws->pump_messages);\r
@@ -598,6 +627,8 @@ static void giveback(struct rk29xx_spi *dws)
        if (msg->complete)\r
                msg->complete(msg->context);\r
 \r
+       DBG("%s ok\n",__func__);\r
+\r
 }\r
 \r
 static void int_error_stop(struct rk29xx_spi *dws, const char *msg)\r
@@ -701,7 +732,9 @@ 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
+#if defined(PRINT_TRANS_DATA)\r
        DBG("%s\n",__func__);\r
+#endif\r
        while (dws->write(dws)) {\r
                wait_till_not_busy(dws);\r
                dws->read(dws);\r
@@ -797,7 +830,7 @@ static void pump_transfers(unsigned long data)
                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
+                               dev_err(&dws->master->dev, "MRST SPI0: unsupported "\r
                                        "freq: %dHz\n", speed);\r
                                message->status = -EIO;\r
                                goto early_exit;\r
@@ -862,7 +895,8 @@ static void pump_transfers(unsigned long data)
                else\r
                        chip->tmode = SPI_TMOD_TO;\r
 \r
-               cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
+               cr0 &= ~(0x3 << SPI_MODE_OFFSET);               \r
+               cr0 &= ~(0x3 << SPI_TMOD_OFFSET);\r
                cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
        } \r
 \r
@@ -894,10 +928,10 @@ static void pump_transfers(unsigned long data)
         *      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
+       if ((rk29xx_readl(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
+               if (rk29xx_readl(dws, SPIM_CTRLR0) != cr0)\r
+                       rk29xx_writel(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
@@ -1012,7 +1046,7 @@ static void dma_transfer(struct rk29xx_spi *dws)
                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
+                               dev_err(&dws->master->dev, "MRST SPI0: unsupported "\r
                                        "freq: %dHz\n", speed);\r
                                message->status = -EIO;\r
                                goto err_out;\r
@@ -1071,6 +1105,7 @@ static void dma_transfer(struct rk29xx_spi *dws)
                        chip->tmode = SPI_TMOD_TO;\r
 \r
                cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
+               cr0 &= ~(0x3 << SPI_TMOD_OFFSET);\r
                cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
        }\r
 \r
@@ -1080,12 +1115,11 @@ static void dma_transfer(struct rk29xx_spi *dws)
         *      2. clk_div is changed\r
         *      3. control value changes\r
         */\r
-       if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0 || cs_change || clk_div) {\r
+       if ((rk29xx_readl(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
+               if (rk29xx_readl(dws, SPIM_CTRLR0) != cr0) {\r
+                       rk29xx_writel(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
@@ -1098,7 +1132,7 @@ static void dma_transfer(struct rk29xx_spi *dws)
                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
+                       rk29xx_writew(dws, SPIM_CTRLR1, transfer->len-1);       \r
                }\r
                rk29xx_writew(dws, SPIM_DMACR, dmacr);\r
                spi_enable_chip(dws, 1);\r
@@ -1108,10 +1142,22 @@ static void dma_transfer(struct rk29xx_spi *dws)
 \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
-       if (transfer->tx_buf != NULL) {\r
-               dws->state |= TXBUSY;\r
+       //spi_dump_regs(dws);\r
+       \r
+       DBG("dws->tx_dmach: %d, dws->rx_dmach: %d, dws->tx_dma: 0x%x,dws->rx_dma: 0x%x\n", dws->tx_dmach, dws->rx_dmach, (unsigned int)dws->tx_dma,(unsigned int)dws->rx_dma);  \r
+       DBG("dws->buffer_tx_dma: 0x%p, dws->buffer_rx_dma: 0x%p,dws->dma_width=%d\n", dws->buffer_tx_dma, dws->buffer_rx_dma,dws->dma_width);   \r
+\r
+       if (transfer->tx_buf != NULL)           \r
+               dws->state |= TXBUSY;   \r
+       if (transfer->rx_buf != NULL) \r
+               dws->state |= RXBUSY;\r
+\r
+       if (transfer->tx_buf != NULL) { \r
+               DBG("%s:start dma tx,dws->state=0x%x\n",__func__,dws->state);\r
+               #if defined(PRINT_TRANS_DATA)\r
+               printk("dma tx:");\r
+               printk_transfer_data(dws->buffer_tx_dma, dws->cur_transfer->len);\r
+               #endif\r
                /*if (transfer->len & 0x3) {\r
                        burst = 1;\r
                }\r
@@ -1119,7 +1165,7 @@ static void dma_transfer(struct rk29xx_spi *dws)
                        burst = 4;\r
                }\r
                if (rk29_dma_config(dws->tx_dmach, burst)) {*/\r
-               if (rk29_dma_config(dws->tx_dmach, 1, 1)) {//there is not dma burst but bitwide, set it 1 alwayss\r
+               if (rk29_dma_config(dws->tx_dmach, dws->dma_width, 1)) {//there is not dma burst but bitwide, set it 1 alwayss\r
                        dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
                        goto err_out;\r
                }\r
@@ -1127,7 +1173,7 @@ static void dma_transfer(struct rk29xx_spi *dws)
                rk29_dma_ctrl(dws->tx_dmach, RK29_DMAOP_FLUSH); \r
                \r
                iRet = rk29_dma_enqueue(dws->tx_dmach, (void *)dws,\r
-                                       transfer->tx_dma, transfer->len);\r
+                                       dws->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
@@ -1142,9 +1188,9 @@ static void dma_transfer(struct rk29xx_spi *dws)
 \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
+       if (transfer->rx_buf != NULL) {                 \r
+               DBG("%s:start dma rx,dws->state=0x%x\n",__func__,dws->state);\r
+               if (rk29_dma_config(dws->rx_dmach, dws->dma_width, 1)) {\r
                        dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
                        goto err_out;\r
                }\r
@@ -1152,7 +1198,7 @@ static void dma_transfer(struct rk29xx_spi *dws)
                rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_FLUSH); \r
                \r
                iRet = rk29_dma_enqueue(dws->rx_dmach, (void *)dws,\r
-                                       transfer->rx_dma, transfer->len);\r
+                                       dws->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
@@ -1164,6 +1210,8 @@ static void dma_transfer(struct rk29xx_spi *dws)
                }\r
        }\r
        \r
+       //wait_till_not_busy(dws);\r
+       \r
        return;\r
 \r
 err_out:\r
@@ -1178,21 +1226,21 @@ static void pump_messages(struct work_struct *work)
                container_of(work, struct rk29xx_spi, pump_messages);\r
        unsigned long flags;\r
 \r
-       DBG(KERN_INFO "pump_messages\n");\r
+       DBG(KERN_INFO "pump_messages,line=%d\n",__LINE__);\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
+               DBG("%s:line=%d,list_empty\n",__func__,__LINE__);\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
+               spin_unlock_irqrestore(&dws->lock, flags);              \r
+               DBG("%s:line=%d,dws->cur_msg\n",__func__,__LINE__);\r
                return;\r
        }\r
 \r
@@ -1208,6 +1256,7 @@ static void pump_messages(struct work_struct *work)
        dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);\r
        dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj\r
 \r
+       \r
        /* Mark as busy and launch transfers */\r
        tasklet_schedule(&dws->pump_transfers);\r
        dws->busy = 1;\r
@@ -1491,8 +1540,8 @@ static int rk29xx_pump_transfers(struct rk29xx_spi *dws, int mode)
         *      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
+       if (rk29xx_readl(dws, SPIM_CTRLR0) != cr0)\r
+               rk29xx_writel(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
@@ -1912,6 +1961,9 @@ 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
+       dws->pclk = clk_get(&pdev->dev, "pclk_spi");\r
+       clk_enable(dws->pclk);\r
        \r
        mutex_init(&dws->dma_lock);\r
        \r
@@ -2017,8 +2069,11 @@ static void __exit rk29xx_spim_remove(struct platform_device *pdev)
        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
+       \r
        clk_disable(dws->clock_spim);\r
+       clk_put(dws->clock_spim);\r
+       clk_disable(dws->pclk);\r
+       clk_put(dws->pclk);\r
        spi_enable_chip(dws, 0);\r
        /* Disable clk */\r
        spi_set_clk(dws, 0);\r
@@ -2048,6 +2103,7 @@ static int rk29xx_spim_suspend(struct platform_device *pdev, pm_message_t mesg)
        {\r
                pdata->io_fix_leakage_bug( );\r
        }\r
+       clk_disable(dws->pclk);\r
        return 0;\r
 }\r
 \r
@@ -2057,7 +2113,8 @@ static int rk29xx_spim_resume(struct platform_device *pdev)
        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
+\r
+       clk_enable(dws->pclk);\r
        clk_enable(dws->clock_spim);    \r
        spi_hw_init(dws);\r
        ret = start_queue(dws);\r
index 6c396abfacb7d0e4371882dd1d740ad8a60c42ac..d417bc8ce94644cf5e8394dc89c193c69378beae 100755 (executable)
@@ -132,6 +132,7 @@ struct rk29xx_spi {
        u32         irq_polarity;\r
        u32                     fifo_len;       /* depth of the FIFO buffer */\r
        struct clk              *clock_spim;    /* clk apb */\r
+       struct clk              *pclk;\r
        struct platform_device  *pdev;\r
        \r
        /* Driver message queue */\r