Merge tag 'spi-fix-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 23 Dec 2022 22:44:08 +0000 (14:44 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 23 Dec 2022 22:44:08 +0000 (14:44 -0800)
Pull spi fix from Mark Brown:
 "One driver specific change here which handles the case where a SPI
  device for some reason tries to change the bus speed during a message
  on fsl_spi hardware, this should be very unusual"

* tag 'spi-fix-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: fsl_spi: Don't change speed while chipselect is active

drivers/spi/spi-fsl-spi.c

index 731624f..9315214 100644 (file)
@@ -333,13 +333,26 @@ static int fsl_spi_prepare_message(struct spi_controller *ctlr,
 {
        struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(ctlr);
        struct spi_transfer *t;
+       struct spi_transfer *first;
+
+       first = list_first_entry(&m->transfers, struct spi_transfer,
+                                transfer_list);
 
        /*
         * In CPU mode, optimize large byte transfers to use larger
         * bits_per_word values to reduce number of interrupts taken.
+        *
+        * Some glitches can appear on the SPI clock when the mode changes.
+        * Check that there is no speed change during the transfer and set it up
+        * now to change the mode without having a chip-select asserted.
         */
-       if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) {
-               list_for_each_entry(t, &m->transfers, transfer_list) {
+       list_for_each_entry(t, &m->transfers, transfer_list) {
+               if (t->speed_hz != first->speed_hz) {
+                       dev_err(&m->spi->dev,
+                               "speed_hz cannot change during message.\n");
+                       return -EINVAL;
+               }
+               if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) {
                        if (t->len < 256 || t->bits_per_word != 8)
                                continue;
                        if ((t->len & 3) == 0)
@@ -348,7 +361,7 @@ static int fsl_spi_prepare_message(struct spi_controller *ctlr,
                                t->bits_per_word = 16;
                }
        }
-       return 0;
+       return fsl_spi_setup_transfer(m->spi, first);
 }
 
 static int fsl_spi_transfer_one(struct spi_controller *controller,