From d04371a116d102e587ba7aa4c329b441cdbea3f4 Mon Sep 17 00:00:00 2001 From: Todor I Mollov Date: Sat, 4 Apr 2009 06:53:06 -0400 Subject: Blackfin: spi: make cs deassert function deterministic Blackfin SPI driver was not driving the SPI chip-select high before putting the chip-select signals into tri-state mode. This is probably something that slipped by unnoticed in most designs. If the signals are put directly into a tri-state mode, then the board is relying on the pull-up resistors to pull up the chip-select before the next transaction. Most of the time this is fine, except when you have two transactions that follow each other very closely, such as the flash erase and read status register commands. In this case I was seeing a 500ns separation between the transactions. In my setup, with a 10kOhm pull-up, it would meet timing spec about half the time and resulted in intermittent errors. (A stronger pull up would fix this, but our design is targeted for low power consumption and a 3.3kOhm @ 3.3v is 3.3mW of needless power consumption.) I modified the spi_cs_deactivate() function in bfin_spi.c to drive the chip-selects high before putting them into tri-state. For me, this resulted in a rise time of 5ns instead of the previous rise time of about 1us, and fully satisfied the timing spec of the chip. Signed-off-by: Todor I Mollov Signed-off-by: Mike Frysinger --- drivers/spi/bfin_spi.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c index bc3394ad59..bc255ccc82 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)); } -- cgit v1.2.1 From a343ba87ea0320ca0a4ecfa2c42cd9d4f18883df Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Sat, 4 Apr 2009 07:45:57 -0400 Subject: Blackfin: nand: flush peripheral before polling it We need to make sure the data written to the nand flash controller makes it there before we start polling its status register. Otherwise, we may get stale data and return before the controller is actually ready. Signed-off-by: Graf Yang Signed-off-by: Mike Frysinger Acked-by: Scott Wood --- drivers/mtd/nand/bfin_nand.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/bfin_nand.c b/drivers/mtd/nand/bfin_nand.c index f6a0835b4b..f134ef100f 100644 --- a/drivers/mtd/nand/bfin_nand.c +++ b/drivers/mtd/nand/bfin_nand.c @@ -98,6 +98,7 @@ static void bfin_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) /* Contents do not matter */ bfin_write_NFC_DATA_RD(0x0000); + SSYNC(); while (!(bfin_read_NFC_IRQSTAT() & RD_RDY)) if (ctrlc()) -- cgit v1.2.1