fix interrupt recv bug for spi
authorcmc <cmc@rock-chips.com>
Fri, 17 Dec 2010 02:48:56 +0000 (10:48 +0800)
committercmc <cmc@rock-chips.com>
Fri, 17 Dec 2010 02:48:56 +0000 (10:48 +0800)
drivers/spi/rk29_spim.c

index b2ffd2ca1605e2ee6f0d0801a52d47e3c378365f..1227e6e836ff16ba332978f2b74862ccec6b083e 100755 (executable)
@@ -40,7 +40,7 @@ QUICK_TRANSFER
 \r
 //#define QUICK_TRANSFER         \r
 \r
-#if 1\r
+#if 0\r
 #define DBG   printk\r
 #else\r
 #define DBG(x...)\r
@@ -274,6 +274,7 @@ static int null_writer(struct rk29xx_spi *dws)
 static int null_reader(struct rk29xx_spi *dws)\r
 {\r
        u8 n_bytes = dws->n_bytes;\r
+       DBG("func: %s, line: %d\n", __FUNCTION__, __LINE__);\r
        while ((!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT))\r
                && (dws->rx < dws->rx_end)) {\r
                rk29xx_readw(dws, SPIM_RXDR);\r
@@ -299,9 +300,11 @@ static int u8_writer(struct rk29xx_spi *dws)
 \r
 static int u8_reader(struct rk29xx_spi *dws)\r
 {\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
+               DBG("rx: 0x%02x\n", *(u8 *)(dws->rx));\r
                ++dws->rx;\r
        }\r
 \r
@@ -330,6 +333,7 @@ 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
                dws->rx += 2;\r
        }\r
 \r
@@ -551,7 +555,9 @@ static irqreturn_t interrupt_transfer(struct rk29xx_spi *dws)
                        dws->write(dws);\r
                        wait_till_not_busy(dws);\r
                }\r
-               dws->read(dws);\r
+               if (dws->rx) {\r
+                   dws->read(dws);\r
+               }\r
 \r
                /* Re-enable the IRQ if there is still data left to tx */\r
                if (dws->tx_end > dws->tx)\r
@@ -560,6 +566,24 @@ static irqreturn_t interrupt_transfer(struct rk29xx_spi *dws)
                        transfer_complete(dws);\r
        }\r
 \r
+       if (irq_status & SPI_INT_RXFI) {\r
+               spi_mask_intr(dws, SPI_INT_RXFI);\r
+               \r
+               dws->read(dws);\r
+\r
+               /* Re-enable the IRQ if there is still data left to rx */\r
+               if (dws->rx_end > dws->rx) {\r
+                       left = ((dws->rx_end - dws->rx) / dws->n_bytes) - 1;\r
+                   left = (left > int_level) ? int_level : left;\r
+\r
+                       rk29xx_writew(dws, SPIM_RXFTLR, left);\r
+                       spi_umask_intr(dws, SPI_INT_RXFI);\r
+               }\r
+               else {\r
+                       transfer_complete(dws);\r
+               }\r
+       }\r
+\r
        return IRQ_HANDLED;\r
 }\r
 \r
@@ -609,11 +633,12 @@ static void pump_transfers(unsigned long data)
        u8 imask = 0;\r
        u8 cs_change = 0;\r
        u16 txint_level = 0;\r
+       u16 rxint_level = 0;\r
        u16 clk_div = 0;\r
        u32 speed = 0;\r
        u32 cr0 = 0;\r
 \r
-       DBG(KERN_INFO "pump_transfers");\r
+       DBG(KERN_INFO "pump_transfers\n");\r
 \r
        /* Get current state information */\r
        message = dws->cur_msg;\r
@@ -742,11 +767,20 @@ static void pump_transfers(unsigned long data)
         * 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
+               int templen ;\r
+               \r
+               if (chip->tmode == SPI_TMOD_RO) {\r
+                       templen = dws->len / dws->n_bytes - 1;\r
+                       rxint_level = dws->fifo_len / 2;\r
+                       rxint_level = (templen > rxint_level) ? rxint_level : templen;\r
+                       imask |= SPI_INT_RXFI;\r
+               }\r
+               else {  \r
+                       templen = dws->len / dws->n_bytes;\r
+                       txint_level = dws->fifo_len / 2;\r
+                       txint_level = (templen > txint_level) ? txint_level : templen;\r
+                       imask |= SPI_INT_TXEI;\r
+               }\r
                dws->transfer_handler = interrupt_transfer;\r
        }\r
 \r
@@ -763,15 +797,19 @@ static void pump_transfers(unsigned long data)
 \r
                spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);            \r
                spi_chip_sel(dws, spi->chip_select);\r
+\r
+        rk29xx_writew(dws, SPIM_CTRLR1, dws->len-1);\r
+               spi_enable_chip(dws, 1);\r
+\r
+               if (txint_level)\r
+                       rk29xx_writew(dws, SPIM_TXFTLR, txint_level);\r
+               if (rxint_level)\r
+                       rk29xx_writew(dws, SPIM_RXFTLR, rxint_level);\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
+               \r
                if (cs_change)\r
                        dws->prev_chip = chip;\r
        } \r
@@ -1093,7 +1131,7 @@ static void pump_messages(struct work_struct *work)
     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
+       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
@@ -1606,7 +1644,6 @@ static int rk29xx_spi_setup(struct spi_device *spi)
                        | (chip->tmode << SPI_TMOD_OFFSET);\r
 \r
        spi_set_ctldata(spi, chip);\r
-       DBG("RK29XX_SPI_SETUP: CRO: 0x%x ???????????????????\n", chip->cr0);\r
        return 0;\r
 }\r
 \r