aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2008-02-29 15:16:16 +0100
committerChris Wright <chrisw@sous-sol.org>2008-03-24 11:47:32 -0700
commit495b375c8798fd9bd7d084bacad100d249a0ddf2 (patch)
tree04274320d668d6d5d4cda7107e796cbdff38faf5
parent061e98a971b62ce4ee25c6cbd88b46d9870d5d9f (diff)
atmel_spi: fix clock polarity
commit: f6febccd7f86fbe94858a4a32d9384cc014c9f40 The atmel_spi driver does not initialize clock polarity correctly (except for at91rm9200 CS0 channel) in some case. The atmel_spi driver uses gpio-controlled chipselect. OTOH spi clock signal is controlled by CSRn.CPOL bit, but this register controls clock signal correctly only in 'real transfer' duration. At the time of cs_activate() call, CSRn.CPOL will be initialized correctly, but the controller do not know which channel is to be used next, so clock signal will stay at the inactive state of last transfer. If clock polarity of new transfer and last transfer was differ, new transfer will start with wrong clock signal state. For example, if you started SPI MODE 2 or 3 transfer after SPI MODE 0 or 1 transfer, the clock signal state at the assertion of chipselect will be low. Of course this will violates SPI transfer. This patch is short term solution for this problem. It makes all CSRn.CPOL match for the transfer before activating chipselect. For longer term, the best fix might be to let NPCS0 stay selected permanently in MR and overwrite CSR0 with to the new slave's settings before asserting CS. Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Acked-by: Haavard Skinnemoen <hskinnemoen@atmel.com> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Chris Wright <chrisw@sous-sol.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/spi/atmel_spi.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index ff10808183a3..e9d795972071 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -85,6 +85,16 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
unsigned gpio = (unsigned) spi->controller_data;
unsigned active = spi->mode & SPI_CS_HIGH;
u32 mr;
+ int i;
+ u32 csr;
+ u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
+
+ /* Make sure clock polarity is correct */
+ for (i = 0; i < spi->master->num_chipselect; i++) {
+ csr = spi_readl(as, CSR0 + 4 * i);
+ if ((csr ^ cpol) & SPI_BIT(CPOL))
+ spi_writel(as, CSR0 + 4 * i, csr ^ SPI_BIT(CPOL));
+ }
mr = spi_readl(as, MR);
mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);