linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/20] Blackfin SPI Driver fixing and updates
@ 2009-02-06  7:12 Bryan Wu
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA


Dear David and Andrew,

I updates this whole Blackfin SPI Driver patches (20 patches) as we
discussed in LKML.

Normally updates the comments and fold patch "Blackfin SPI Driver: add
comment about full duplex dma according to David Brownell" to
"Blackfin SPI Driver: ensure cache coherency before doing DMA".

Thanks a lot
-Bryan

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 01/20] Blackfin SPI Driver: ensure cache coherency before doing DMA
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 02/20] Blackfin SPI Driver: Fix erroneous SPI Clock divisor calculation Bryan Wu
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	Vitja Makarov, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Mike Frysinger

From: Vitja Makarov <vitja.makarov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

flush or invalidate caches before doing DMA transfer, if needed.

[Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>: add comment to address the
issue "Full duplex only works for non-DMA transfers".]

Signed-off-by: Vitja Makarov <vitja.makarov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |   23 ++++++++++++++++++++---
 1 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 7fea3cf..590f975 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -26,6 +26,10 @@
 #include <asm/portmux.h>
 #include <asm/bfin5xx_spi.h>
 
+/* reserved_mem_dcache_on and cache friends */
+#include <asm/cplbinit.h>
+#include <asm/cacheflush.h>
+
 #define DRV_NAME	"bfin-spi"
 #define DRV_AUTHOR	"Bryan Wu, Luke Yang"
 #define DRV_DESC	"Blackfin BF5xx on-chip SPI Controller Driver"
