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