linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] Blackfin SPI Driver updates
@ 2009-02-05 10:07 Bryan Wu
  2009-02-05 10:07 ` [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions Bryan Wu
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Bryan Wu @ 2009-02-05 10:07 UTC (permalink / raw)
  To: dbrownell, spi-devel-general; +Cc: linux-kernel


Hi Dave,

We also got several Blackfin SPI Driver updates as well as former 16
patches I posted before and 2 patches about spi_lock/spi_unlock.

Please kindly take a look.

Thanks
-Bryan

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

* [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions
  2009-02-05 10:07 [PATCH 0/5] Blackfin SPI Driver updates Bryan Wu
@ 2009-02-05 10:07 ` Bryan Wu
  2009-02-05 22:12   ` Andrew Morton
  2009-02-05 10:07 ` [PATCH 2/5] Blackfin SPI Driver: add comment about full duplex dma according to David Brownell Bryan Wu
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Bryan Wu @ 2009-02-05 10:07 UTC (permalink / raw)
  To: dbrownell, spi-devel-general; +Cc: linux-kernel, Mike Frysinger, Bryan Wu

From: Mike Frysinger <vapier.adi@gmail.com>

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@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
---
 drivers/spi/spi_bfin5xx.c |  231 +++++++++++++++++++++++----------------------
 1 files changed, 116 insertions(+), 115 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 1a9d2ed..74c5bb9 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);
@@ -164,7 +164,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;
 
@@ -178,7 +178,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);
 
@@ -188,7 +188,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);
 
@@ -203,7 +203,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;
 
@@ -217,18 +217,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;
 
@@ -240,20 +240,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));
@@ -270,12 +270,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)
@@ -283,13 +283,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));
@@ -301,7 +301,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))
@@ -316,12 +316,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))
@@ -330,13 +330,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) {
@@ -351,12 +351,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)));
 
@@ -366,14 +366,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));
@@ -390,12 +390,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))
@@ -403,13 +403,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));
@@ -421,7 +421,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))
@@ -436,7 +436,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;
 
@@ -447,19 +447,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();
@@ -467,7 +467,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) {
@@ -482,12 +482,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))
@@ -496,7 +496,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;
@@ -504,7 +504,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;
@@ -523,7 +523,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;
@@ -544,7 +544,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)
@@ -554,7 +554,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;
@@ -604,10 +604,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 */
@@ -622,7 +622,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;
@@ -647,7 +647,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;
 	}
 
@@ -655,7 +655,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;
 	}
 
@@ -669,10 +669,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;
 	}
 
@@ -706,31 +706,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));
@@ -744,7 +744,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;
@@ -759,7 +759,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",
@@ -813,7 +813,7 @@ static void pump_transfers(unsigned long data)
 			 * in this mode
 			 */
 			message->status = 0;
-			giveback(drv_data);
+			bfin_spi_giveback(drv_data);
 			return;
 		}
 
@@ -918,9 +918,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);
@@ -929,7 +929,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;
@@ -986,7 +986,7 @@ static void pump_messages(struct work_struct *work)
 #endif
 	/* 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);
 
@@ -1014,7 +1014,7 @@ static void pump_messages(struct work_struct *work)
 /*
  * lock the spi bus for exclusive access
  */
-static int lock_bus(struct spi_device *spi)
+static int bfin_spi_lock_bus(struct spi_device *spi)
 {
 #ifdef CONFIG_SPI_BFIN_LOCK
 	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
@@ -1031,7 +1031,7 @@ static int lock_bus(struct spi_device *spi)
 	return 0;
 }
 
-static int unlock_bus(struct spi_device *spi)
+static int bfin_spi_unlock_bus(struct spi_device *spi)
 {
 #ifdef CONFIG_SPI_BFIN_LOCK
 	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
@@ -1048,7 +1048,7 @@ static int unlock_bus(struct spi_device *spi)
  * 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;
@@ -1092,7 +1092,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;
@@ -1166,7 +1166,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;
 		}
@@ -1187,28 +1187,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;
 	}
 