@@ -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));
+
 			/* 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));
+
 			/* start dma */
 			dma_enable_irq(drv_data->dma_channel);
 			dma_config = (RESTART | dma_width | DI_EN);
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 02/20] Blackfin SPI Driver: Fix erroneous SPI Clock divisor calculation
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
  2009-02-06  7:12   ` [PATCH 01/20] Blackfin SPI Driver: ensure cache coherency before doing DMA Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 03/20] Blackfin SPI Driver: remove useless <asm/cplbinit.h> Bryan Wu
                     ` (17 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Michael Hennerich

From: Michael Hennerich <michael.hennerich-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>

Fix erroneous SPI Clock divisor calculation. Make sure SPI_BAUD is
always >= 2. Writing a value of 0 or 1 to the SPI_BAUD register disables
the serial clock.

Signed-off-by: Michael Hennerich <michael.hennerich-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 arch/blackfin/include/asm/bfin5xx_spi.h |    2 ++
 drivers/spi/spi_bfin5xx.c               |    3 +++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h
index 1306e6b..e1bb164 100644
--- a/arch/blackfin/include/asm/bfin5xx_spi.h
+++ b/arch/blackfin/include/asm/bfin5xx_spi.h
@@ -11,6 +11,8 @@
 #ifndef _SPI_CHANNEL_H_
 #define _SPI_CHANNEL_H_
 
+#define MIN_SPI_BAUD_VAL	2
+
 #define SPI_READ              0
 #define SPI_WRITE             1
 
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 590f975..f2e18f7 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -158,6 +158,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;
 }
 
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 03/20] Blackfin SPI Driver: remove useless <asm/cplbinit.h>
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
  2009-02-06  7:12   ` [PATCH 01/20] Blackfin SPI Driver: ensure cache coherency before doing DMA Bryan Wu
  2009-02-06  7:12   ` [PATCH 02/20] Blackfin SPI Driver: Fix erroneous SPI Clock divisor calculation Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 04/20] Blackfin SPI Driver: use len_in_bytes when we care about the number of bytes transferred Bryan Wu
                     ` (16 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

We already moved bfin_addr_dcachable() and friends into the cacheflush
header where it belongs, so don't need to include <asm/cplbinit.h> here.

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index f2e18f7..1e046b1 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -25,9 +25,6 @@
 #include <asm/dma.h>
 #include <asm/portmux.h>
 #include <asm/bfin5xx_spi.h>
-
-/* reserved_mem_dcache_on and cache friends */
-#include <asm/cplbinit.h>
 #include <asm/cacheflush.h>
 
 #define DRV_NAME	"bfin-spi"
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 04/20] Blackfin SPI Driver: use len_in_bytes when we care about the number of bytes transferred
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (2 preceding siblings ...)
  2009-02-06  7:12   ` [PATCH 03/20] Blackfin SPI Driver: remove useless <asm/cplbinit.h> Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 05/20] Blackfin SPI Driver: pass DMA overflow error to the higher level Bryan Wu
                     ` (15 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Use len_in_bytes when we care about the number of bytes transferred
rather than the number of spi transactions. (this value will be the
same for 8bit transfers, but not any other sizes)

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 1e046b1..4a67770 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -804,7 +804,7 @@ static void pump_transfers(unsigned long data)
 			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));
+							drv_data->len_in_bytes));
 
 			/* clear tx reg soformer data is not shifted out */
 			write_TDBR(drv_data, 0xFFFF);
@@ -830,7 +830,7 @@ static void pump_transfers(unsigned long data)
 			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));
+						drv_data->len_in_bytes));
 
 			/* start dma */
 			dma_enable_irq(drv_data->dma_channel);
@@ -893,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);
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 05/20] Blackfin SPI Driver: pass DMA overflow error to the higher level
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (3 preceding siblings ...)
  2009-02-06  7:12   ` [PATCH 04/20] Blackfin SPI Driver: use len_in_bytes when we care about the number of bytes transferred Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 06/20] Blackfin SPI Driver: unify duplicated code in dma read/write paths Bryan Wu
                     ` (14 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

If the SPI bus registers a receive overflow error,
pass the result back up to the higher levels.

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |   16 +++++++++++-----
 1 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 4a67770..3945b59 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -559,6 +559,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 	struct driver_data *drv_data = dev_id;
 	struct chip_data *chip = drv_data->cur_chip;
 	struct spi_message *msg = drv_data->cur_msg;
+	u16 spistat = read_STAT(drv_data);
 
 	dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n");
 	clear_dma_irqstat(drv_data->dma_channel);
@@ -582,13 +583,18 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 	while (!(read_STAT(drv_data) & SPIF))
 		cpu_relax();
 
-	msg->actual_length += drv_data->len_in_bytes;
+	if (spistat & RBSY) {
+		msg->state = ERROR_STATE;
+		dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n");
+	} else {
+		msg->actual_length += drv_data->len_in_bytes;
 
-	if (drv_data->cs_change)
-		cs_deactive(drv_data, chip);
+		if (drv_data->cs_change)
+			cs_deactive(drv_data, chip);
 
-	/* Move to next transfer */
-	msg->state = next_transfer(drv_data);
+		/* Move to next transfer */
+		msg->state = next_transfer(drv_data);
+	}
 
 	/* Schedule transfer tasklet */
 	tasklet_schedule(&drv_data->pump_transfers);
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 06/20] Blackfin SPI Driver: unify duplicated code in dma read/write paths
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (4 preceding siblings ...)
  2009-02-06  7:12   ` [PATCH 05/20] Blackfin SPI Driver: pass DMA overflow error to the higher level Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 07/20] Blackfin SPI Driver: drop bogus cast and touchup dma label Bryan Wu
                     ` (13 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

For DMA TX/RX operation in pump_transfers, DMA contriguration code
in TX and RX paths are almost the same. This patch unify the duplicated
DMA code to make it more readable.

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |   47 ++++++++++++++++++++------------------------
 1 files changed, 21 insertions(+), 26 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 3945b59..acb9739 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -756,18 +756,19 @@ static void pump_transfers(unsigned long data)
 	if (!full_duplex && drv_data->cur_chip->enable_dma
 				&& drv_data->len > 6) {
 
+		unsigned long dma_start_addr;
+
 		disable_dma(drv_data->dma_channel);
 		clear_dma_irqstat(drv_data->dma_channel);
 		bfin_spi_disable(drv_data);
 
 		/* config dma channel */
 		dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
+		set_dma_x_count(drv_data->dma_channel, drv_data->len);
 		if (width == CFG_SPI_WORDSIZE16) {
-			set_dma_x_count(drv_data->dma_channel, drv_data->len);
 			set_dma_x_modify(drv_data->dma_channel, 2);
 			dma_width = WDSIZE_16;
 		} else {
-			set_dma_x_count(drv_data->dma_channel, drv_data->len);
 			set_dma_x_modify(drv_data->dma_channel, 1);
 			dma_width = WDSIZE_8;
 		}
@@ -802,6 +803,7 @@ static void pump_transfers(unsigned long data)
 		}
 
 		/* In dma mode, rx or tx must be NULL in one transfer */
+		dma_config = (RESTART | dma_width | DI_EN);
 		if (drv_data->rx != NULL) {
 			/* set transfer mode, and enable SPI */
 			dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n");
@@ -815,19 +817,9 @@ static void pump_transfers(unsigned long data)
 			/* clear tx reg soformer data is not shifted out */
 			write_TDBR(drv_data, 0xFFFF);
 
-			set_dma_x_count(drv_data->dma_channel, drv_data->len);
-
-			/* start dma */
-			dma_enable_irq(drv_data->dma_channel);
-			dma_config = (WNR | RESTART | dma_width | DI_EN);
-			set_dma_config(drv_data->dma_channel, dma_config);
-			set_dma_start_addr(drv_data->dma_channel,
-					(unsigned long)drv_data->rx);
-			enable_dma(drv_data->dma_channel);
-
-			/* start SPI transfer */
-			write_CTRL(drv_data,
-				(cr | CFG_SPI_DMAREAD | BIT_CTL_ENABLE));
+			dma_config |= WNR;
+			dma_start_addr = (unsigned long)drv_data->rx;
+			cr |= CFG_SPI_DMAREAD;
 
 		} else if (drv_data->tx != NULL) {
 			dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");
@@ -838,18 +830,21 @@ static void pump_transfers(unsigned long data)
 						(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);
-			set_dma_config(drv_data->dma_channel, dma_config);
-			set_dma_start_addr(drv_data->dma_channel,
-					(unsigned long)drv_data->tx);
-			enable_dma(drv_data->dma_channel);
+			dma_start_addr = (unsigned long)drv_data->tx;
+			cr |= CFG_SPI_DMAWRITE;
+
+		} else
+			BUG();
+
+		/* start dma */
+		dma_enable_irq(drv_data->dma_channel);
+		set_dma_config(drv_data->dma_channel, dma_config);
+		set_dma_start_addr(drv_data->dma_channel, dma_start_addr);
+		enable_dma(drv_data->dma_channel);
+
+		/* start SPI transfer */
+		write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
 
-			/* start SPI transfer */
-			write_CTRL(drv_data,
-				(cr | CFG_SPI_DMAWRITE | BIT_CTL_ENABLE));
-		}
 	} else {
 		/* IO mode write then read */
 		dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 07/20] Blackfin SPI Driver: drop bogus cast and touchup dma label
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (5 preceding siblings ...)
  2009-02-06  7:12   ` [PATCH 06/20] Blackfin SPI Driver: unify duplicated code in dma read/write paths Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 08/20] Blackfin SPI Driver: add a few more DMA debug messages Bryan Wu
                     ` (12 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Blackfin's related DMA callback API doesn't need void * cast, so drop it.
And this driver is for all Blackfin processors not only for BF53x, we
update the DMA request label for more meaningful information.

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index acb9739..459ec36 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1077,13 +1077,13 @@ static int setup(struct spi_device *spi)
 	 */
 	if (chip->enable_dma && !drv_data->dma_requested) {
 		/* register dma irq handler */
-		if (request_dma(drv_data->dma_channel, "BF53x_SPI_DMA") < 0) {
+		if (request_dma(drv_data->dma_channel, "BFIN_SPI_DMA") < 0) {
 			dev_dbg(&spi->dev,
 				"Unable to request BlackFin SPI DMA channel\n");
 			return -ENODEV;
 		}
 		if (set_dma_callback(drv_data->dma_channel,
-			(void *)dma_irq_handler, drv_data) < 0) {
+		    dma_irq_handler, drv_data) < 0) {
 			dev_dbg(&spi->dev, "Unable to set dma callback\n");
 			return -EPERM;
 		}
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 08/20] Blackfin SPI Driver: add a few more DMA debug messages
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (6 preceding siblings ...)
  2009-02-06  7:12   ` [PATCH 07/20] Blackfin SPI Driver: drop bogus cast and touchup dma label Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 09/20] Blackfin SPI Driver: do not check for SPI errors if DMA itself did not flag any Bryan Wu
                     ` (11 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Because of DMA hardware issue, we were trying to use software workaround.
This patch add some useful debug messages to help us debugging the DMA
code.

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 459ec36..7652da8 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -559,9 +559,13 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 	struct driver_data *drv_data = dev_id;
 	struct chip_data *chip = drv_data->cur_chip;
 	struct spi_message *msg = drv_data->cur_msg;
+	unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
 	u16 spistat = read_STAT(drv_data);
 
-	dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n");
+	dev_dbg(&drv_data->pdev->dev,
+		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
+		dmastat, spistat);
+
 	clear_dma_irqstat(drv_data->dma_channel);
 
 	/* Wait for DMA to complete */
@@ -631,6 +635,7 @@ static void pump_transfers(unsigned long data)
 
 	 /* Handle for abort */
 	if (message->state == ERROR_STATE) {
+		dev_dbg(&drv_data->pdev->dev, "transfer: we've hit an error\n");
 		message->status = -EIO;
 		giveback(drv_data);
 		return;
@@ -638,6 +643,7 @@ static void pump_transfers(unsigned long data)
 
 	/* Handle end of message */
 	if (message->state == DONE_STATE) {
+		dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
 		message->status = 0;
 		giveback(drv_data);
 		return;
@@ -645,6 +651,7 @@ static void pump_transfers(unsigned long data)
 
 	/* Delay if requested at end of transfer */
 	if (message->state == RUNNING_STATE) {
+		dev_dbg(&drv_data->pdev->dev, "transfer: still running ...\n");
 		previous = list_entry(transfer->transfer_list.prev,
 				      struct spi_transfer, transfer_list);
 		if (previous->delay_usecs)
@@ -806,7 +813,8 @@ static void pump_transfers(unsigned long data)
 		dma_config = (RESTART | dma_width | DI_EN);
 		if (drv_data->rx != NULL) {
 			/* set transfer mode, and enable SPI */
-			dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n");
+			dev_dbg(&drv_data->pdev->dev, "doing DMA in to %p (size %zx)\n",
+				drv_data->rx, drv_data->len_in_bytes);
 
 			/* invalidate caches, if needed */
 			if (bfin_addr_dcachable((unsigned long) drv_data->rx))
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 09/20] Blackfin SPI Driver: do not check for SPI errors if DMA itself did not flag any
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (7 preceding siblings ...)
  2009-02-06  7:12   ` [PATCH 08/20] Blackfin SPI Driver: add a few more DMA debug messages Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 10/20] Blackfin SPI Driver: use the properl BIT_CTL_xxx defines Bryan Wu
                     ` (10 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

We only need to check SPI error when DMA failes, cause that
is the DMA IRQ handling routine.

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 7652da8..f7a4b5b 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -587,7 +587,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 	while (!(read_STAT(drv_data) & SPIF))
 		cpu_relax();
 
-	if (spistat & RBSY) {
+	if ((dmastat & DMA_ERR) && (spistat & RBSY)) {
 		msg->state = ERROR_STATE;
 		dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n");
 	} else {
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 10/20] Blackfin SPI Driver: use the properl BIT_CTL_xxx defines
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (8 preceding siblings ...)
  2009-02-06  7:12   ` [PATCH 09/20] Blackfin SPI Driver: do not check for SPI errors if DMA itself did not flag any Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:12   ` [PATCH 11/20] Blackfin SPI Driver: SPI slave select code cleanup Bryan Wu
                     ` (9 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

use the properl BIT_CTL_... defines rather than the internal driv
er CFG_SPI_... defines

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index f7a4b5b..54d8948 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -799,7 +799,7 @@ static void pump_transfers(unsigned long data)
 
 			/* start SPI transfer */
 			write_CTRL(drv_data,
-				(cr | CFG_SPI_DMAWRITE | BIT_CTL_ENABLE));
+				(cr | BIT_CTL_TIMOD_DMA_TX | BIT_CTL_ENABLE));
 
 			/* just return here, there can only be one transfer
 			 * in this mode
@@ -827,7 +827,7 @@ static void pump_transfers(unsigned long data)
 
 			dma_config |= WNR;
 			dma_start_addr = (unsigned long)drv_data->rx;
-			cr |= CFG_SPI_DMAREAD;
+			cr |= BIT_CTL_TIMOD_DMA_RX | BIT_CTL_SENDOPT;
 
 		} else if (drv_data->tx != NULL) {
 			dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");
@@ -839,7 +839,7 @@ static void pump_transfers(unsigned long data)
 						drv_data->len_in_bytes));
 
 			dma_start_addr = (unsigned long)drv_data->tx;
-			cr |= CFG_SPI_DMAWRITE;
+			cr |= BIT_CTL_TIMOD_DMA_TX;
 
 		} else
 			BUG();
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 11/20] Blackfin SPI Driver: SPI slave select code cleanup
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (9 preceding siblings ...)
  2009-02-06  7:12   ` [PATCH 10/20] Blackfin SPI Driver: use the properl BIT_CTL_xxx defines Bryan Wu
@ 2009-02-06  7:12   ` Bryan Wu
  2009-02-06  7:13   ` [PATCH 12/20] Blackfin SPI Driver: get dma working for SPI flashes Bryan Wu
                     ` (8 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:12 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

 - remove duplicated definition MAX_SPI_SSEL
 - remove unnecessary array size

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 54d8948..bfb587e 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -198,8 +198,6 @@ static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
 		udelay(chip->cs_chg_udelay);
 }
 
-#define MAX_SPI_SSEL	7
-
 /* stop controller and re-config current chip*/
 static void restore_state(struct driver_data *drv_data)
 {
@@ -1001,7 +999,7 @@ static int transfer(struct spi_device *spi, struct spi_message *msg)
 
 #define MAX_SPI_SSEL	7
 
-static u16 ssel[3][MAX_SPI_SSEL] = {
+static u16 ssel[][MAX_SPI_SSEL] = {
 	{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
 	P_SPI0_SSEL4, P_SPI0_SSEL5,
 	P_SPI0_SSEL6, P_SPI0_SSEL7},
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 12/20] Blackfin SPI Driver: get dma working for SPI flashes
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (10 preceding siblings ...)
  2009-02-06  7:12   ` [PATCH 11/20] Blackfin SPI Driver: SPI slave select code cleanup Bryan Wu
@ 2009-02-06  7:13   ` Bryan Wu
  2009-02-06  7:13   ` [PATCH 13/20] Blackfin SPI Driver: add timeout while waiting for SPIF in dma irq handler Bryan Wu
                     ` (7 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:13 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

When using a BF533-STAMP here with a W25X10 SPI flash. It works fine when
enable_dma is disabled, but doesn't work at all when turning DMA on.
We get just 0xff bytes back when trying to read the device.

If change the code around so that it programs the SPI first and then
enables DMA, it seems to work a lot better ...

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |   26 ++++++++++++++++----------
 1 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index bfb587e..83398b3 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -761,11 +761,10 @@ static void pump_transfers(unsigned long data)
 	if (!full_duplex && drv_data->cur_chip->enable_dma
 				&& drv_data->len > 6) {
 
-		unsigned long dma_start_addr;
+		unsigned long dma_start_addr, flags;
 
 		disable_dma(drv_data->dma_channel);
 		clear_dma_irqstat(drv_data->dma_channel);
-		bfin_spi_disable(drv_data);
 
 		/* config dma channel */
 		dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
@@ -796,8 +795,7 @@ static void pump_transfers(unsigned long data)
 			enable_dma(drv_data->dma_channel);
 
 			/* start SPI transfer */
-			write_CTRL(drv_data,
-				(cr | BIT_CTL_TIMOD_DMA_TX | BIT_CTL_ENABLE));
+			write_CTRL(drv_data, cr | BIT_CTL_TIMOD_DMA_TX);
 
 			/* just return here, there can only be one transfer
 			 * in this mode
@@ -842,14 +840,22 @@ static void pump_transfers(unsigned long data)
 		} else
 			BUG();
 
-		/* start dma */
-		dma_enable_irq(drv_data->dma_channel);
-		set_dma_config(drv_data->dma_channel, dma_config);
+		/* oh man, here there be monsters ... and i dont mean the
+		 * fluffy cute ones from pixar, i mean the kind that'll eat
+		 * your data, kick your dog, and love it all.  do *not* try
+		 * and change these lines unless you (1) heavily test DMA
+		 * with SPI flashes on a loaded system (e.g. ping floods),
+		 * (2) know just how broken the DMA engine interaction with
+		 * the SPI peripheral is, and (3) have someone else to blame
+		 * when you screw it all up anyways.
+		 */
 		set_dma_start_addr(drv_data->dma_channel, dma_start_addr);
+		set_dma_config(drv_data->dma_channel, dma_config);
+		local_irq_save(flags);
 		enable_dma(drv_data->dma_channel);
-
-		/* start SPI transfer */
-		write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
+		write_CTRL(drv_data, cr);
+		dma_enable_irq(drv_data->dma_channel);
+		local_irq_restore(flags);
 
 	} else {
 		/* IO mode write then read */
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 13/20] Blackfin SPI Driver: add timeout while waiting for SPIF in dma irq handler
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (11 preceding siblings ...)
  2009-02-06  7:13   ` [PATCH 12/20] Blackfin SPI Driver: get dma working for SPI flashes Bryan Wu
@ 2009-02-06  7:13   ` Bryan Wu
  2009-02-06  7:13   ` [PATCH 14/20] Blackfin SPI Driver: tweak magic spi dma sequence to get it working on BF54x Bryan Wu
                     ` (6 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:13 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

The "while" endless loop will cause the system hang if hardware error, so we add
timeout control to make the system alive.

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 83398b3..748e98f 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -557,6 +557,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 	struct driver_data *drv_data = dev_id;
 	struct chip_data *chip = drv_data->cur_chip;
 	struct spi_message *msg = drv_data->cur_msg;
+	unsigned long timeout;
 	unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
 	u16 spistat = read_STAT(drv_data);
 
@@ -582,8 +583,17 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 			cpu_relax();
 	}
 
+	dev_dbg(&drv_data->pdev->dev,
+		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
+		dmastat, read_STAT(drv_data));
+
+	timeout = jiffies + HZ;
 	while (!(read_STAT(drv_data) & SPIF))
-		cpu_relax();
+		if (!time_before(jiffies, timeout)) {
+			dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");
+			break;
+		} else
+			cpu_relax();
 
 	if ((dmastat & DMA_ERR) && (spistat & RBSY)) {
 		msg->state = ERROR_STATE;
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 14/20] Blackfin SPI Driver: tweak magic spi dma sequence to get it working on BF54x
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (12 preceding siblings ...)
  2009-02-06  7:13   ` [PATCH 13/20] Blackfin SPI Driver: add timeout while waiting for SPIF in dma irq handler Bryan Wu
@ 2009-02-06  7:13   ` Bryan Wu
  2009-02-06  7:13   ` [PATCH 15/20] Blackfin SPI Driver: fix bug - spi controller driver does not assert/deassert CS correctly Bryan Wu
                     ` (5 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:13 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Without this changes, SPI DMA is not reliably under stress tests.
Obiviously it's a hardware issue which is not addressed by any document.

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 748e98f..d8c4be1 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -862,8 +862,9 @@ static void pump_transfers(unsigned long data)
 		set_dma_start_addr(drv_data->dma_channel, dma_start_addr);
 		set_dma_config(drv_data->dma_channel, dma_config);
 		local_irq_save(flags);
-		enable_dma(drv_data->dma_channel);
+		SSYNC();
 		write_CTRL(drv_data, cr);
+		enable_dma(drv_data->dma_channel);
 		dma_enable_irq(drv_data->dma_channel);
 		local_irq_restore(flags);
 
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 15/20] Blackfin SPI Driver: fix bug - spi controller driver does not assert/deassert CS correctly
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (13 preceding siblings ...)
  2009-02-06  7:13   ` [PATCH 14/20] Blackfin SPI Driver: tweak magic spi dma sequence to get it working on BF54x Bryan Wu
@ 2009-02-06  7:13   ` Bryan Wu
  2009-02-06  7:13   ` [PATCH 16/20] Blackfin SPI Driver: fix bug - correct usage of struct spi_transfer.cs_change Bryan Wu
                     ` (4 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:13 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Yi Li,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

From: Yi Li <yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>

This bug can be observed when two SPI devices are sharing the spi bus:
One device is set as SPI CS 7, another one is using SPI CS 4.

In spi_bfin5xx.c: cs_active(), cs_deactive() are used to control SPI_FLG
register. From the debug bellow:

cs_active: flag: 0x7f91, chip->flag: 0x7f80, cs: 7
cs_active: flag: 0xef91, chip->flag: 0xef10, cs: 4

When device A (cs_7) activate CS 7, SPI_FLG is set as 0x7f91 (however,
SPI_FLG should be set as 0x7f80, or 0x6f91 if in broadcast mode).

Due to some HW bug (very possibly), if SPI_FLG is set as 0x7f91,
SPISSEL7 is asserted, however SPISSEL4 will be asserted too (I can see
this using the scope). This is unreasonable according to HRM.

Signed-off-by: Yi Li <yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index d8c4be1..ed6a4c1 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -189,6 +189,7 @@ static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
 {
 	u16 flag = read_FLAG(drv_data);
 
+	flag &= ~chip->flag;
 	flag |= (chip->flag << 8);
 
 	write_FLAG(drv_data, flag);
@@ -1036,7 +1037,6 @@ static int setup(struct spi_device *spi)
 	struct bfin5xx_spi_chip *chip_info = NULL;
 	struct chip_data *chip;
 	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
-	u8 spi_flg;
 
 	/* Abort device setup if requested features are not supported */
 	if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {
@@ -1119,8 +1119,7 @@ static int setup(struct spi_device *spi)
 	 * SPI_BAUD, not the real baudrate
 	 */
 	chip->baud = hz_to_spi_baud(spi->max_speed_hz);
-	spi_flg = ~(1 << (spi->chip_select));
-	chip->flag = ((u16) spi_flg << 8) | (1 << (spi->chip_select));
+	chip->flag = 1 << (spi->chip_select);
 	chip->chip_select_num = spi->chip_select;
 
 	switch (chip->bits_per_word) {
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 16/20] Blackfin SPI Driver: fix bug - correct usage of struct spi_transfer.cs_change
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (14 preceding siblings ...)
  2009-02-06  7:13   ` [PATCH 15/20] Blackfin SPI Driver: fix bug - spi controller driver does not assert/deassert CS correctly Bryan Wu
@ 2009-02-06  7:13   ` Bryan Wu
  2009-02-06  7:13   ` [PATCH 17/20] Blackfin SPI Driver: use bfin_spi_ prefix on all functions Bryan Wu
                     ` (3 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:13 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Yi Li,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

From: Yi Li <yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>

According to comments in linux/spi/spi.h:

 * All SPI transfers start with the relevant chipselect active.  Normally
 * it stays selected until after the last transfer in a message. Drivers
 * can affect the chipselect signal using cs_change.
 *
 * (i) If the transfer isn't the last one in the message, this flag is
 * used to make the chipselect briefly go inactive in the middle of the
 * message.  Toggling chipselect in this way may be needed to terminate
 * a chip command, letting a single spi_message perform all of group of
 * chip transactions together.
 *
 * (ii) When the transfer is the last one in the message, the chip may
 * stay selected until the next transfer.  On multi-device SPI busses
 * with nothing blocking messages going to other devices, this is just
 * a performance hint; starting a message to another device deselects
 * this one.  But in other cases, this can be used to ensure correctness.
 * Some devices need protocol transactions to be built from a series of
 * spi_message submissions, where the content of one message is determined
 * by the results of previous messages and where the whole transaction
 * ends when the chipselect goes intactive.

Signed-off-by: Yi Li <yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |   17 ++++++++---------
 1 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index ed6a4c1..811a305 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -540,15 +540,13 @@ static void giveback(struct driver_data *drv_data)
 
 	msg->state = NULL;
 
-	/* disable chip select signal. And not stop spi in autobuffer mode */
-	if (drv_data->tx_dma != 0xFFFF) {
-		cs_deactive(drv_data, chip);
-		bfin_spi_disable(drv_data);
-	}
-
 	if (!drv_data->cs_change)
 		cs_deactive(drv_data, chip);
 
+	/* Not stop spi in autobuffer mode */
+	if (drv_data->tx_dma != 0xFFFF)
+		bfin_spi_disable(drv_data);
+
 	if (msg->complete)
 		msg->complete(msg->context);
 }
@@ -757,7 +755,8 @@ static void pump_transfers(unsigned long data)
 
 	write_STAT(drv_data, BIT_STAT_CLR);
 	cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
-	cs_active(drv_data, chip);
+	if (drv_data->cs_change)
+		cs_active(drv_data, chip);
 
 	dev_dbg(&drv_data->pdev->dev,
 		"now pumping a transfer: width is %d, len is %d\n",
@@ -919,11 +918,11 @@ static void pump_transfers(unsigned long data)
 		} else {
 			/* Update total byte transfered */
 			message->actual_length += drv_data->len_in_bytes;
-
 			/* Move to next transfer of this msg */
 			message->state = next_transfer(drv_data);
+			if (drv_data->cs_change)
+				cs_deactive(drv_data, chip);
 		}
-
 		/* Schedule next transfer tasklet */
 		tasklet_schedule(&drv_data->pump_transfers);
 
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 17/20] Blackfin SPI Driver: use bfin_spi_ prefix on all functions
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (15 preceding siblings ...)
  2009-02-06  7:13   ` [PATCH 16/20] Blackfin SPI Driver: fix bug - correct usage of struct spi_transfer.cs_change Bryan Wu
@ 2009-02-06  7:13   ` Bryan Wu
  2009-02-06  7:13   ` [PATCH 18/20] Blackfin SPI Driver: fix NULL pointer crash Bryan Wu
                     ` (2 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:13 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Do this because when things crash, we get simple names like "setup" and
"start_queue" which is pretty difficult to trace back to the real thing:
the spi driver

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |  223 +++++++++++++++++++++++----------------------
 1 files changed, 112 insertions(+), 111 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 811a305..f9e1fbc 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -29,7 +29,7 @@
 
 #define DRV_NAME	"bfin-spi"
 #define DRV_AUTHOR	"Bryan Wu, Luke Yang"
-#define DRV_DESC	"Blackfin BF5xx on-chip SPI Controller Driver"
+#define DRV_DESC	"Blackfin on-chip SPI Controller Driver"
 #define DRV_VERSION	"1.0"
 
 MODULE_AUTHOR(DRV_AUTHOR);
@@ -161,7 +161,7 @@ static u16 hz_to_spi_baud(u32 speed_hz)
 	return spi_baud;
 }
 
-static int flush(struct driver_data *drv_data)
+static int bfin_spi_flush(struct driver_data *drv_data)
 {
 	unsigned long limit = loops_per_jiffy << 1;
 
@@ -175,7 +175,7 @@ static int flush(struct driver_data *drv_data)
 }
 
 /* Chip select operation functions for cs_change flag */
-static void cs_active(struct driver_data *drv_data, struct chip_data *chip)
+static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *chip)
 {
 	u16 flag = read_FLAG(drv_data);
 
@@ -185,7 +185,7 @@ static void cs_active(struct driver_data *drv_data, struct chip_data *chip)
 	write_FLAG(drv_data, flag);
 }
 
-static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
+static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
 {
 	u16 flag = read_FLAG(drv_data);
 
@@ -200,7 +200,7 @@ static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
 }
 
 /* stop controller and re-config current chip*/
-static void restore_state(struct driver_data *drv_data)
+static void bfin_spi_restore_state(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
@@ -214,18 +214,18 @@ static void restore_state(struct driver_data *drv_data)
 	write_BAUD(drv_data, chip->baud);
 
 	bfin_spi_enable(drv_data);
-	cs_active(drv_data, chip);
+	bfin_spi_cs_active(drv_data, chip);
 }
 
 /* used to kick off transfer in rx mode */
-static unsigned short dummy_read(struct driver_data *drv_data)
+static unsigned short bfin_spi_dummy_read(struct driver_data *drv_data)
 {
 	unsigned short tmp;
 	tmp = read_RDBR(drv_data);
 	return tmp;
 }
 
-static void null_writer(struct driver_data *drv_data)
+static void bfin_spi_null_writer(struct driver_data *drv_data)
 {
 	u8 n_bytes = drv_data->n_bytes;
 
@@ -237,20 +237,20 @@ static void null_writer(struct driver_data *drv_data)
 	}
 }
 
-static void null_reader(struct driver_data *drv_data)
+static void bfin_spi_null_reader(struct driver_data *drv_data)
 {
 	u8 n_bytes = drv_data->n_bytes;
-	dummy_read(drv_data);
+	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < drv_data->rx_end) {
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-		dummy_read(drv_data);
+		bfin_spi_dummy_read(drv_data);
 		drv_data->rx += n_bytes;
 	}
 }
 
-static void u8_writer(struct driver_data *drv_data)
+static void bfin_spi_u8_writer(struct driver_data *drv_data)
 {
 	dev_dbg(&drv_data->pdev->dev,
 		"cr8-s is 0x%x\n", read_STAT(drv_data));
@@ -267,12 +267,12 @@ static void u8_writer(struct driver_data *drv_data)
 		cpu_relax();
 }
 
-static void u8_cs_chg_writer(struct driver_data *drv_data)
+static void bfin_spi_u8_cs_chg_writer(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
 	while (drv_data->tx < drv_data->tx_end) {
-		cs_active(drv_data, chip);
+		bfin_spi_cs_active(drv_data, chip);
 
 		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
 		while (read_STAT(drv_data) & BIT_STAT_TXS)
@@ -280,13 +280,13 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)
 		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
 			cpu_relax();
 
-		cs_deactive(drv_data, chip);
+		bfin_spi_cs_deactive(drv_data, chip);
 
 		++drv_data->tx;
 	}
 }
 
-static void u8_reader(struct driver_data *drv_data)
+static void bfin_spi_u8_reader(struct driver_data *drv_data)
 {
 	dev_dbg(&drv_data->pdev->dev,
 		"cr-8 is 0x%x\n", read_STAT(drv_data));
@@ -298,7 +298,7 @@ static void u8_reader(struct driver_data *drv_data)
 	/* clear TDBR buffer before read(else it will be shifted out) */
 	write_TDBR(drv_data, 0xFFFF);
 
-	dummy_read(drv_data);
+	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < drv_data->rx_end - 1) {
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
@@ -313,12 +313,12 @@ static void u8_reader(struct driver_data *drv_data)
 	++drv_data->rx;
 }
 
-static void u8_cs_chg_reader(struct driver_data *drv_data)
+static void bfin_spi_u8_cs_chg_reader(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
 	while (drv_data->rx < drv_data->rx_end) {
-		cs_active(drv_data, chip);
+		bfin_spi_cs_active(drv_data, chip);
 		read_RDBR(drv_data);	/* kick off */
 
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
@@ -327,13 +327,13 @@ static void u8_cs_chg_reader(struct driver_data *drv_data)
 			cpu_relax();
 
 		*(u8 *) (drv_data->rx) = read_SHAW(drv_data);
-		cs_deactive(drv_data, chip);
+		bfin_spi_cs_deactive(drv_data, chip);
 
 		++drv_data->rx;
 	}
 }
 
-static void u8_duplex(struct driver_data *drv_data)
+static void bfin_spi_u8_duplex(struct driver_data *drv_data)
 {
 	/* in duplex mode, clk is triggered by writing of TDBR */
 	while (drv_data->rx < drv_data->rx_end) {
@@ -348,12 +348,12 @@ static void u8_duplex(struct driver_data *drv_data)
 	}
 }
 
-static void u8_cs_chg_duplex(struct driver_data *drv_data)
+static void bfin_spi_u8_cs_chg_duplex(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
 	while (drv_data->rx < drv_data->rx_end) {
-		cs_active(drv_data, chip);
+		bfin_spi_cs_active(drv_data, chip);
 
 		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
 
@@ -363,14 +363,14 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)
 			cpu_relax();
 		*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
 
-		cs_deactive(drv_data, chip);
+		bfin_spi_cs_deactive(drv_data, chip);
 
 		++drv_data->rx;
 		++drv_data->tx;
 	}
 }
 
