]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
[PATCH] ARM: OMAP: omap_uwire byteswap bugfix
authorDavid Brownell <dbrownell@users.sourceforge.net>
Wed, 3 May 2006 12:12:56 +0000 (05:12 -0700)
committerTony Lindgren <tony@atomide.com>
Wed, 3 May 2006 12:12:56 +0000 (05:12 -0700)
Get rid of broken optimization in MicroWire driver:  don't try to morph
consecutive single-byte operations into one (faster) two-byte operation.
This resolves some byteswap problems.  (And consequently allows fixing
some bugs in at least the OMAP version of the ads7846 driver...)

Also, reject LSB-first device modes; this controller doesn't support them.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Tony Lindgren <tony@atomide.com>
drivers/spi/omap_uwire.c

index 8d2e4949eb4bb2c90cf33159575b2f64c1131ee1..97a1846fc9f94ae4f80673d0e1820b5ecd4c27db 100644 (file)
@@ -196,6 +196,9 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
        if (t->tx_buf && t->rx_buf)
                return -EPERM;
 
+       if (!bits)
+               bits = 8;
+
        w = spi->chip_select << 10;
        w |= CS_CMD;
 
@@ -206,18 +209,15 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
 
                /* write one or two bytes at a time */
                while (len >= 1) {
-                       /* tx is msb-aligned */
+                       /* tx bit 15 is first sent; we byteswap multibyte words
+                        * (msb-first) on the way out from memory.
+                        */
                        val = *buf++;
-                       if (len > 1 && (!bits || bits > 8)) {
-                               if (!bits)
-                                       bits = 16;
+                       if (bits > 8) {
                                bytes = 2;
                                val |= *buf++ << 8;
-                       } else {
-                               if (!bits || bits > 8)
-                                       bits = 8;
+                       } else
                                bytes = 1;
-                       }
                        val <<= 16 - bits;
 
 #ifdef VERBOSE
@@ -253,15 +253,10 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
 
                /* read one or two bytes at a time */
                while (len) {
-                       if (len > 1 && (!bits || bits > 8)) {
-                               if (!bits)
-                                       bits = 16;
+                       if (bits > 8) {
                                bytes = 2;
-                       } else {
-                               if (!bits || bits > 8)
-                                       bits = 8;
+                       } else
                                bytes = 1;
-                       }
 
                        /* start read */
                        val = START | w | (bits << 0);
@@ -275,7 +270,9 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
                                                RDRB, 0))
                                goto eio;
 
-                       /* rx is lsb-aligned */
+                       /* rx bit 0 is last received; multibyte words will
+                        * be properly byteswapped on the way to memory.
+                        */
                        val = uwire_read_reg(UWIRE_RDR);
                        val &= (1 << bits) - 1;
                        *buf++ = (u8) val;
@@ -320,6 +317,12 @@ static int uwire_setup(struct spi_device *spi)
                goto done;
        }
 
+       if (spi->mode & SPI_LSB_FIRST) {
+               pr_debug("%s: lsb first?\n", spi->dev.bus_id);
+               status = -EINVAL;
+               goto done;
+       }
+
        /* mode 0..3, clock inverted separately;
         * standard nCS signaling;
         * don't treat DI=high as "not ready"