@@ -1225,7 +1226,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;
 }
@@ -1234,7 +1235,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);
 
@@ -1246,7 +1247,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);
@@ -1259,10 +1260,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)
@@ -1271,7 +1272,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;
 
@@ -1293,7 +1294,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;
@@ -1325,11 +1326,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;
 
@@ -1338,7 +1339,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;
@@ -1364,11 +1365,11 @@ 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->lock_bus = lock_bus;
-	master->unlock_bus = unlock_bus;
+	master->cleanup = bfin_spi_cleanup;
+	master->setup = bfin_spi_setup;
+	master->transfer = bfin_spi_transfer;
+	master->lock_bus = bfin_spi_lock_bus;
+	master->unlock_bus = bfin_spi_unlock_bus;
 
 	/* Find and map our resources */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1393,13 +1394,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;
@@ -1425,7 +1426,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:
@@ -1436,7 +1437,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;
@@ -1445,7 +1446,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;
 
@@ -1470,12 +1471,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;
 
@@ -1485,7 +1486,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;
@@ -1494,7 +1495,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;
@@ -1503,29 +1504,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

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

* [PATCH 2/5] Blackfin SPI Driver: add comment about full duplex dma according to David Brownell
  2009-02-05 10:07 [PATCH 0/5] Blackfin SPI Driver updates Bryan Wu
  2009-02-05 10:07 ` [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions Bryan Wu
@ 2009-02-05 10:07 ` Bryan Wu
  2009-02-05 10:07 ` [PATCH 3/5] Blackfin SPI Driver: fix NULL pointer crash Bryan Wu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 14+ messages in thread
From: Bryan Wu @ 2009-02-05 10:07 UTC (permalink / raw)
  To: dbrownell, spi-devel-general; +Cc: linux-kernel, Mike Frysinger, Bryan Wu

From: Mike Frysinger <vapier.adi@gmail.com>

Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
---
 drivers/spi/spi_bfin5xx.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 74c5bb9..ce24d5e 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -766,9 +766,10 @@ static void bfin_spi_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) {
-- 
1.5.6.3

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

* [PATCH 3/5] Blackfin SPI Driver: fix NULL pointer crash
  2009-02-05 10:07 [PATCH 0/5] Blackfin SPI Driver updates Bryan Wu
  2009-02-05 10:07 ` [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions Bryan Wu
  2009-02-05 10:07 ` [PATCH 2/5] Blackfin SPI Driver: add comment about full duplex dma according to David Brownell Bryan Wu
@ 2009-02-05 10:07 ` Bryan Wu
  2009-02-05 22:12   ` Andrew Morton
  2009-02-05 10:07 ` [PATCH 4/5] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support Bryan Wu
  2009-02-05 10:07 ` [PATCH 5/5] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin Bryan Wu
  4 siblings, 1 reply; 14+ messages in thread
From: Bryan Wu @ 2009-02-05 10:07 UTC (permalink / raw)
  To: dbrownell, spi-devel-general; +Cc: linux-kernel, Mike Frysinger, Bryan Wu

From: Mike Frysinger <vapier.adi@gmail.com>

fix NULL pointer crash when cleaning up from invalid platform resources

Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.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 ce24d5e..b6098b5 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1240,6 +1240,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

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

* [PATCH 4/5] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support
  2009-02-05 10:07 [PATCH 0/5] Blackfin SPI Driver updates Bryan Wu
                   ` (2 preceding siblings ...)
  2009-02-05 10:07 ` [PATCH 3/5] Blackfin SPI Driver: fix NULL pointer crash Bryan Wu
@ 2009-02-05 10:07 ` Bryan Wu
  2009-02-05 22:12   ` Andrew Morton
  2009-02-05 10:07 ` [PATCH 5/5] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin Bryan Wu
  4 siblings, 1 reply; 14+ messages in thread
From: Bryan Wu @ 2009-02-05 10:07 UTC (permalink / raw)
  To: dbrownell, spi-devel-general; +Cc: linux-kernel, Michael Hennerich, Bryan Wu

From: Michael Hennerich <michael.hennerich@analog.com>

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@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.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 b6098b5..5089afe 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -114,6 +114,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 *);
@@ -180,22 +181,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)
@@ -1098,6 +1107,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)) {
@@ -1143,6 +1153,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 */
@@ -1183,6 +1194,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;
@@ -1248,6 +1269,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

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

* [PATCH 5/5] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin
  2009-02-05 10:07 [PATCH 0/5] Blackfin SPI Driver updates Bryan Wu
                   ` (3 preceding siblings ...)
  2009-02-05 10:07 ` [PATCH 4/5] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support Bryan Wu
@ 2009-02-05 10:07 ` Bryan Wu
  2009-02-05 22:13   ` Andrew Morton
  4 siblings, 1 reply; 14+ messages in thread
From: Bryan Wu @ 2009-02-05 10:07 UTC (permalink / raw)
  To: dbrownell, spi-devel-general
  Cc: linux-kernel, Wolfgang Muees, Yi Li, Bryan Wu

From: Wolfgang Muees <wolfgang.mues@auerswald.de>

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@analog.com>: 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@auerswald.de>
Signed-off-by: Yi Li <yi.li@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
---
 arch/blackfin/include/asm/bfin5xx_spi.h |    2 +
 drivers/spi/spi_bfin5xx.c               |  247 ++++++++++++++-----------------
 2 files changed, 110 insertions(+), 139 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 5089afe..0f6c15a 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;
@@ -115,6 +118,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 *);
@@ -229,134 +233,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);
 	}
 }
 