-static void u16_writer(struct driver_data *drv_data)
+static void bfin_spi_u16_writer(struct driver_data *drv_data)
 {
 	dev_dbg(&drv_data->pdev->dev,
 		"cr16 is 0x%x\n", read_STAT(drv_data));
@@ -387,12 +387,12 @@ static void u16_writer(struct driver_data *drv_data)
 		cpu_relax();
 }
 
-static void u16_cs_chg_writer(struct driver_data *drv_data)
+static void bfin_spi_u16_cs_chg_writer(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
 	while (drv_data->tx < drv_data->tx_end) {
-		cs_active(drv_data, chip);
+		bfin_spi_cs_active(drv_data, chip);
 
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
 		while ((read_STAT(drv_data) & BIT_STAT_TXS))
@@ -400,13 +400,13 @@ static void u16_cs_chg_writer(struct driver_data *drv_data)
 		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
 			cpu_relax();
 
-		cs_deactive(drv_data, chip);
+		bfin_spi_cs_deactive(drv_data, chip);
 
 		drv_data->tx += 2;
 	}
 }
 
-static void u16_reader(struct driver_data *drv_data)
+static void bfin_spi_u16_reader(struct driver_data *drv_data)
 {
 	dev_dbg(&drv_data->pdev->dev,
 		"cr-16 is 0x%x\n", read_STAT(drv_data));
@@ -418,7 +418,7 @@ static void u16_reader(struct driver_data *drv_data)
 	/* clear TDBR buffer before read(else it will be shifted out) */
 	write_TDBR(drv_data, 0xFFFF);
 
-	dummy_read(drv_data);
+	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < (drv_data->rx_end - 2)) {
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
@@ -433,7 +433,7 @@ static void u16_reader(struct driver_data *drv_data)
 	drv_data->rx += 2;
 }
 
