Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 109795
b: refs/heads/master
c: 8423597
h: refs/heads/master
i:
  109793: 46c9d8b
  109791: e404cc2
v: v3
  • Loading branch information
Ned Forrester authored and Linus Torvalds committed Sep 13, 2008
1 parent 0faada7 commit a5e4b80
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: aa77d96ba94326db4f50d2aa36602824dd03286a
refs/heads/master: 8423597d676615f3dd2d9ab36f59f147086b90b8
59 changes: 48 additions & 11 deletions trunk/drivers/spi/pxa2xx_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ struct driver_data {
size_t tx_map_len;
u8 n_bytes;
u32 dma_width;
int cs_change;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
Expand Down Expand Up @@ -406,8 +405,45 @@ static void giveback(struct driver_data *drv_data)
struct spi_transfer,
transfer_list);

/* Delay if requested before any change in chip select */
if (last_transfer->delay_usecs)
udelay(last_transfer->delay_usecs);

/* Drop chip select UNLESS cs_change is true or we are returning
* a message with an error, or next message is for another chip
*/
if (!last_transfer->cs_change)
drv_data->cs_control(PXA2XX_CS_DEASSERT);
else {
struct spi_message *next_msg;

/* Holding of cs was hinted, but we need to make sure
* the next message is for the same chip. Don't waste
* time with the following tests unless this was hinted.
*
* We cannot postpone this until pump_messages, because
* after calling msg->complete (below) the driver that
* sent the current message could be unloaded, which
* could invalidate the cs_control() callback...
*/

/* get a pointer to the next message, if any */
spin_lock_irqsave(&drv_data->lock, flags);
if (list_empty(&drv_data->queue))
next_msg = NULL;
else
next_msg = list_entry(drv_data->queue.next,
struct spi_message, queue);
spin_unlock_irqrestore(&drv_data->lock, flags);

/* see if the next and current messages point
* to the same chip
*/
if (next_msg && next_msg->spi != msg->spi)
next_msg = NULL;
if (!next_msg || msg->state == ERROR_STATE)
drv_data->cs_control(PXA2XX_CS_DEASSERT);
}

msg->state = NULL;
if (msg->complete)
Expand Down Expand Up @@ -490,10 +526,9 @@ static void dma_transfer_complete(struct driver_data *drv_data)
msg->actual_length += drv_data->len -
(drv_data->rx_end - drv_data->rx);

/* Release chip select if requested, transfer delays are
* handled in pump_transfers */
if (drv_data->cs_change)
drv_data->cs_control(PXA2XX_CS_DEASSERT);
/* Transfer delays and chip select release are
* handled in pump_transfers or giveback
*/

/* Move to next transfer */
msg->state = next_transfer(drv_data);
Expand Down Expand Up @@ -602,10 +637,9 @@ static void int_transfer_complete(struct driver_data *drv_data)
drv_data->cur_msg->actual_length += drv_data->len -
(drv_data->rx_end - drv_data->rx);

/* Release chip select if requested, transfer delays are
* handled in pump_transfers */
if (drv_data->cs_change)
drv_data->cs_control(PXA2XX_CS_DEASSERT);
/* Transfer delays and chip select release are
* handled in pump_transfers or giveback
*/

/* Move to next transfer */
drv_data->cur_msg->state = next_transfer(drv_data);
Expand Down Expand Up @@ -840,13 +874,17 @@ static void pump_transfers(unsigned long data)
return;
}

/* Delay if requested at end of transfer*/
/* Delay if requested at end of transfer before CS change */
if (message->state == RUNNING_STATE) {
previous = list_entry(transfer->transfer_list.prev,
struct spi_transfer,
transfer_list);
if (previous->delay_usecs)
udelay(previous->delay_usecs);

/* Drop chip select only if cs_change is requested */
if (previous->cs_change)
drv_data->cs_control(PXA2XX_CS_DEASSERT);
}

/* Check transfer length */
Expand Down Expand Up @@ -878,7 +916,6 @@ static void pump_transfers(unsigned long data)
drv_data->len = transfer->len & DCMD_LENGTH;
drv_data->write = drv_data->tx ? chip->write : null_writer;
drv_data->read = drv_data->rx ? chip->read : null_reader;
drv_data->cs_change = transfer->cs_change;

/* Change speed and bit per word on a per transfer */
cr0 = chip->cr0;
Expand Down

0 comments on commit a5e4b80

Please sign in to comment.