@@ -364,130 +360,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;
 	}
 }
 
@@ -495,20 +463,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);
 	}
 }
 
@@ -685,6 +651,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;
@@ -881,6 +854,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 +866,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 +875,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 +884,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 +903,6 @@ static void bfin_spi_pump_transfers(unsigned long data)
 		}
 		/* Schedule next transfer tasklet */
 		tasklet_schedule(&drv_data->pump_transfers);
-
 	}
 }
 
@@ -1154,6 +1122,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

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

* Re: [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions
  2009-02-05 10:07 ` [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions Bryan Wu
@ 2009-02-05 22:12   ` Andrew Morton
       [not found]     ` <20090205141245.2945141e.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2009-02-05 22:12 UTC (permalink / raw)
  To: Bryan Wu; +Cc: dbrownell, spi-devel-general, linux-kernel, vapier.adi, cooloney

On Thu,  5 Feb 2009 18:07:29 +0800
Bryan Wu <cooloney@kernel.org> wrote:

> 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
> 

As usual, the driver core guys have gone trompling all over other people's code
and your patch doesn't apply to linux-next.

11 out of 61 hunks FAILED -- saving rejects to file drivers/spi/spi_bfin5xx.c.rej

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

* Re: [PATCH 3/5] Blackfin SPI Driver: fix NULL pointer crash
  2009-02-05 10:07 ` [PATCH 3/5] Blackfin SPI Driver: fix NULL pointer crash Bryan Wu
@ 2009-02-05 22:12   ` Andrew Morton
       [not found]     ` <20090205141250.cf66e663.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2009-02-05 22:12 UTC (permalink / raw)
  To: Bryan Wu; +Cc: dbrownell, spi-devel-general, linux-kernel, vapier.adi, cooloney

On Thu,  5 Feb 2009 18:07:31 +0800
Bryan Wu <cooloney@kernel.org> wrote:

> From: Mike Frysinger <vapier.adi@gmail.com>
> 
> fix NULL pointer crash when cleaning up from invalid platform resources
> 
> Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
> Signed-off-by: Bryan Wu <cooloney@kernel.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 ce24d5e..b6098b5 100644
> --- a/drivers/spi/spi_bfin5xx.c
> +++ b/drivers/spi/spi_bfin5xx.c
> @@ -1240,6 +1240,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]

This one looks like 2.6.29 material to me.

If you believe that it should be backported to earlier kernels then
please let me know.  indicating whcih kernel versions would help things
a bit, too.

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