-static void u16_cs_chg_reader(struct driver_data *drv_data)
+static void bfin_spi_u16_cs_chg_reader(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
@@ -444,19 +444,19 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
 	/* clear TDBR buffer before read(else it will be shifted out) */
 	write_TDBR(drv_data, 0xFFFF);
 
-	cs_active(drv_data, chip);
-	dummy_read(drv_data);
+	bfin_spi_cs_active(drv_data, chip);
+	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < drv_data->rx_end - 2) {
-		cs_deactive(drv_data, chip);
+		bfin_spi_cs_deactive(drv_data, chip);
 
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-		cs_active(drv_data, chip);
+		bfin_spi_cs_active(drv_data, chip);
 		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
 		drv_data->rx += 2;
 	}
-	cs_deactive(drv_data, chip);
+	bfin_spi_cs_deactive(drv_data, chip);
 
 	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 		cpu_relax();
@@ -464,7 +464,7 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
 	drv_data->rx += 2;
 }
 
-static void u16_duplex(struct driver_data *drv_data)
+static void bfin_spi_u16_duplex(struct driver_data *drv_data)
 {
 	/* in duplex mode, clk is triggered by writing of TDBR */
 	while (drv_data->tx < drv_data->tx_end) {
@@ -479,12 +479,12 @@ static void u16_duplex(struct driver_data *drv_data)
 	}
 }
 
-static void u16_cs_chg_duplex(struct driver_data *drv_data)
+static void bfin_spi_u16_cs_chg_duplex(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
 	while (drv_data->tx < drv_data->tx_end) {
-		cs_active(drv_data, chip);
+		bfin_spi_cs_active(drv_data, chip);
 
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
 		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
@@ -493,7 +493,7 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
 			cpu_relax();
 		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
 
-		cs_deactive(drv_data, chip);
+		bfin_spi_cs_deactive(drv_data, chip);
 
 		drv_data->rx += 2;
 		drv_data->tx += 2;
@@ -501,7 +501,7 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
 }
 
 /* test if ther is more transfer to be done */
-static void *next_transfer(struct driver_data *drv_data)
+static void *bfin_spi_next_transfer(struct driver_data *drv_data)
 {
 	struct spi_message *msg = drv_data->cur_msg;
 	struct spi_transfer *trans = drv_data->cur_transfer;
@@ -520,7 +520,7 @@ static void *next_transfer(struct driver_data *drv_data)
  * caller already set message->status;
  * dma and pio irqs are blocked give finished message back
  */
-static void giveback(struct driver_data *drv_data)
+static void bfin_spi_giveback(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 	struct spi_transfer *last_transfer;
@@ -541,7 +541,7 @@ static void giveback(struct driver_data *drv_data)
 	msg->state = NULL;
 
 	if (!drv_data->cs_change)
-		cs_deactive(drv_data, chip);
+		bfin_spi_cs_deactive(drv_data, chip);
 
 	/* Not stop spi in autobuffer mode */
 	if (drv_data->tx_dma != 0xFFFF)
@@ -551,7 +551,7 @@ static void giveback(struct driver_data *drv_data)
 		msg->complete(msg->context);
 }
 
-static irqreturn_t dma_irq_handler(int irq, void *dev_id)
+static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
 {
 	struct driver_data *drv_data = dev_id;
 	struct chip_data *chip = drv_data->cur_chip;
@@ -601,10 +601,10 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 		msg->actual_length += drv_data->len_in_bytes;
 
 		if (drv_data->cs_change)
-			cs_deactive(drv_data, chip);
+			bfin_spi_cs_deactive(drv_data, chip);
 
 		/* Move to next transfer */
-		msg->state = next_transfer(drv_data);
+		msg->state = bfin_spi_next_transfer(drv_data);
 	}
 
 	/* Schedule transfer tasklet */
@@ -619,7 +619,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static void pump_transfers(unsigned long data)
+static void bfin_spi_pump_transfers(unsigned long data)
 {
 	struct driver_data *drv_data = (struct driver_data *)data;
 	struct spi_message *message = NULL;
@@ -644,7 +644,7 @@ static void pump_transfers(unsigned long data)
 	if (message->state == ERROR_STATE) {
 		dev_dbg(&drv_data->pdev->dev, "transfer: we've hit an error\n");
 		message->status = -EIO;
-		giveback(drv_data);
+		bfin_spi_giveback(drv_data);
 		return;
 	}
 
@@ -652,7 +652,7 @@ static void pump_transfers(unsigned long data)
 	if (message->state == DONE_STATE) {
 		dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
 		message->status = 0;
-		giveback(drv_data);
+		bfin_spi_giveback(drv_data);
 		return;
 	}
 
@@ -666,10 +666,10 @@ static void pump_transfers(unsigned long data)
 	}
 
 	/* Setup the transfer state based on the type of transfer */
-	if (flush(drv_data) == 0) {
+	if (bfin_spi_flush(drv_data) == 0) {
 		dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
 		message->status = -EIO;
-		giveback(drv_data);
+		bfin_spi_giveback(drv_data);
 		return;
 	}
 
@@ -703,31 +703,31 @@ static void pump_transfers(unsigned long data)
 		drv_data->n_bytes = 1;
 		width = CFG_SPI_WORDSIZE8;
 		drv_data->read = chip->cs_change_per_word ?
-			u8_cs_chg_reader : u8_reader;
+			bfin_spi_u8_cs_chg_reader : bfin_spi_u8_reader;
 		drv_data->write = chip->cs_change_per_word ?
-			u8_cs_chg_writer : u8_writer;
+			bfin_spi_u8_cs_chg_writer : bfin_spi_u8_writer;
 		drv_data->duplex = chip->cs_change_per_word ?
-			u8_cs_chg_duplex : u8_duplex;
+			bfin_spi_u8_cs_chg_duplex : bfin_spi_u8_duplex;
 		break;
 
 	case 16:
 		drv_data->n_bytes = 2;
 		width = CFG_SPI_WORDSIZE16;
 		drv_data->read = chip->cs_change_per_word ?
-			u16_cs_chg_reader : u16_reader;
+			bfin_spi_u16_cs_chg_reader : bfin_spi_u16_reader;
 		drv_data->write = chip->cs_change_per_word ?
-			u16_cs_chg_writer : u16_writer;
+			bfin_spi_u16_cs_chg_writer : bfin_spi_u16_writer;
 		drv_data->duplex = chip->cs_change_per_word ?
-			u16_cs_chg_duplex : u16_duplex;
+			bfin_spi_u16_cs_chg_duplex : bfin_spi_u16_duplex;
 		break;
 
 	default:
 		/* No change, the same as default setting */
 		drv_data->n_bytes = chip->n_bytes;
 		width = chip->width;
-		drv_data->write = drv_data->tx ? chip->write : null_writer;
-		drv_data->read = drv_data->rx ? chip->read : null_reader;
-		drv_data->duplex = chip->duplex ? chip->duplex : null_writer;
+		drv_data->write = drv_data->tx ? chip->write : bfin_spi_null_writer;
+		drv_data->read = drv_data->rx ? chip->read : bfin_spi_null_reader;
+		drv_data->duplex = chip->duplex ? chip->duplex : bfin_spi_null_writer;
 		break;
 	}
 	cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
@@ -741,7 +741,7 @@ static void pump_transfers(unsigned long data)
 	}
 	dev_dbg(&drv_data->pdev->dev,
 		"transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n",
-		drv_data->write, chip->write, null_writer);
+		drv_data->write, chip->write, bfin_spi_null_writer);
 
 	/* speed and width has been set on per message */
 	message->state = RUNNING_STATE;
@@ -756,7 +756,7 @@ static void pump_transfers(unsigned long data)
 	write_STAT(drv_data, BIT_STAT_CLR);
 	cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
 	if (drv_data->cs_change)
-		cs_active(drv_data, chip);
+		bfin_spi_cs_active(drv_data, chip);
 
 	dev_dbg(&drv_data->pdev->dev,
 		"now pumping a transfer: width is %d, len is %d\n",
@@ -811,7 +811,7 @@ static void pump_transfers(unsigned long data)
 			 * in this mode
 			 */
 			message->status = 0;
-			giveback(drv_data);
+			bfin_spi_giveback(drv_data);
 			return;
 		}
 
@@ -919,9 +919,9 @@ static void pump_transfers(unsigned long data)
 			/* Update total byte transfered */
 			message->actual_length += drv_data->len_in_bytes;
 			/* Move to next transfer of this msg */
-			message->state = next_transfer(drv_data);
+			message->state = bfin_spi_next_transfer(drv_data);
 			if (drv_data->cs_change)
-				cs_deactive(drv_data, chip);
+				bfin_spi_cs_deactive(drv_data, chip);
 		}
 		/* Schedule next transfer tasklet */
 		tasklet_schedule(&drv_data->pump_transfers);
@@ -930,7 +930,7 @@ static void pump_transfers(unsigned long data)
 }
 
 /* pop a msg from queue and kick off real transfer */
-static void pump_messages(struct work_struct *work)
+static void bfin_spi_pump_messages(struct work_struct *work)
 {
 	struct driver_data *drv_data;
 	unsigned long flags;
@@ -958,7 +958,7 @@ static void pump_messages(struct work_struct *work)
 
 	/* Setup the SSP using the per chip configuration */
 	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
-	restore_state(drv_data);
+	bfin_spi_restore_state(drv_data);
 
 	list_del_init(&drv_data->cur_msg->queue);
 
@@ -987,7 +987,7 @@ static void pump_messages(struct work_struct *work)
  * got a msg to transfer, queue it in drv_data->queue.
  * And kick off message pumper
  */
-static int transfer(struct spi_device *spi, struct spi_message *msg)
+static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
 {
 	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
 	unsigned long flags;
@@ -1031,7 +1031,7 @@ static u16 ssel[][MAX_SPI_SSEL] = {
 };
 
 /* first setup for new devices */
-static int setup(struct spi_device *spi)
+static int bfin_spi_setup(struct spi_device *spi)
 {
 	struct bfin5xx_spi_chip *chip_info = NULL;
 	struct chip_data *chip;
@@ -1105,7 +1105,7 @@ static int setup(struct spi_device *spi)
 			return -ENODEV;
 		}
 		if (set_dma_callback(drv_data->dma_channel,
-		    dma_irq_handler, drv_data) < 0) {
+		    bfin_spi_dma_irq_handler, drv_data) < 0) {
 			dev_dbg(&spi->dev, "Unable to set dma callback\n");
 			return -EPERM;
 		}
@@ -1126,28 +1126,29 @@ static int setup(struct spi_device *spi)
 		chip->n_bytes = 1;
 		chip->width = CFG_SPI_WORDSIZE8;
 		chip->read = chip->cs_change_per_word ?
-			u8_cs_chg_reader : u8_reader;
+			bfin_spi_u8_cs_chg_reader : bfin_spi_u8_reader;
 		chip->write = chip->cs_change_per_word ?
-			u8_cs_chg_writer : u8_writer;
+			bfin_spi_u8_cs_chg_writer : bfin_spi_u8_writer;
 		chip->duplex = chip->cs_change_per_word ?
-			u8_cs_chg_duplex : u8_duplex;
+			bfin_spi_u8_cs_chg_duplex : bfin_spi_u8_duplex;
 		break;
 
 	case 16:
 		chip->n_bytes = 2;
 		chip->width = CFG_SPI_WORDSIZE16;
 		chip->read = chip->cs_change_per_word ?
-			u16_cs_chg_reader : u16_reader;
+			bfin_spi_u16_cs_chg_reader : bfin_spi_u16_reader;
 		chip->write = chip->cs_change_per_word ?
-			u16_cs_chg_writer : u16_writer;
+			bfin_spi_u16_cs_chg_writer : bfin_spi_u16_writer;
 		chip->duplex = chip->cs_change_per_word ?
-			u16_cs_chg_duplex : u16_duplex;
+			bfin_spi_u16_cs_chg_duplex : bfin_spi_u16_duplex;
 		break;
 
 	default:
 		dev_err(&spi->dev, "%d bits_per_word is not supported\n",
 				chip->bits_per_word);
-		kfree(chip);
+		if (chip_info)
+			kfree(chip);
 		return -ENODEV;
 	}
 
@@ -1164,7 +1165,7 @@ static int setup(struct spi_device *spi)
 		peripheral_request(ssel[spi->master->bus_num]
 			[chip->chip_select_num-1], spi->modalias);
 
-	cs_deactive(drv_data, chip);
+	bfin_spi_cs_deactive(drv_data, chip);
 
 	return 0;
 }
@@ -1173,7 +1174,7 @@ static int setup(struct spi_device *spi)
  * callback for spi framework.
  * clean driver specific data
  */
-static void cleanup(struct spi_device *spi)
+static void bfin_spi_cleanup(struct spi_device *spi)
 {
 	struct chip_data *chip = spi_get_ctldata(spi);
 
@@ -1185,7 +1186,7 @@ static void cleanup(struct spi_device *spi)
 	kfree(chip);
 }
 
-static inline int init_queue(struct driver_data *drv_data)
+static inline int bfin_spi_init_queue(struct driver_data *drv_data)
 {
 	INIT_LIST_HEAD(&drv_data->queue);
 	spin_lock_init(&drv_data->lock);
@@ -1195,10 +1196,10 @@ static inline int init_queue(struct driver_data *drv_data)
 
 	/* init transfer tasklet */
 	tasklet_init(&drv_data->pump_transfers,
-		     pump_transfers, (unsigned long)drv_data);
+		     bfin_spi_pump_transfers, (unsigned long)drv_data);
 
 	/* init messages workqueue */
-	INIT_WORK(&drv_data->pump_messages, pump_messages);
+	INIT_WORK(&drv_data->pump_messages, bfin_spi_pump_messages);
 	drv_data->workqueue =
 	    create_singlethread_workqueue(drv_data->master->dev.parent->bus_id);
 	if (drv_data->workqueue == NULL)
@@ -1207,7 +1208,7 @@ static inline int init_queue(struct driver_data *drv_data)
 	return 0;
 }
 
