]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
spi: spi-fsl-dspi: Enable modified transfer protocol on S32G
authorAndra-Teodora Ilie <andra.ilie@nxp.com>
Thu, 22 May 2025 14:51:40 +0000 (15:51 +0100)
committerMark Brown <broonie@kernel.org>
Sun, 8 Jun 2025 22:35:36 +0000 (23:35 +0100)
S32G supports modified transfer protocol where both host and target
devices sample later in the SCK period than in Classic SPI mode to allow
the logic to tolerate more delays in device pads and board traces. Set
MTFE bit in MCR register for frequencies higher than 25MHz.

Signed-off-by: Andra-Teodora Ilie <andra.ilie@nxp.com>
Signed-off-by: Bogdan-Gabriel Roman <bogdan-gabriel.roman@nxp.com>
Signed-off-by: Larisa Grigore <larisa.grigore@nxp.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Link: https://patch.msgid.link/20250522-james-nxp-spi-v2-11-bea884630cfb@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-fsl-dspi.c

index a3efe1bd3b376efd275b6ba1abfff7994405a5b1..01af641fa757e997b6082e4920b99ddcae709440 100644 (file)
@@ -24,6 +24,7 @@
 
 #define SPI_MCR                                0x00
 #define SPI_MCR_HOST                   BIT(31)
+#define SPI_MCR_MTFE                   BIT(26)
 #define SPI_MCR_PCSIS(x)               ((x) << 16)
 #define SPI_MCR_CLR_TXF                        BIT(11)
 #define SPI_MCR_CLR_RXF                        BIT(10)
@@ -37,6 +38,7 @@
 
 #define SPI_CTAR(x)                    (0x0c + (((x) & GENMASK(2, 0)) * 4))
 #define SPI_CTAR_FMSZ(x)               (((x) << 27) & GENMASK(30, 27))
+#define SPI_CTAR_DBR                   BIT(31)
 #define SPI_CTAR_CPOL                  BIT(26)
 #define SPI_CTAR_CPHA                  BIT(25)
 #define SPI_CTAR_LSBFE                 BIT(24)
 
 #define DMA_COMPLETION_TIMEOUT         msecs_to_jiffies(3000)
 
+#define SPI_25MHZ                      25000000
+
 struct chip_data {
        u32                     ctar_val;
 };
@@ -346,6 +350,7 @@ struct fsl_dspi {
        const void                              *tx;
        void                                    *rx;
        u16                                     tx_cmd;
+       bool                                    mtf_enabled;
        const struct fsl_dspi_devtype_data      *devtype_data;
 
        struct completion                       xfer_done;
@@ -722,7 +727,7 @@ static void dspi_release_dma(struct fsl_dspi *dspi)
 }
 
 static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
-                          unsigned long clkrate)
+                          unsigned long clkrate, bool mtf_enabled)
 {
        /* Valid baud rate pre-scaler values */
        int pbr_tbl[4] = {2, 3, 5, 7};
@@ -739,7 +744,13 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
 
        for (i = 0; i < ARRAY_SIZE(brs); i++)
                for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) {
-                       scale = brs[i] * pbr_tbl[j];
+                       if (mtf_enabled) {
+                               /* In MTF mode DBR=1 so frequency is doubled */
+                               scale = (brs[i] * pbr_tbl[j]) / 2;
+                       } else {
+                               scale = brs[i] * pbr_tbl[j];
+                       }
+
                        if (scale >= scale_needed) {
                                if (scale < minscale) {
                                        minscale = scale;
@@ -1146,6 +1157,20 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
        return status;
 }
 
+static int dspi_set_mtf(struct fsl_dspi *dspi)
+{
+       if (spi_controller_is_target(dspi->ctlr))
+               return 0;
+
+       if (dspi->mtf_enabled)
+               regmap_update_bits(dspi->regmap, SPI_MCR, SPI_MCR_MTFE,
+                                  SPI_MCR_MTFE);
+       else
+               regmap_update_bits(dspi->regmap, SPI_MCR, SPI_MCR_MTFE, 0);
+
+       return 0;
+}
+
 static int dspi_setup(struct spi_device *spi)
 {
        struct fsl_dspi *dspi = spi_controller_get_devdata(spi->controller);
@@ -1204,7 +1229,16 @@ static int dspi_setup(struct spi_device *spi)
                cs_sck_delay, sck_cs_delay);
 
        clkrate = clk_get_rate(dspi->clk);
-       hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate);
+
+       if (is_s32g_dspi(dspi) && spi->max_speed_hz > SPI_25MHZ)
+               dspi->mtf_enabled = true;
+       else
+               dspi->mtf_enabled = false;
+
+       dspi_set_mtf(dspi);
+
+       hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate,
+                      dspi->mtf_enabled);
 
        /* Set PCS to SCK delay scale values */
        ns_delay_scale(&pcssck, &cssck, cs_sck_delay, clkrate);
@@ -1226,6 +1260,9 @@ static int dspi_setup(struct spi_device *spi)
                                  SPI_CTAR_PBR(pbr) |
                                  SPI_CTAR_BR(br);
 
+               if (dspi->mtf_enabled)
+                       chip->ctar_val |= SPI_CTAR_DBR;
+
                if (spi->mode & SPI_LSB_FIRST)
                        chip->ctar_val |= SPI_CTAR_LSBFE;
        }
@@ -1352,6 +1389,8 @@ static int dspi_resume(struct device *dev)
                return ret;
        }
 
+       dspi_set_mtf(dspi);
+
        if (dspi->irq)
                enable_irq(dspi->irq);