* Re: [PATCH 4/5] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support
  2009-02-05 10:07 ` [PATCH 4/5] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support Bryan Wu
@ 2009-02-05 22:12   ` Andrew Morton
  0 siblings, 0 replies; 14+ messages in thread
From: Andrew Morton @ 2009-02-05 22:12 UTC (permalink / raw)
  To: Bryan Wu
  Cc: dbrownell, spi-devel-general, linux-kernel, michael.hennerich, cooloney

On Thu,  5 Feb 2009 18:07:32 +0800
Bryan Wu <cooloney@kernel.org> wrote:

> 
> 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.

Cannot apply this due to previously-mentioned driver-core-tramplings.

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

* Re: [PATCH 5/5] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin
  2009-02-05 10:07 ` [PATCH 5/5] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin Bryan Wu
@ 2009-02-05 22:13   ` Andrew Morton
  0 siblings, 0 replies; 14+ messages in thread
From: Andrew Morton @ 2009-02-05 22:13 UTC (permalink / raw)
  To: Bryan Wu
  Cc: dbrownell, spi-devel-general, linux-kernel, wolfgang.mues, yi.li,
	cooloney

On Thu,  5 Feb 2009 18:07:33 +0800
Bryan Wu <cooloney@kernel.org> wrote:

> 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@analog.com>: add a field "u16 idle_tx_val" in "struct
> bfin5xx_spi_chip" to specify the value to transmit if no TX value
> is supplied.]


again, driver-core has destroyed your patch.

There was no _need_ to take the unusual and undesirable step of
modifying SPI via an unrelated tree.

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

* Re: [PATCH 3/5] Blackfin SPI Driver: fix NULL pointer crash
       [not found]     ` <20090205141250.cf66e663.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
@ 2009-02-05 22:29       ` Mike Frysinger
  0 siblings, 0 replies; 14+ messages in thread
From: Mike Frysinger @ 2009-02-05 22:29 UTC (permalink / raw)
  To: Andrew Morton
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Thu, Feb 5, 2009 at 17:12, Andrew Morton wrote:
> On Thu,  5 Feb 2009 18:07:31 +0800 Bryan Wu wrote:
>> 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 ce24d5e..b6098b5 100644
>> --- a/drivers/spi/spi_bfin5xx.c
>> +++ b/drivers/spi/spi_bfin5xx.c
>> @@ -1240,6 +1240,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]
>
> This one looks like 2.6.29 material to me.
>
> If you believe that it should be backported to earlier kernels then
> please let me know.  indicating whcih kernel versions would help things
> a bit, too.

including with 2.6.29 would be a good thing ... we havent quite synced
up our development process enough yet to do that kind of tracking, so
all of our stuff just goes into "the next thing" ...
-mike

------------------------------------------------------------------------------
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] 14+ messages in thread