-static inline int start_queue(struct driver_data *drv_data)
+static inline int bfin_spi_start_queue(struct driver_data *drv_data)
 {
 	unsigned long flags;
 
@@ -1229,7 +1230,7 @@ static inline int start_queue(struct driver_data *drv_data)
 	return 0;
 }
 
-static inline int stop_queue(struct driver_data *drv_data)
+static inline int bfin_spi_stop_queue(struct driver_data *drv_data)
 {
 	unsigned long flags;
 	unsigned limit = 500;
@@ -1258,11 +1259,11 @@ static inline int stop_queue(struct driver_data *drv_data)
 	return status;
 }
 
-static inline int destroy_queue(struct driver_data *drv_data)
+static inline int bfin_spi_destroy_queue(struct driver_data *drv_data)
 {
 	int status;
 
-	status = stop_queue(drv_data);
+	status = bfin_spi_stop_queue(drv_data);
 	if (status != 0)
 		return status;
 
@@ -1271,7 +1272,7 @@ static inline int destroy_queue(struct driver_data *drv_data)
 	return 0;
 }
 
-static int __init bfin5xx_spi_probe(struct platform_device *pdev)
+static int __init bfin_spi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct bfin5xx_spi_master *platform_info;
@@ -1297,9 +1298,9 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
 
 	master->bus_num = pdev->id;
 	master->num_chipselect = platform_info->num_chipselect;
-	master->cleanup = cleanup;
-	master->setup = setup;
-	master->transfer = transfer;
+	master->cleanup = bfin_spi_cleanup;
+	master->setup = bfin_spi_setup;
+	master->transfer = bfin_spi_transfer;
 
 	/* Find and map our resources */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1324,13 +1325,13 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
 	}
 
 	/* Initial and start queue */
-	status = init_queue(drv_data);
+	status = bfin_spi_init_queue(drv_data);
 	if (status != 0) {
 		dev_err(dev, "problem initializing queue\n");
 		goto out_error_queue_alloc;
 	}
 
-	status = start_queue(drv_data);
+	status = bfin_spi_start_queue(drv_data);
 	if (status != 0) {
 		dev_err(dev, "problem starting queue\n");
 		goto out_error_queue_alloc;
@@ -1356,7 +1357,7 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
 	return status;
 
 out_error_queue_alloc:
-	destroy_queue(drv_data);
+	bfin_spi_destroy_queue(drv_data);
 out_error_no_dma_ch:
 	iounmap((void *) drv_data->regs_base);
 out_error_ioremap:
@@ -1367,7 +1368,7 @@ out_error_get_res:
 }
 
 /* stop hardware and remove the driver */
-static int __devexit bfin5xx_spi_remove(struct platform_device *pdev)
+static int __devexit bfin_spi_remove(struct platform_device *pdev)
 {
 	struct driver_data *drv_data = platform_get_drvdata(pdev);
 	int status = 0;
@@ -1376,7 +1377,7 @@ static int __devexit bfin5xx_spi_remove(struct platform_device *pdev)
 		return 0;
 
 	/* Remove the queue */
-	status = destroy_queue(drv_data);
+	status = bfin_spi_destroy_queue(drv_data);
 	if (status != 0)
 		return status;
 
@@ -1401,12 +1402,12 @@ static int __devexit bfin5xx_spi_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int bfin5xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
+static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	struct driver_data *drv_data = platform_get_drvdata(pdev);
 	int status = 0;
 
-	status = stop_queue(drv_data);
+	status = bfin_spi_stop_queue(drv_data);
 	if (status != 0)
 		return status;
 
@@ -1416,7 +1417,7 @@ static int bfin5xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
 	return 0;
 }
 
-static int bfin5xx_spi_resume(struct platform_device *pdev)
+static int bfin_spi_resume(struct platform_device *pdev)
 {
 	struct driver_data *drv_data = platform_get_drvdata(pdev);
 	int status = 0;
@@ -1425,7 +1426,7 @@ static int bfin5xx_spi_resume(struct platform_device *pdev)
 	bfin_spi_enable(drv_data);
 
 	/* Start the queue running */
-	status = start_queue(drv_data);
+	status = bfin_spi_start_queue(drv_data);
 	if (status != 0) {
 		dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
 		return status;
@@ -1434,29 +1435,29 @@ static int bfin5xx_spi_resume(struct platform_device *pdev)
 	return 0;
 }
 #else
-#define bfin5xx_spi_suspend NULL
-#define bfin5xx_spi_resume NULL
+#define bfin_spi_suspend NULL
+#define bfin_spi_resume NULL
 #endif				/* CONFIG_PM */
 
 MODULE_ALIAS("platform:bfin-spi");
-static struct platform_driver bfin5xx_spi_driver = {
+static struct platform_driver bfin_spi_driver = {
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
 	},
-	.suspend	= bfin5xx_spi_suspend,
-	.resume		= bfin5xx_spi_resume,
-	.remove		= __devexit_p(bfin5xx_spi_remove),
+	.suspend	= bfin_spi_suspend,
+	.resume		= bfin_spi_resume,
+	.remove		= __devexit_p(bfin_spi_remove),
 };
 
-static int __init bfin5xx_spi_init(void)
+static int __init bfin_spi_init(void)
 {
-	return platform_driver_probe(&bfin5xx_spi_driver, bfin5xx_spi_probe);
+	return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe);
 }
-module_init(bfin5xx_spi_init);
+module_init(bfin_spi_init);
 
-static void __exit bfin5xx_spi_exit(void)
+static void __exit bfin_spi_exit(void)
 {
-	platform_driver_unregister(&bfin5xx_spi_driver);
+	platform_driver_unregister(&bfin_spi_driver);
 }
-module_exit(bfin5xx_spi_exit);
+module_exit(bfin_spi_exit);
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 18/20] Blackfin SPI Driver: fix NULL pointer crash
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (16 preceding siblings ...)
  2009-02-06  7:13   ` [PATCH 17/20] Blackfin SPI Driver: use bfin_spi_ prefix on all functions Bryan Wu
@ 2009-02-06  7:13   ` Bryan Wu
  2009-02-06  7:13   ` [PATCH 19/20] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support Bryan Wu
  2009-02-06  7:13   ` [PATCH 20/20] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin Bryan Wu
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:13 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mike Frysinger

From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

fix NULL pointer crash when cleaning up from invalid platform resources

