commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=0df9e77676274a698b30a3e0704c8c26b48a9c37 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk
Signed-off-by: Scott Jiang <[email protected]> --- drivers/spi/spi-bfin6xx.c | 78 +++++++++++++++++++++++---------------------- 1 files changed, 40 insertions(+), 38 deletions(-) diff --git a/drivers/spi/spi-bfin6xx.c b/drivers/spi/spi-bfin6xx.c index 816522a..e6e2546 100644 --- a/drivers/spi/spi-bfin6xx.c +++ b/drivers/spi/spi-bfin6xx.c @@ -27,17 +27,18 @@ #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/types.h> -#include <linux/workqueue.h> #include <asm/bfin6xx_spi.h> #include <asm/cacheflush.h> #include <asm/dma.h> #include <asm/portmux.h> -#define START_STATE ((void *)0) -#define RUNNING_STATE ((void *)1) -#define DONE_STATE ((void *)2) -#define ERROR_STATE ((void *)-1) +enum bfin_spi_state { + START_STATE, + RUNNING_STATE, + DONE_STATE, + ERROR_STATE +}; struct bfin_spi_master; @@ -90,6 +91,7 @@ struct bfin_spi_master { u32 ssel; unsigned long sclk; + enum bfin_spi_state state; const struct bfin_spi_transfer_ops *ops; }; @@ -343,28 +345,24 @@ static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = { /* test if there is more transfer to be done */ -static void *bfin_spi_next_transfer(struct bfin_spi_master *drv_data) +static void bfin_spi_next_transfer(struct bfin_spi_master *drv) { - struct spi_message *msg = drv_data->cur_msg; - struct spi_transfer *trans = drv_data->cur_transfer; + struct spi_message *msg = drv->cur_msg; + struct spi_transfer *t = drv->cur_transfer; /* Move to next transfer */ - if (trans->transfer_list.next != &msg->transfers) { - drv_data->cur_transfer = - list_entry(trans->transfer_list.next, + if (t->transfer_list.next != &msg->transfers) + t = list_entry(t->transfer_list.next, struct spi_transfer, transfer_list); - return RUNNING_STATE; - } else - return DONE_STATE; + else + t = NULL; } static void bfin_spi_giveback(struct bfin_spi_master *drv_data) { struct bfin_spi_device *chip = drv_data->cur_chip; - if (!drv_data->cs_change) - bfin_spi_cs_deactive(drv_data, chip); - + bfin_spi_cs_deactive(drv_data, chip); spi_finalize_current_message(drv_data->master); } @@ -386,14 +384,14 @@ static void bfin_spi_pump_transfers(unsigned long data) chip = drv_data->cur_chip; /* Handle for abort */ - if (message->state == ERROR_STATE) { + if (drv_data->state == ERROR_STATE) { message->status = -EIO; bfin_spi_giveback(drv_data); return; } /* Handle end of message */ - if (message->state == DONE_STATE) { + if (drv_data->state == DONE_STATE) { message->status = 0; bfin_spi_flush(drv_data); bfin_spi_giveback(drv_data); @@ -401,7 +399,7 @@ static void bfin_spi_pump_transfers(unsigned long data) } /* Delay if requested at end of transfer */ - if (message->state == RUNNING_STATE) { + if (drv_data->state == RUNNING_STATE) { previous = list_entry(transfer->transfer_list.prev, struct spi_transfer, transfer_list); if (previous->delay_usecs) @@ -418,7 +416,7 @@ static void bfin_spi_pump_transfers(unsigned long data) if ((transfer->len == 0) || (transfer->tx_buf == NULL && transfer->rx_buf == NULL)) { /* Move to next transfer of this msg */ - message->state = bfin_spi_next_transfer(drv_data); + bfin_spi_next_transfer(drv_data); /* Schedule next transfer tasklet */ tasklet_schedule(&drv_data->pump_transfers); return; @@ -467,7 +465,7 @@ static void bfin_spi_pump_transfers(unsigned long data) cr |= cr_width; bfin_write(&drv_data->regs->control, cr); - message->state = RUNNING_STATE; + drv_data->state = RUNNING_STATE; /* Speed setup (surely valid because already checked) */ if (transfer->speed_hz) @@ -534,7 +532,7 @@ static void bfin_spi_pump_transfers(unsigned long data) DMA_TO_DEVICE); if (dma_mapping_error(&message->spi->dev, drv_data->tx_dma_addr)) { - message->state = ERROR_STATE; + drv_data->state = ERROR_STATE; return; } @@ -544,7 +542,7 @@ static void bfin_spi_pump_transfers(unsigned long data) DMA_FROM_DEVICE); if (dma_mapping_error(&message->spi->dev, drv_data->rx_dma_addr)) { - message->state = ERROR_STATE; + drv_data->state = ERROR_STATE; dma_unmap_single(&message->spi->dev, drv_data->tx_dma_addr, drv_data->tx_dma_size, @@ -595,13 +593,13 @@ static void bfin_spi_pump_transfers(unsigned long data) } if (!tranf_success) { - message->state = ERROR_STATE; + drv_data->state = ERROR_STATE; } else { /* Update total byte transferred */ message->actual_length += drv_data->transfer_len; /* Move to next transfer of this msg */ - message->state = bfin_spi_next_transfer(drv_data); - if (drv_data->cs_change && message->state != DONE_STATE) { + bfin_spi_next_transfer(drv_data); + if (drv_data->cs_change) { bfin_spi_flush(drv_data); bfin_spi_cs_deactive(drv_data, chip); } @@ -620,7 +618,7 @@ static int bfin_spi_transfer_one_message(struct spi_master *master, drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); bfin_spi_restore_state(drv_data); - drv_data->cur_msg->state = START_STATE; + drv_data->state = START_STATE; drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, struct spi_transfer, transfer_list); @@ -762,11 +760,14 @@ static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id) u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma); clear_dma_irqstat(drv_data->tx_dma); - if (dma_stat & DMA_DONE) + if (dma_stat & DMA_DONE) { drv_data->tx_num++; - if (dma_stat & DMA_ERR) + } else { dev_err(&drv_data->master->dev, "spi tx dma error: %d\n", dma_stat); + if (drv_data->tx) + drv_data->state = ERROR_STATE; + } bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF); return IRQ_HANDLED; } @@ -779,17 +780,18 @@ static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma); clear_dma_irqstat(drv_data->rx_dma); - if (dma_stat & DMA_DONE) + if (dma_stat & DMA_DONE) { drv_data->rx_num++; - if (dma_stat & DMA_ERR) { - msg->state = ERROR_STATE; - dev_err(&drv_data->master->dev, - "spi rx dma error: %d\n", dma_stat); - } else { - msg->actual_length += drv_data->transfer_len; + /* we may fail on tx dma */ + if (drv_data->state != ERROR_STATE) + msg->actual_length += drv_data->transfer_len; if (drv_data->cs_change) bfin_spi_cs_deactive(drv_data, chip); - msg->state = bfin_spi_next_transfer(drv_data); + bfin_spi_next_transfer(drv_data); + } else { + drv_data->state = ERROR_STATE; + dev_err(&drv_data->master->dev, + "spi rx dma error: %d\n", dma_stat); } bfin_write(&drv_data->regs->tx_control, 0); bfin_write(&drv_data->regs->rx_control, 0);
_______________________________________________ Linux-kernel-commits mailing list [email protected] https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits
