spi: fsl: Fix problem with multi message transfers
authorStefan Roese <sr@denx.de>
Fri, 31 Jan 2014 12:44:59 +0000 (13:44 +0100)
committerMark Brown <broonie@linaro.org>
Tue, 4 Feb 2014 11:33:39 +0000 (11:33 +0000)
When used via spidev with more than one messages to tranfer via
SPI_IOC_MESSAGE the current implementation would return with
-EINVAL, since bits_per_word and speed_hz are set in all
transfer structs. And in the 2nd loop status will stay at
-EINVAL as its not overwritten again via fsl_spi_setup_transfer().

This patch changes this behavious by first checking if one of
the messages uses different settings. If this is the case
the function will return with -EINVAL. If not, the messages
are transferred correctly.

Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
drivers/spi/spi-fsl-spi.c

index 119f7af..4dcb292 100644 (file)
@@ -362,18 +362,28 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
 static void fsl_spi_do_one_msg(struct spi_message *m)
 {
        struct spi_device *spi = m->spi;
-       struct spi_transfer *t;
+       struct spi_transfer *t, *first;
        unsigned int cs_change;
        const int nsecs = 50;
        int status;
 
-       cs_change = 1;
-       status = 0;
+       /* Don't allow changes if CS is active */
+       first = list_first_entry(&m->transfers, struct spi_transfer,
+                       transfer_list);
        list_for_each_entry(t, &m->transfers, transfer_list) {
-               if (t->bits_per_word || t->speed_hz) {
-                       /* Don't allow changes if CS is active */
+               if ((first->bits_per_word != t->bits_per_word) ||
+                       (first->speed_hz != t->speed_hz)) {
                        status = -EINVAL;
+                       dev_err(&spi->dev,
+                               "bits_per_word/speed_hz should be same for the same SPI transfer\n");
+                       return;
+               }
+       }
 
+       cs_change = 1;
+       status = -EINVAL;
+       list_for_each_entry(t, &m->transfers, transfer_list) {
+               if (t->bits_per_word || t->speed_hz) {
                        if (cs_change)
                                status = fsl_spi_setup_transfer(spi, t);
                        if (status < 0)