Unverified Commit c74526f9 authored by Kamal Dasu's avatar Kamal Dasu Committed by Mark Brown
Browse files

spi: bcm-qspi: choose sysclk setting based on requested speed



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: default avatarKamal Dasu <kdasu.kdev@gmail.com>
Link: https://lore.kernel.org/r/20211124193353.32311-2-kdasu.kdev@gmail.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent b79332ef
Loading
Loading
Loading
Loading
+26 −6
Original line number Diff line number Diff line
@@ -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,10 +633,18 @@ 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 */
			/* 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) {
			/* data_reg_size 1 (64bit) */
@@ -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);