X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fspi%2Fbfin_spi.c;h=f28d42b4893d5a30499af9e3ffc821eee03e3877;hb=25ae8aeb54a6ca89ba1fd11c00865b8fed9348b4;hp=bc3394ad59f76c8cda86baddc965606882ce989a;hpb=ca41ef301b21b3ac25af71750624e0b3d5ddbb3e;p=u-boot diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c index bc3394ad59..f28d42b489 100644 --- a/drivers/spi/bfin_spi.c +++ b/drivers/spi/bfin_spi.c @@ -52,6 +52,7 @@ void spi_cs_activate(struct spi_slave *slave) (read_SPI_FLG(bss) & ~((!bss->flg << 8) << slave->cs)) | (1 << slave->cs)); + SSYNC(); debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss)); } @@ -59,7 +60,20 @@ __attribute__((weak)) void spi_cs_deactivate(struct spi_slave *slave) { struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); - write_SPI_FLG(bss, read_SPI_FLG(bss) & ~(1 << slave->cs)); + u16 flg; + + /* make sure we force the cs to deassert rather than let the + * pin float back up. otherwise, exact timings may not be + * met some of the time leading to random behavior (ugh). + */ + flg = read_SPI_FLG(bss) | ((!bss->flg << 8) << slave->cs); + write_SPI_FLG(bss, flg); + SSYNC(); + debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss)); + + flg &= ~(1 << slave->cs); + write_SPI_FLG(bss, flg); + SSYNC(); debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss)); } @@ -71,6 +85,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { struct bfin_spi_slave *bss; + ulong sclk; u32 mmr_base; u32 baud; @@ -91,7 +106,11 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, default: return NULL; } - baud = get_sclk() / (2 * max_hz); + sclk = get_sclk(); + baud = sclk / (2 * max_hz); + /* baud should be rounded up */ + if (sclk % (2 * max_hz)) + baud += 1; if (baud < 2) baud = 2; else if (baud > (u16)-1) @@ -142,7 +161,7 @@ static void spi_portmux(struct spi_slave *slave) case 1: SET_MUX(f, 2, 1); f_fer |= PF7; break; case 2: /* see G above */ g_fer |= PG15; break; case 3: SET_MUX(h, 1, 3); f_fer |= PH4; break; - case 4: /* no muxing */ break; + case 4: /* no muxing */ h_fer |= PH8; break; case 5: SET_MUX(g, 1, 3); h_fer |= PG3; break; case 6: /* no muxing */ break; case 7: /* no muxing */ break; @@ -300,6 +319,10 @@ void spi_release_bus(struct spi_slave *slave) SSYNC(); } +#ifndef CONFIG_BFIN_SPI_IDLE_VAL +# define CONFIG_BFIN_SPI_IDLE_VAL 0xff +#endif + int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { @@ -326,7 +349,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, /* todo: take advantage of hardware fifos and setup RX dma */ while (bytes--) { - u8 value = (tx ? *tx++ : 0); + u8 value = (tx ? *tx++ : CONFIG_BFIN_SPI_IDLE_VAL); debug("%s: tx:%x ", __func__, value); write_SPI_TDBR(bss, value); SSYNC();