Signed-off-by: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index f9e1fbc..9459c42 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1178,6 +1178,9 @@ static void bfin_spi_cleanup(struct spi_device *spi)
 {
 	struct chip_data *chip = spi_get_ctldata(spi);
 
+	if (!chip)
+		return;
+
 	if ((chip->chip_select_num > 0)
 		&& (chip->chip_select_num <= spi->master->num_chipselect))
 		peripheral_free(ssel[spi->master->bus_num]
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 19/20] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (17 preceding siblings ...)
  2009-02-06  7:13   ` [PATCH 18/20] Blackfin SPI Driver: fix NULL pointer crash Bryan Wu
@ 2009-02-06  7:13   ` Bryan Wu
  2009-02-06  7:13   ` [PATCH 20/20] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin Bryan Wu
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:13 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Michael Hennerich

From: Michael Hennerich <michael.hennerich-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>

This patch adds support for GPIO controlled SPI Chip Selects.
To make use of this feature, set chip_select = 0 and add a proper
cs_gpio to your controller_data.

struct spi_board_info
        .chip_select = 0

struct bfin5xx_spi_chip
        .cs_gpio = GPIO_P###

There are various SPI devices that require SPI MODE_0,
and need to have the Chip Selects asserted during the entire transfer.
Consider using SPI_MODE_3 (SPI_CPHA | SPI_CPOL) if your device allows
it.

Signed-off-by: Michael Hennerich <michael.hennerich-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 arch/blackfin/include/asm/bfin5xx_spi.h |    1 +
 drivers/spi/spi_bfin5xx.c               |   40 ++++++++++++++++++++++++------
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h
index e1bb164..da8b9ca 100644
--- a/arch/blackfin/include/asm/bfin5xx_spi.h
+++ b/arch/blackfin/include/asm/bfin5xx_spi.h
@@ -124,6 +124,7 @@ struct bfin5xx_spi_chip {
 	u8 bits_per_word;
 	u8 cs_change_per_word;
 	u16 cs_chg_udelay; /* Some devices require 16-bit delays */
+	u32 cs_gpio;
 };
 
 #endif /* _SPI_CHANNEL_H_ */
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 9459c42..3e63a5d 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -111,6 +111,7 @@ struct chip_data {
 	u8 bits_per_word;	/* 8 or 16 */
 	u8 cs_change_per_word;
 	u16 cs_chg_udelay;	/* Some devices require > 255usec delay */
+	u32 cs_gpio;
 	void (*write) (struct driver_data *);
 	void (*read) (struct driver_data *);
 	void (*duplex) (struct driver_data *);
@@ -177,22 +178,30 @@ static int bfin_spi_flush(struct driver_data *drv_data)
 /* Chip select operation functions for cs_change flag */
 static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *chip)
 {
-	u16 flag = read_FLAG(drv_data);
+	if (likely(chip->chip_select_num)) {
+		u16 flag = read_FLAG(drv_data);
 
-	flag |= chip->flag;
-	flag &= ~(chip->flag << 8);
+		flag |= chip->flag;
+		flag &= ~(chip->flag << 8);
 
-	write_FLAG(drv_data, flag);
+		write_FLAG(drv_data, flag);
+	} else {
+		gpio_set_value(chip->cs_gpio, 0);
+	}
 }
 
 static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
 {
-	u16 flag = read_FLAG(drv_data);
+	if (likely(chip->chip_select_num)) {
+		u16 flag = read_FLAG(drv_data);
 
-	flag &= ~chip->flag;
-	flag |= (chip->flag << 8);
+		flag &= ~chip->flag;
+		flag |= (chip->flag << 8);
 
-	write_FLAG(drv_data, flag);
+		write_FLAG(drv_data, flag);
+	} else {
+		gpio_set_value(chip->cs_gpio, 1);
+	}
 
 	/* Move delay here for consistency */
 	if (chip->cs_chg_udelay)
@@ -1036,6 +1045,7 @@ static int bfin_spi_setup(struct spi_device *spi)
 	struct bfin5xx_spi_chip *chip_info = NULL;
 	struct chip_data *chip;
 	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	int ret;
 
 	/* Abort device setup if requested features are not supported */
 	if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {
@@ -1081,6 +1091,7 @@ static int bfin_spi_setup(struct spi_device *spi)
 		chip->bits_per_word = chip_info->bits_per_word;
 		chip->cs_change_per_word = chip_info->cs_change_per_word;
 		chip->cs_chg_udelay = chip_info->cs_chg_udelay;
+		chip->cs_gpio = chip_info->cs_gpio;
 	}
 
 	/* translate common spi framework into our register */
@@ -1121,6 +1132,16 @@ static int bfin_spi_setup(struct spi_device *spi)
 	chip->flag = 1 << (spi->chip_select);
 	chip->chip_select_num = spi->chip_select;
 
+	if (chip->chip_select_num == 0) {
+		ret = gpio_request(chip->cs_gpio, spi->modalias);
+		if (ret) {
+			if (drv_data->dma_requested)
+				free_dma(drv_data->dma_channel);
+			return ret;
+		}
+		gpio_direction_output(chip->cs_gpio, 1);
+	}
+
 	switch (chip->bits_per_word) {
 	case 8:
 		chip->n_bytes = 1;
@@ -1186,6 +1207,9 @@ static void bfin_spi_cleanup(struct spi_device *spi)
 		peripheral_free(ssel[spi->master->bus_num]
 					[chip->chip_select_num-1]);
 
+	if (chip->chip_select_num == 0)
+		gpio_free(chip->cs_gpio);
+
 	kfree(chip);
 }
 
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 20/20] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin
       [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
                     ` (18 preceding siblings ...)
  2009-02-06  7:13   ` [PATCH 19/20] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support Bryan Wu
@ 2009-02-06  7:13   ` Bryan Wu
  19 siblings, 0 replies; 21+ messages in thread
From: Bryan Wu @ 2009-02-06  7:13 UTC (permalink / raw)
  To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Yi Li,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Wolfgang Muees

From: Wolfgang Muees <wolfgang.mues-3FOdemwfcUYPyMaTEpOvjQ@public.gmane.org>

1. Rewrite of the non-dma data transfer functions to use only ONE
mode of TIMOD (TIMOD=0x1). With TIMOD=0, it was not possible to set
the TX bit pattern. So the TDBR = 0xFFFF inside the read calls won't
work.

2. Clear SPI_RDBR before reading and before duplex transfer. Otherwise
the garbage data in RDBR will get read. Since mmc_spi uses a lot of
duplex transfers, this is the main cause of mmc_spi failure.

3. Poll RXS for transfer completion. Polling SPIF or TXS cannot
guarantee transfer completion. This may interrupt a transfer before
it is finished. Also this may leave garbage data in buffer and
affect next transfer.

[Yi Li <yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>: add a field "u16 idle_tx_val" in "struct
bfin5xx_spi_chip" to specify the value to transmit if no TX value
is supplied.]

Signed-off-by: Wolfgang Muees <wolfgang.mues-3FOdemwfcUYPyMaTEpOvjQ@public.gmane.org>
Signed-off-by: Yi Li <yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 arch/blackfin/include/asm/bfin5xx_spi.h |    2 +
 drivers/spi/spi_bfin5xx.c               |  250 +++++++++++++-----------------
 2 files changed, 110 insertions(+), 142 deletions(-)

diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h
index da8b9ca..2202b9d 100644
--- a/arch/blackfin/include/asm/bfin5xx_spi.h
+++ b/arch/blackfin/include/asm/bfin5xx_spi.h
@@ -125,6 +125,8 @@ struct bfin5xx_spi_chip {
 	u8 cs_change_per_word;
 	u16 cs_chg_udelay; /* Some devices require 16-bit delays */
 	u32 cs_gpio;
+	/* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */
+	u16 idle_tx_val;
 };
 
 #endif /* _SPI_CHANNEL_H_ */
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 3e63a5d..a69c396 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -45,6 +45,9 @@ MODULE_LICENSE("GPL");
 #define QUEUE_RUNNING	0
 #define QUEUE_STOPPED	1
 
+/* Value to send if no TX value is supplied */
+#define SPI_IDLE_TXVAL 0x0000
+
 struct driver_data {
 	/* Driver model hookup */
 	struct platform_device *pdev;
@@ -112,6 +115,7 @@ struct chip_data {
 	u8 cs_change_per_word;
 	u16 cs_chg_udelay;	/* Some devices require > 255usec delay */
 	u32 cs_gpio;
+	u16 idle_tx_val;
 	void (*write) (struct driver_data *);
 	void (*read) (struct driver_data *);
 	void (*duplex) (struct driver_data *);
@@ -226,134 +230,126 @@ static void bfin_spi_restore_state(struct driver_data *drv_data)
 	bfin_spi_cs_active(drv_data, chip);
 }
 
-/* used to kick off transfer in rx mode */
-static unsigned short bfin_spi_dummy_read(struct driver_data *drv_data)
+/* used to kick off transfer in rx mode and read unwanted RX data */
+static inline void bfin_spi_dummy_read(struct driver_data *drv_data)
 {
-	unsigned short tmp;
-	tmp = read_RDBR(drv_data);
-	return tmp;
+	(void) read_RDBR(drv_data);
 }
 
 static void bfin_spi_null_writer(struct driver_data *drv_data)
 {
 	u8 n_bytes = drv_data->n_bytes;
+	u16 tx_val = drv_data->cur_chip->idle_tx_val;
+
+	/* clear RXS (we check for RXS inside the loop) */
+	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->tx < drv_data->tx_end) {
-		write_TDBR(drv_data, 0);
-		while ((read_STAT(drv_data) & BIT_STAT_TXS))
-			cpu_relax();
+		write_TDBR(drv_data, tx_val);
 		drv_data->tx += n_bytes;
+		/* wait until transfer finished.
+		   checking SPIF or TXS may not guarantee transfer completion */
+		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+			cpu_relax();
+		/* discard RX data and clear RXS */
+		bfin_spi_dummy_read(drv_data);
 	}
 }
 
 static void bfin_spi_null_reader(struct driver_data *drv_data)
 {
 	u8 n_bytes = drv_data->n_bytes;
+	u16 tx_val = drv_data->cur_chip->idle_tx_val;
+
+	/* discard old RX data and clear RXS */
 	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < drv_data->rx_end) {
+		write_TDBR(drv_data, tx_val);
+		drv_data->rx += n_bytes;
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
 		bfin_spi_dummy_read(drv_data);
-		drv_data->rx += n_bytes;
 	}
 }
 
 static void bfin_spi_u8_writer(struct driver_data *drv_data)
 {
-	dev_dbg(&drv_data->pdev->dev,
-		"cr8-s is 0x%x\n", read_STAT(drv_data));
+	/* clear RXS (we check for RXS inside the loop) */
+	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->tx < drv_data->tx_end) {
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
-		while (read_STAT(drv_data) & BIT_STAT_TXS)
+		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
+		/* wait until transfer finished.
+		   checking SPIF or TXS may not guarantee transfer completion */
+		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-		++drv_data->tx;
+		/* discard RX data and clear RXS */
+		bfin_spi_dummy_read(drv_data);
 	}
-
-	/* poll for SPI completion before return */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
 }
 
 static void bfin_spi_u8_cs_chg_writer(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
+	/* clear RXS (we check for RXS inside the loop) */
+	bfin_spi_dummy_read(drv_data);
+
 	while (drv_data->tx < drv_data->tx_end) {
 		bfin_spi_cs_active(drv_data, chip);
-
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
-		while (read_STAT(drv_data) & BIT_STAT_TXS)
-			cpu_relax();
-		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
+		/* make sure transfer finished before deactiving CS */
+		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-
+		bfin_spi_dummy_read(drv_data);
 		bfin_spi_cs_deactive(drv_data, chip);
-
-		++drv_data->tx;
 	}
 }
 
 static void bfin_spi_u8_reader(struct driver_data *drv_data)
 {
-	dev_dbg(&drv_data->pdev->dev,
-		"cr-8 is 0x%x\n", read_STAT(drv_data));
-
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
-	/* clear TDBR buffer before read(else it will be shifted out) */
-	write_TDBR(drv_data, 0xFFFF);
+	u16 tx_val = drv_data->cur_chip->idle_tx_val;
 
+	/* discard old RX data and clear RXS */
 	bfin_spi_dummy_read(drv_data);
 
-	while (drv_data->rx < drv_data->rx_end - 1) {
+	while (drv_data->rx < drv_data->rx_end) {
+		write_TDBR(drv_data, tx_val);
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-		*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
-		++drv_data->rx;
+		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
 	}
-
-	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-		cpu_relax();
-	*(u8 *) (drv_data->rx) = read_SHAW(drv_data);
-	++drv_data->rx;
 }
 
 static void bfin_spi_u8_cs_chg_reader(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
+	u16 tx_val = chip->idle_tx_val;
+
+	/* discard old RX data and clear RXS */
+	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->rx < drv_data->rx_end) {
 		bfin_spi_cs_active(drv_data, chip);
-		read_RDBR(drv_data);	/* kick off */
-
+		write_TDBR(drv_data, tx_val);
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-			cpu_relax();
-
-		*(u8 *) (drv_data->rx) = read_SHAW(drv_data);
+		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
 		bfin_spi_cs_deactive(drv_data, chip);
-
-		++drv_data->rx;
 	}
 }
 
 static void bfin_spi_u8_duplex(struct driver_data *drv_data)
 {
-	/* in duplex mode, clk is triggered by writing of TDBR */
+	/* discard old RX data and clear RXS */
+	bfin_spi_dummy_read(drv_data);
+
 	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
-		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-			cpu_relax();
+		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-		*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
-		++drv_data->rx;
-		++drv_data->tx;
+		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
 	}
 }
 
