spi: bcm-qspi: choose sysclk setting based on requested speed
authorKamal Dasu <kdasu.kdev@gmail.com>
Wed, 24 Nov 2021 19:33:52 +0000 (14:33 -0500)
committerMark Brown <broonie@kernel.org>
Thu, 25 Nov 2021 11:54:36 +0000 (11:54 +0000)
Check requested speed for a given transfer before setting
27MHz or 108Mhz sysclk on SoCs that support both. This way
for baud rates below 212Khz we can use 27Mhz clock.

Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com>
Link: https://lore.kernel.org/r/20211124193353.32311-2-kdasu.kdev@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-bcm-qspi.c

index f3de330..38e6e2c 100644 (file)
@@ -287,6 +287,18 @@ static inline int bcm_qspi_spbr_min(struct bcm_qspi *qspi)
                return 8;
 }
 
+static u32 bcm_qspi_calc_spbr(u32 clk_speed_hz,
+                             const struct bcm_qspi_parms *xp)
+{
+       u32 spbr = 0;
+
+       /* SPBR = System Clock/(2 * SCK Baud Rate) */
+       if (xp->speed_hz)
+               spbr = clk_speed_hz / (xp->speed_hz * 2);
+
+       return spbr;
+}
+
 /* Read qspi controller register*/
 static inline u32 bcm_qspi_read(struct bcm_qspi *qspi, enum base_type type,
                                unsigned int offset)
@@ -621,9 +633,17 @@ static void bcm_qspi_hw_set_parms(struct bcm_qspi *qspi,
                        spcr |= MSPI_SPCR3_HALFDUPLEX |  MSPI_SPCR3_HDOUTTYPE;
 
                if (bcm_qspi_has_sysclk_108(qspi)) {
-                       /* SYSCLK_108 */
-                       spcr |= MSPI_SPCR3_SYSCLKSEL_108;
-                       qspi->base_clk = MSPI_BASE_FREQ * 4;
+                       /* check requested baud rate before moving to 108Mhz */
+                       spbr = bcm_qspi_calc_spbr(MSPI_BASE_FREQ * 4, xp);
+                       if (spbr > QSPI_SPBR_MAX) {
+                               /* use SYSCLK_27Mhz for slower baud rates */
+                               spcr &= ~MSPI_SPCR3_SYSCLKSEL_MASK;
+                               qspi->base_clk = MSPI_BASE_FREQ;
+                       } else {
+                               /* SYSCLK_108Mhz */
+                               spcr |= MSPI_SPCR3_SYSCLKSEL_108;
+                               qspi->base_clk = MSPI_BASE_FREQ * 4;
+                       }
                }
 
                if (xp->bits_per_word > 16) {
@@ -649,9 +669,9 @@ static void bcm_qspi_hw_set_parms(struct bcm_qspi *qspi,
                bcm_qspi_write(qspi, MSPI, MSPI_SPCR3, spcr);
        }
 
-       if (xp->speed_hz)
-               spbr = qspi->base_clk / (2 * xp->speed_hz);
-
+       /* SCK Baud Rate = System Clock/(2 * SPBR) */
+       qspi->max_speed_hz = qspi->base_clk / (bcm_qspi_spbr_min(qspi) * 2);
+       spbr = bcm_qspi_calc_spbr(qspi->base_clk, xp);
        spbr = clamp_val(spbr, bcm_qspi_spbr_min(qspi), QSPI_SPBR_MAX);
        bcm_qspi_write(qspi, MSPI, MSPI_SPCR0_LSB, spbr);