Skip to content

Commit

Permalink
spi/bfin_spi: fix CS handling
Browse files Browse the repository at this point in the history
The CS helper functions were toggling both the Flag Enable and the Flag
Value bits, but the Flag Value bit is ignored if the corresponding Flag
Enable bit is cleared.  So under high speed transactions, the CS sometimes
would not toggle properly.

Since it makes no sense to toggle the Flag Enable bit dynamically when we
actually want to control the Flag Value, do this when setting up the device
and then only handle toggling of the CS value during runtime.

Signed-off-by: Barry Song <barry.song@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
  • Loading branch information
Barry Song authored and Mike Frysinger committed Oct 18, 2010
1 parent f6a6d96 commit 8221610
Showing 1 changed file with 27 additions and 6 deletions.
33 changes: 27 additions & 6 deletions drivers/spi/spi_bfin5xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,7 @@ static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *c
if (likely(chip->chip_select_num)) {
u16 flag = read_FLAG(drv_data);

flag |= chip->flag;
flag &= ~(chip->flag << 8);
flag &= ~chip->flag;

write_FLAG(drv_data, flag);
} else {
Expand All @@ -202,8 +201,7 @@ static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data
if (likely(chip->chip_select_num)) {
u16 flag = read_FLAG(drv_data);

flag &= ~chip->flag;
flag |= (chip->flag << 8);
flag |= chip->flag;

write_FLAG(drv_data, flag);
} else {
Expand All @@ -215,6 +213,25 @@ static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data
udelay(chip->cs_chg_udelay);
}

/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
static inline void bfin_spi_cs_enable(struct driver_data *drv_data, struct chip_data *chip)
{
u16 flag = read_FLAG(drv_data);

flag |= (chip->flag >> 8);

write_FLAG(drv_data, flag);
}

static inline void bfin_spi_cs_disable(struct driver_data *drv_data, struct chip_data *chip)
{
u16 flag = read_FLAG(drv_data);

flag &= ~(chip->flag >> 8);

write_FLAG(drv_data, flag);
}

/* stop controller and re-config current chip*/
static void bfin_spi_restore_state(struct driver_data *drv_data)
{
Expand Down Expand Up @@ -1169,7 +1186,7 @@ static int bfin_spi_setup(struct spi_device *spi)
* SPI_BAUD, not the real baudrate
*/
chip->baud = hz_to_spi_baud(spi->max_speed_hz);
chip->flag = 1 << (spi->chip_select);
chip->flag = (1 << (spi->chip_select)) << 8;
chip->chip_select_num = spi->chip_select;

switch (chip->bits_per_word) {
Expand Down Expand Up @@ -1268,6 +1285,7 @@ static int bfin_spi_setup(struct spi_device *spi)
}
}

bfin_spi_cs_enable(drv_data, chip);
bfin_spi_cs_deactive(drv_data, chip);

return 0;
Expand Down Expand Up @@ -1299,14 +1317,17 @@ static int bfin_spi_setup(struct spi_device *spi)
static void bfin_spi_cleanup(struct spi_device *spi)
{
struct chip_data *chip = spi_get_ctldata(spi);
struct driver_data *drv_data = spi_master_get_devdata(spi->master);

if (!chip)
return;

if ((chip->chip_select_num > 0)
&& (chip->chip_select_num <= spi->master->num_chipselect))
&& (chip->chip_select_num <= spi->master->num_chipselect)) {
peripheral_free(ssel[spi->master->bus_num]
[chip->chip_select_num-1]);
bfin_spi_cs_disable(drv_data, chip);
}

if (chip->chip_select_num == 0)
gpio_free(chip->cs_gpio);
Expand Down

0 comments on commit 8221610

Please sign in to comment.