@@ -361,130 +357,102 @@ static void bfin_spi_u8_cs_chg_duplex(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
+	/* discard old RX data and clear RXS */
+	bfin_spi_dummy_read(drv_data);
+
 	while (drv_data->rx < drv_data->rx_end) {
 		bfin_spi_cs_active(drv_data, chip);
-
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
-
-		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-			cpu_relax();
+		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-		*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
-
+		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
 		bfin_spi_cs_deactive(drv_data, chip);
-
-		++drv_data->rx;
-		++drv_data->tx;
 	}
 }
 
 static void bfin_spi_u16_writer(struct driver_data *drv_data)
 {
-	dev_dbg(&drv_data->pdev->dev,
-		"cr16 is 0x%x\n", read_STAT(drv_data));
+	/* clear RXS (we check for RXS inside the loop) */
+	bfin_spi_dummy_read(drv_data);
 
 	while (drv_data->tx < drv_data->tx_end) {
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		while ((read_STAT(drv_data) & BIT_STAT_TXS))
-			cpu_relax();
 		drv_data->tx += 2;
+		/* wait until transfer finished.
+		   checking SPIF or TXS may not guarantee transfer completion */
+		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+			cpu_relax();
+		/* discard RX data and clear RXS */
+		bfin_spi_dummy_read(drv_data);
 	}
-
-	/* poll for SPI completion before return */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
 }
 
 static void bfin_spi_u16_cs_chg_writer(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
+	/* clear RXS (we check for RXS inside the loop) */
+	bfin_spi_dummy_read(drv_data);
+
 	while (drv_data->tx < drv_data->tx_end) {
 		bfin_spi_cs_active(drv_data, chip);
-
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		while ((read_STAT(drv_data) & BIT_STAT_TXS))
-			cpu_relax();
-		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+		drv_data->tx += 2;
+		/* make sure transfer finished before deactiving CS */
+		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-
+		bfin_spi_dummy_read(drv_data);
 		bfin_spi_cs_deactive(drv_data, chip);
-
-		drv_data->tx += 2;
 	}
 }
 
 static void bfin_spi_u16_reader(struct driver_data *drv_data)
 {
-	dev_dbg(&drv_data->pdev->dev,
-		"cr-16 is 0x%x\n", read_STAT(drv_data));
-
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
-	/* clear TDBR buffer before read(else it will be shifted out) */
-	write_TDBR(drv_data, 0xFFFF);
+	u16 tx_val = drv_data->cur_chip->idle_tx_val;
 
+	/* discard old RX data and clear RXS */
 	bfin_spi_dummy_read(drv_data);
 
-	while (drv_data->rx < (drv_data->rx_end - 2)) {
+	while (drv_data->rx < drv_data->rx_end) {
+		write_TDBR(drv_data, tx_val);
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
 		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
 		drv_data->rx += 2;
 	}
-
-	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-		cpu_relax();
-	*(u16 *) (drv_data->rx) = read_SHAW(drv_data);
-	drv_data->rx += 2;
 }
 
 static void bfin_spi_u16_cs_chg_reader(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
+	u16 tx_val = chip->idle_tx_val;
 
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
-	/* clear TDBR buffer before read(else it will be shifted out) */
-	write_TDBR(drv_data, 0xFFFF);
-
-	bfin_spi_cs_active(drv_data, chip);
+	/* discard old RX data and clear RXS */
 	bfin_spi_dummy_read(drv_data);
 
-	while (drv_data->rx < drv_data->rx_end - 2) {
-		bfin_spi_cs_deactive(drv_data, chip);
-
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_spi_cs_active(drv_data, chip);
+		write_TDBR(drv_data, tx_val);
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-		bfin_spi_cs_active(drv_data, chip);
 		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
 		drv_data->rx += 2;
+		bfin_spi_cs_deactive(drv_data, chip);
 	}
-	bfin_spi_cs_deactive(drv_data, chip);
-
-	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-		cpu_relax();
-	*(u16 *) (drv_data->rx) = read_SHAW(drv_data);
-	drv_data->rx += 2;
 }
 
 static void bfin_spi_u16_duplex(struct driver_data *drv_data)
 {
-	/* in duplex mode, clk is triggered by writing of TDBR */
-	while (drv_data->tx < drv_data->tx_end) {
+	/* discard old RX data and clear RXS */
+	bfin_spi_dummy_read(drv_data);
+
+	while (drv_data->rx < drv_data->rx_end) {
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-			cpu_relax();
+		drv_data->tx += 2;
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
 		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
 		drv_data->rx += 2;
-		drv_data->tx += 2;
 	}
 }
 
@@ -492,20 +460,18 @@ static void bfin_spi_u16_cs_chg_duplex(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
-	while (drv_data->tx < drv_data->tx_end) {
-		bfin_spi_cs_active(drv_data, chip);
+	/* discard old RX data and clear RXS */
+	bfin_spi_dummy_read(drv_data);
 
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_spi_cs_active(drv_data, chip);
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-			cpu_relax();
+		drv_data->tx += 2;
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
 		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-
-		bfin_spi_cs_deactive(drv_data, chip);
-
 		drv_data->rx += 2;
-		drv_data->tx += 2;
+		bfin_spi_cs_deactive(drv_data, chip);
 	}
 }
 
@@ -682,6 +648,13 @@ static void bfin_spi_pump_transfers(unsigned long data)
 		return;
 	}
 
+	if (transfer->len == 0) {
+		/* Move to next transfer of this msg */
+		message->state = bfin_spi_next_transfer(drv_data);
+		/* Schedule next transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+	}
+
 	if (transfer->tx_buf != NULL) {
 		drv_data->tx = (void *)transfer->tx_buf;
 		drv_data->tx_end = drv_data->tx + transfer->len;
@@ -837,9 +810,6 @@ static void bfin_spi_pump_transfers(unsigned long data)
 							(unsigned long) (drv_data->rx +
 							drv_data->len_in_bytes));
 
-			/* clear tx reg soformer data is not shifted out */
-			write_TDBR(drv_data, 0xFFFF);
-
 			dma_config |= WNR;
 			dma_start_addr = (unsigned long)drv_data->rx;
 			cr |= BIT_CTL_TIMOD_DMA_RX | BIT_CTL_SENDOPT;
@@ -881,6 +851,11 @@ static void bfin_spi_pump_transfers(unsigned long data)
 		/* IO mode write then read */
 		dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
 
+		/* we always use SPI_WRITE mode. SPI_READ mode
+		   seems to have problems with setting up the
+		   output value in TDBR prior to the transfer. */
+		write_CTRL(drv_data, (cr | CFG_SPI_WRITE));
+
 		if (full_duplex) {
 			/* full duplex mode */
 			BUG_ON((drv_data->tx_end - drv_data->tx) !=
@@ -888,9 +863,6 @@ static void bfin_spi_pump_transfers(unsigned long data)
 			dev_dbg(&drv_data->pdev->dev,
 				"IO duplex: cr is 0x%x\n", cr);
 
-			/* set SPI transfer mode */
-			write_CTRL(drv_data, (cr | CFG_SPI_WRITE));
-
 			drv_data->duplex(drv_data);
 
 			if (drv_data->tx != drv_data->tx_end)
@@ -900,9 +872,6 @@ static void bfin_spi_pump_transfers(unsigned long data)
 			dev_dbg(&drv_data->pdev->dev,
 				"IO write: cr is 0x%x\n", cr);
 
-			/* set SPI transfer mode */
-			write_CTRL(drv_data, (cr | CFG_SPI_WRITE));
-
 			drv_data->write(drv_data);
 
 			if (drv_data->tx != drv_data->tx_end)
@@ -912,9 +881,6 @@ static void bfin_spi_pump_transfers(unsigned long data)
 			dev_dbg(&drv_data->pdev->dev,
 				"IO read: cr is 0x%x\n", cr);
 
-			/* set SPI transfer mode */
-			write_CTRL(drv_data, (cr | CFG_SPI_READ));
-
 			drv_data->read(drv_data);
 			if (drv_data->rx != drv_data->rx_end)
 				tranf_success = 0;
@@ -934,7 +900,6 @@ static void bfin_spi_pump_transfers(unsigned long data)
 		}
 		/* Schedule next transfer tasklet */
 		tasklet_schedule(&drv_data->pump_transfers);
-
 	}
 }
 
@@ -1092,6 +1057,7 @@ static int bfin_spi_setup(struct spi_device *spi)
 		chip->cs_change_per_word = chip_info->cs_change_per_word;
 		chip->cs_chg_udelay = chip_info->cs_chg_udelay;
 		chip->cs_gpio = chip_info->cs_gpio;
+		chip->idle_tx_val = chip_info->idle_tx_val;
 	}
 
 	/* translate common spi framework into our register */
-- 
1.5.6.3

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com

^ permalink raw reply related	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2009-02-06  7:13 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-06  7:12 [PATCH 00/20] Blackfin SPI Driver fixing and updates Bryan Wu
     [not found] ` <1233904388-5765-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2009-02-06  7:12   ` [PATCH 01/20] Blackfin SPI Driver: ensure cache coherency before doing DMA Bryan Wu
2009-02-06  7:12   ` [PATCH 02/20] Blackfin SPI Driver: Fix erroneous SPI Clock divisor calculation Bryan Wu
2009-02-06  7:12   ` [PATCH 03/20] Blackfin SPI Driver: remove useless <asm/cplbinit.h> Bryan Wu
2009-02-06  7:12   ` [PATCH 04/20] Blackfin SPI Driver: use len_in_bytes when we care about the number of bytes transferred Bryan Wu
2009-02-06  7:12   ` [PATCH 05/20] Blackfin SPI Driver: pass DMA overflow error to the higher level Bryan Wu
2009-02-06  7:12   ` [PATCH 06/20] Blackfin SPI Driver: unify duplicated code in dma read/write paths Bryan Wu
2009-02-06  7:12   ` [PATCH 07/20] Blackfin SPI Driver: drop bogus cast and touchup dma label Bryan Wu
2009-02-06  7:12   ` [PATCH 08/20] Blackfin SPI Driver: add a few more DMA debug messages Bryan Wu
2009-02-06  7:12   ` [PATCH 09/20] Blackfin SPI Driver: do not check for SPI errors if DMA itself did not flag any Bryan Wu
2009-02-06  7:12   ` [PATCH 10/20] Blackfin SPI Driver: use the properl BIT_CTL_xxx defines Bryan Wu
2009-02-06  7:12   ` [PATCH 11/20] Blackfin SPI Driver: SPI slave select code cleanup Bryan Wu
2009-02-06  7:13   ` [PATCH 12/20] Blackfin SPI Driver: get dma working for SPI flashes Bryan Wu
2009-02-06  7:13   ` [PATCH 13/20] Blackfin SPI Driver: add timeout while waiting for SPIF in dma irq handler Bryan Wu
2009-02-06  7:13   ` [PATCH 14/20] Blackfin SPI Driver: tweak magic spi dma sequence to get it working on BF54x Bryan Wu
2009-02-06  7:13   ` [PATCH 15/20] Blackfin SPI Driver: fix bug - spi controller driver does not assert/deassert CS correctly Bryan Wu
2009-02-06  7:13   ` [PATCH 16/20] Blackfin SPI Driver: fix bug - correct usage of struct spi_transfer.cs_change Bryan Wu
2009-02-06  7:13   ` [PATCH 17/20] Blackfin SPI Driver: use bfin_spi_ prefix on all functions Bryan Wu
2009-02-06  7:13   ` [PATCH 18/20] Blackfin SPI Driver: fix NULL pointer crash Bryan Wu
2009-02-06  7:13   ` [PATCH 19/20] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support Bryan Wu
2009-02-06  7:13   ` [PATCH 20/20] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin Bryan Wu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).