Merge tag 'mm-nonmm-stable-2023-04-27-16-01' of git://git.kernel.org/pub/scm/linux...
[linux-block.git] / drivers / spi / spi-fsl-spi.c
index 725d043488a1254038bcaad2a84aa2ae7e78da0d..106fe60a0a50bf604b64a5ccb64a4216b5901918 100644 (file)
@@ -145,10 +145,10 @@ static void fsl_spi_grlib_set_shifts(u32 *rx_shift, u32 *tx_shift,
        }
 }
 
-static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
-                               struct spi_device *spi,
-                               struct mpc8xxx_spi *mpc8xxx_spi,
-                               int bits_per_word)
+static void mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
+                                      struct spi_device *spi,
+                                      struct mpc8xxx_spi *mpc8xxx_spi,
+                                      int bits_per_word)
 {
        cs->rx_shift = 0;
        cs->tx_shift = 0;
@@ -161,8 +161,7 @@ static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
        } else if (bits_per_word <= 32) {
                cs->get_rx = mpc8xxx_spi_rx_buf_u32;
                cs->get_tx = mpc8xxx_spi_tx_buf_u32;
-       } else
-               return -EINVAL;
+       }
 
        if (mpc8xxx_spi->set_shifts)
                mpc8xxx_spi->set_shifts(&cs->rx_shift, &cs->tx_shift,
@@ -173,26 +172,6 @@ static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
        mpc8xxx_spi->tx_shift = cs->tx_shift;
        mpc8xxx_spi->get_rx = cs->get_rx;
        mpc8xxx_spi->get_tx = cs->get_tx;
-
-       return bits_per_word;
-}
-
-static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
-                               struct spi_device *spi,
-                               int bits_per_word)
-{
-       /* QE uses Little Endian for words > 8
-        * so transform all words > 8 into 8 bits
-        * Unfortnatly that doesn't work for LSB so
-        * reject these for now */
-       /* Note: 32 bits word, LSB works iff
-        * tfcr/rfcr is set to CPMFCR_GBL */
-       if (spi->mode & SPI_LSB_FIRST &&
-           bits_per_word > 8)
-               return -EINVAL;
-       if (bits_per_word > 8)
-               return 8; /* pretend its 8 bits */
-       return bits_per_word;
 }
 
 static int fsl_spi_setup_transfer(struct spi_device *spi,
@@ -219,15 +198,7 @@ static int fsl_spi_setup_transfer(struct spi_device *spi,
                hz = spi->max_speed_hz;
 
        if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
-               bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
-                                                          mpc8xxx_spi,
-                                                          bits_per_word);
-       else if (mpc8xxx_spi->flags & SPI_QE)
-               bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
-                                                         bits_per_word);
-
-       if (bits_per_word < 0)
-               return bits_per_word;
+               mspi_apply_cpu_mode_quirks(cs, spi, mpc8xxx_spi, bits_per_word);
 
        if (bits_per_word == 32)
                bits_per_word = 0;
@@ -292,18 +263,10 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
        if (t->bits_per_word)
                bits_per_word = t->bits_per_word;
 
-       if (bits_per_word > 8) {
-               /* invalid length? */
-               if (len & 1)
-                       return -EINVAL;
+       if (bits_per_word > 8)
                len /= 2;
-       }
-       if (bits_per_word > 16) {
-               /* invalid length? */
-               if (len & 1)
-                       return -EINVAL;
+       if (bits_per_word > 16)
                len /= 2;
-       }
 
        mpc8xxx_spi->tx = t->tx_buf;
        mpc8xxx_spi->rx = t->rx_buf;
@@ -359,6 +322,22 @@ static int fsl_spi_prepare_message(struct spi_controller *ctlr,
                                t->bits_per_word = 32;
                        else if ((t->len & 1) == 0)
                                t->bits_per_word = 16;
+               } else {
+                       /*
+                        * CPM/QE uses Little Endian for words > 8
+                        * so transform 16 and 32 bits words into 8 bits
+                        * Unfortnatly that doesn't work for LSB so
+                        * reject these for now
+                        * Note: 32 bits word, LSB works iff
+                        * tfcr/rfcr is set to CPMFCR_GBL
+                        */
+                       if (m->spi->mode & SPI_LSB_FIRST && t->bits_per_word > 8)
+                               return -EINVAL;
+                       if (t->bits_per_word == 16 || t->bits_per_word == 32)
+                               t->bits_per_word = 8; /* pretend its 8 bits */
+                       if (t->bits_per_word == 8 && t->len >= 256 &&
+                           (mpc8xxx_spi->flags & SPI_CPM1))
+                               t->bits_per_word = 16;
                }
        }
        return fsl_spi_setup_transfer(m->spi, first);
@@ -503,7 +482,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
        struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
        struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
        u32 slvsel;
-       u16 cs = spi->chip_select;
+       u16 cs = spi_get_chipselect(spi, 0);
 
        if (cs < mpc8xxx_spi->native_chipselects) {
                slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
@@ -592,8 +571,14 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
        if (mpc8xxx_spi->type == TYPE_GRLIB)
                fsl_spi_grlib_probe(dev);
 
-       master->bits_per_word_mask =
-               (SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32)) &
+       if (mpc8xxx_spi->flags & SPI_CPM_MODE)
+               master->bits_per_word_mask =
+                       (SPI_BPW_RANGE_MASK(4, 8) | SPI_BPW_MASK(16) | SPI_BPW_MASK(32));
+       else
+               master->bits_per_word_mask =
+                       (SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32));
+
+       master->bits_per_word_mask &=
                SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word);
 
        if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)