Blackfin SPI Driver: use len_in_bytes when we care about the number of bytes transferred
[pandora-kernel.git] / drivers / spi / spi_bfin5xx.c
index 7fea3cf..6d3f606 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/dma.h>
 #include <asm/portmux.h>
 #include <asm/bfin5xx_spi.h>
+#include <asm/cacheflush.h>
 
 #define DRV_NAME       "bfin-spi"
 #define DRV_AUTHOR     "Bryan Wu, Luke Yang"
@@ -154,6 +155,9 @@ static u16 hz_to_spi_baud(u32 speed_hz)
        if ((sclk % (2 * speed_hz)) > 0)
                spi_baud++;
 
+       if (spi_baud < MIN_SPI_BAUD_VAL)
+               spi_baud = MIN_SPI_BAUD_VAL;
+
        return spi_baud;
 }
 
@@ -738,9 +742,10 @@ static void pump_transfers(unsigned long data)
                width, transfer->len);
 
        /*
-        * Try to map dma buffer and do a dma transfer if
-        * successful use different way to r/w according to
-        * drv_data->cur_chip->enable_dma
+        * Try to map dma buffer and do a dma transfer.  If successful use,
+        * different way to r/w according to the enable_dma settings and if
+        * we are not doing a full duplex transfer (since the hardware does
+        * not support full duplex DMA transfers).
         */
        if (!full_duplex && drv_data->cur_chip->enable_dma
                                && drv_data->len > 6) {
@@ -795,6 +800,12 @@ static void pump_transfers(unsigned long data)
                        /* set transfer mode, and enable SPI */
                        dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n");
 
+                       /* invalidate caches, if needed */
+                       if (bfin_addr_dcachable((unsigned long) drv_data->rx))
+                               invalidate_dcache_range((unsigned long) drv_data->rx,
+                                                       (unsigned long) (drv_data->rx +
+                                                       drv_data->len_in_bytes));
+
                        /* clear tx reg soformer data is not shifted out */
                        write_TDBR(drv_data, 0xFFFF);
 
@@ -815,6 +826,12 @@ static void pump_transfers(unsigned long data)
                } else if (drv_data->tx != NULL) {
                        dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");
 
+                       /* flush caches, if needed */
+                       if (bfin_addr_dcachable((unsigned long) drv_data->tx))
+                               flush_dcache_range((unsigned long) drv_data->tx,
+                                               (unsigned long) (drv_data->tx +
+                                               drv_data->len_in_bytes));
+
                        /* start dma */
                        dma_enable_irq(drv_data->dma_channel);
                        dma_config = (RESTART | dma_width | DI_EN);
@@ -876,7 +893,7 @@ static void pump_transfers(unsigned long data)
                        message->state = ERROR_STATE;
                } else {
                        /* Update total byte transfered */
-                       message->actual_length += drv_data->len;
+                       message->actual_length += drv_data->len_in_bytes;
 
                        /* Move to next transfer of this msg */
                        message->state = next_transfer(drv_data);
@@ -1160,8 +1177,8 @@ static inline int init_queue(struct driver_data *drv_data)
 
        /* init messages workqueue */
        INIT_WORK(&drv_data->pump_messages, pump_messages);
-       drv_data->workqueue =
-           create_singlethread_workqueue(drv_data->master->dev.parent->bus_id);
+       drv_data->workqueue = create_singlethread_workqueue(
+                               dev_name(drv_data->master->dev.parent));
        if (drv_data->workqueue == NULL)
                return -EBUSY;