* Re: [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions
       [not found]     ` <20090205141245.2945141e.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
@ 2009-02-06  2:26       ` Bryan Wu
  2009-02-06  2:34       ` Stephen Rothwell
  1 sibling, 0 replies; 14+ messages in thread
From: Bryan Wu @ 2009-02-06  2:26 UTC (permalink / raw)
  To: Andrew Morton
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	vapier.adi-Re5JQEeQqe8AvxtiuMwx3w

On Fri, Feb 6, 2009 at 6:12 AM, Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org> wrote:
> On Thu,  5 Feb 2009 18:07:29 +0800
> Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>
>> 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
>>
>
> As usual, the driver core guys have gone trompling all over other people's code
> and your patch doesn't apply to linux-next.
>
> 11 out of 61 hunks FAILED -- saving rejects to file drivers/spi/spi_bfin5xx.c.rej
>

That is because our earlier 16 spi patches not merged. As David
request, I will fold those 16 spi patches with these 5 patches and
send them out later.

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] 14+ messages in thread

* Re: [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions
       [not found]     ` <20090205141245.2945141e.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
  2009-02-06  2:26       ` Bryan Wu
@ 2009-02-06  2:34       ` Stephen Rothwell
       [not found]         ` <20090206133436.199d9282.sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org>
  1 sibling, 1 reply; 14+ messages in thread
From: Stephen Rothwell @ 2009-02-06  2:34 UTC (permalink / raw)
  To: Andrew Morton
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	vapier.adi-Re5JQEeQqe8AvxtiuMwx3w


[-- Attachment #1.1: Type: text/plain, Size: 718 bytes --]

Hi Andrew,

On Thu, 5 Feb 2009 14:12:45 -0800 Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org> wrote:
>
> As usual, the driver core guys have gone trompling all over other people's code
> and your patch doesn't apply to linux-next.
> 
> 11 out of 61 hunks FAILED -- saving rejects to file drivers/spi/spi_bfin5xx.c.rej

To be fair, next-20090206 has one patch to that file it is a single hunk
and only affects 2 lines and the patch was cc'd to the spi folks (I can't
easily tell when as the driver-core stuff (being a quilt tree) gets
rebased often).

-- 
Cheers,
Stephen Rothwell                    sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org
http://www.canb.auug.org.au/~sfr/

[-- Attachment #1.2: Type: application/pgp-signature, Size: 197 bytes --]

[-- Attachment #2: Type: text/plain, Size: 467 bytes --]

------------------------------------------------------------------------------
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

[-- Attachment #3: Type: text/plain, Size: 210 bytes --]

_______________________________________________
spi-devel-general mailing list
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

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

* Re: [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions
       [not found]         ` <20090206133436.199d9282.sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org>
@ 2009-02-06  2:47           ` Andrew Morton
  0 siblings, 0 replies; 14+ messages in thread
From: Andrew Morton @ 2009-02-06  2:47 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	vapier.adi-Re5JQEeQqe8AvxtiuMwx3w

On Fri, 6 Feb 2009 13:34:36 +1100 Stephen Rothwell <sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org> wrote:

> Hi Andrew,
> 
> On Thu, 5 Feb 2009 14:12:45 -0800 Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org> wrote:
> >
> > As usual, the driver core guys have gone trompling all over other people's code
> > and your patch doesn't apply to linux-next.
> > 
> > 11 out of 61 hunks FAILED -- saving rejects to file drivers/spi/spi_bfin5xx.c.rej
> 
> To be fair

no, they don't deserve it!  They just got lucky this time ;)

>, next-20090206 has one patch to that file it is a single hunk
> and only affects 2 lines and the patch was cc'd to the spi folks (I can't
> easily tell when as the driver-core stuff (being a quilt tree) gets
> rebased often).

yup.

------------------------------------------------------------------------------
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] 14+ messages in thread

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

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-05 10:07 [PATCH 0/5] Blackfin SPI Driver updates Bryan Wu
2009-02-05 10:07 ` [PATCH 1/5] Blackfin SPI Driver: use bfin_spi_ prefix on all functions Bryan Wu
2009-02-05 22:12   ` Andrew Morton
     [not found]     ` <20090205141245.2945141e.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2009-02-06  2:26       ` Bryan Wu
2009-02-06  2:34       ` Stephen Rothwell
     [not found]         ` <20090206133436.199d9282.sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org>
2009-02-06  2:47           ` Andrew Morton
2009-02-05 10:07 ` [PATCH 2/5] Blackfin SPI Driver: add comment about full duplex dma according to David Brownell Bryan Wu
2009-02-05 10:07 ` [PATCH 3/5] Blackfin SPI Driver: fix NULL pointer crash Bryan Wu
2009-02-05 22:12   ` Andrew Morton
     [not found]     ` <20090205141250.cf66e663.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2009-02-05 22:29       ` Mike Frysinger
2009-02-05 10:07 ` [PATCH 4/5] Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support Bryan Wu
2009-02-05 22:12   ` Andrew Morton
2009-02-05 10:07 ` [PATCH 5/5] Blackfin SPI Driver: Make mmc_spi driver work on Blackfin Bryan Wu
2009-02-05 22:13   ` Andrew Morton

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).