All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michał Mirosław" <mirq-linux@rere.qmqm.pl>
To: Adrian Hunter <adrian.hunter@intel.com>,
	Kevin Liu <kliu5@marvell.com>,
	Michal Simek <michal.simek@xilinx.com>,
	Suneel Garapati <suneel.garapati@xilinx.com>,
	Ulf Hansson <ulf.hansson@linaro.org>
Cc: linux-kernel@vger.kernel.org, linux-mmc@vger.kernel.org
Subject: [PATCH 6/7] mmc: sdhci: squash v2/v3+ clock calculation differences
Date: Thu, 02 Apr 2020 13:54:57 +0200	[thread overview]
Message-ID: <ea92e0e23c8cc79b960d9129aa64d0371e630b7f.1585827904.git.mirq-linux@rere.qmqm.pl> (raw)
In-Reply-To: <cover.1585827904.git.mirq-linux@rere.qmqm.pl>

SDHCI V2 differs from base-clock-V3+ only in allowed divisor values.
Remove the duplicate version of code. We can see now, that 'real_div'
can't be zero.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 drivers/mmc/host/sdhci.c | 106 ++++++++++++++++++---------------------
 1 file changed, 49 insertions(+), 57 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index d750c0997c3f..01fd897f8f3c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1756,82 +1756,74 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)
 u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
 		   unsigned int *actual_clock)
 {
-	unsigned int div = 0; /* Initialized for compiler warning */
-	int real_div = div, clk_mul = 1;
+	unsigned int div, real_div, clk_mul = 1;
 	u16 clk = 0;
-	bool use_base_clk;
 
 	if (clock == 0)
 		unreachable();
 
-	if (host->version >= SDHCI_SPEC_300) {
-		if (host->preset_enabled) {
-			u16 pre_val;
-
-			pre_val = sdhci_get_preset_value(host);
-			div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val);
-			if (pre_val & SDHCI_PRESET_CLKGEN_SEL) {
-				clk = SDHCI_PROG_CLOCK_MODE;
-				real_div = div + 1;
-				clk_mul = host->clk_mul ?: 1;
-			} else {
-				real_div = max_t(int, 1, div << 1);
-			}
+	if (host->preset_enabled) {
+		/* Only version 3.00+ can have preset_enabled */
+		u16 pre_val;
+
+		pre_val = sdhci_get_preset_value(host);
+		div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val);
+		if (pre_val & SDHCI_PRESET_CLKGEN_SEL) {
+			clk = SDHCI_PROG_CLOCK_MODE;
+			real_div = div + 1;
+			clk_mul = host->clk_mul ?: 1;
+		} else {
+			real_div = max_t(int, 1, div << 1);
+		}
+
+		goto clock_set;
+	}
+
+	/*
+	 * Check if the Host Controller supports Programmable Clock
+	 * Mode.
+	 */
+	if (host->version >= SDHCI_SPEC_300 && host->clk_mul) {
+		div = DIV_ROUND_UP(host->max_clk * host->clk_mul, clock);
+
+		if (div <= SDHCI_MAX_DIV_SPEC_300 / 2 + 1) {
+			/*
+			 * Set Programmable Clock Mode in the Clock
+			 * Control register.
+			 */
+			clk = SDHCI_PROG_CLOCK_MODE;
+			real_div = div;
+			clk_mul = host->clk_mul;
+			div--;
+
 			goto clock_set;
 		}
 
 		/*
-		 * Check if the Host Controller supports Programmable Clock
-		 * Mode.
+		 * Divisor is too big for requested clock rate.
+		 * Fall back to the base clock, then.
 		 */
-		use_base_clk = !host->clk_mul;
+	}
 
-		if (!use_base_clk) {
-			div = DIV_ROUND_UP(host->max_clk * host->clk_mul, clock);
+	div = DIV_ROUND_UP(host->max_clk, clock);
 
-			if (div <= SDHCI_MAX_DIV_SPEC_300 / 2 + 1) {
-				/*
-				 * Set Programmable Clock Mode in the Clock
-				 * Control register.
-				 */
-				clk = SDHCI_PROG_CLOCK_MODE;
-				real_div = div;
-				clk_mul = host->clk_mul;
-				div--;
-			} else {
-				/*
-				 * Divisor is too big for requested clock rate.
-				 * Use the base clock, then.
-				 */
-				use_base_clk = true;
-			}
-		}
+	if (div == 1 && (host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN))
+		div = 2;
 
-		if (use_base_clk) {
-			/* Version 3.00 divisors must be 1 or a multiple of 2. */
-			div = DIV_ROUND_UP(host->max_clk, clock);
-			if (div > 1) {
-				div = min(div, SDHCI_MAX_DIV_SPEC_300);
-				div = round_up(div, 2);
-			}
-			div >>= 1;
-			if (host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN)
-				div += !div;
-
-			real_div = div * 2 + !div;
-		}
+	if (host->version >= SDHCI_SPEC_300) {
+		/* Version 3.00 divisors must be a multiple of 2. */
+		div = min(div, SDHCI_MAX_DIV_SPEC_300);
+		div = DIV_ROUND_UP(div, 2);
 	} else {
 		/* Version 2.00 divisors must be a power of 2. */
-		div = DIV_ROUND_UP(host->max_clk, clock);
 		div = min(div, SDHCI_MAX_DIV_SPEC_200);
-		div = roundup_pow_of_two(div);
-		real_div = div;
-		div >>= 1;
+		div = roundup_pow_of_two(div) / 2;
 	}
 
+	real_div = div * 2 + !div;
+
 clock_set:
-	if (real_div)
-		*actual_clock = (host->max_clk * clk_mul) / real_div;
+	*actual_clock = (host->max_clk * clk_mul) / real_div;
 	clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
 	clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
 		<< SDHCI_DIVIDER_HI_SHIFT;
-- 
2.20.1


  parent reply	other threads:[~2020-04-02 11:55 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-02 11:54 [PATCH 0/7] SDHCI clock handling fixes and cleanups Michał Mirosław
2020-04-02 11:54 ` [PATCH 3/7] mmc: sdhci: fix SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN Michał Mirosław
2020-04-15 13:06   ` Adrian Hunter
2020-04-15 16:03     ` Michał Mirosław
2020-04-16  7:40       ` Adrian Hunter
2020-04-02 11:54 ` [PATCH 2/7] mmc: sdhci: fix programmable clock config from preset value Michał Mirosław
2020-04-15 12:44   ` Adrian Hunter
2020-04-02 11:54 ` [PATCH 1/7] mmc: sdhci: fix base clock usage in " Michał Mirosław
2020-04-15 12:25   ` Adrian Hunter
2020-04-15 16:28     ` Michał Mirosław
2020-04-16  8:26       ` Adrian Hunter
2020-04-17 13:55         ` Alan Cooper
2020-04-20  5:31           ` Adrian Hunter
2020-04-02 11:54 ` [PATCH 4/7] mmc: sdhci: move SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN frequency limit Michał Mirosław
2020-04-15 13:16   ` Adrian Hunter
2020-04-15 16:16     ` Michał Mirosław
2020-04-16  7:43       ` Adrian Hunter
2020-04-02 11:54 ` Michał Mirosław [this message]
2020-04-02 11:54 ` [PATCH 5/7] mmc: sdhci: simplify clock frequency calculation Michał Mirosław
2020-04-03 13:02   ` kbuild test robot
2020-04-03 13:02     ` kbuild test robot
2020-04-03 16:15     ` Michał Mirosław
2020-04-15 13:54   ` Adrian Hunter
2020-04-15 16:45     ` Michał Mirosław
2020-04-02 11:54 ` [PATCH 7/7] mmc: sdhci: respect non-zero div quirk in programmable clock mode Michał Mirosław
2020-04-03 16:03   ` kbuild test robot
2020-04-03 16:03     ` kbuild test robot
2020-04-15  8:52 ` [PATCH 0/7] SDHCI clock handling fixes and cleanups Ulf Hansson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ea92e0e23c8cc79b960d9129aa64d0371e630b7f.1585827904.git.mirq-linux@rere.qmqm.pl \
    --to=mirq-linux@rere.qmqm.pl \
    --cc=adrian.hunter@intel.com \
    --cc=kliu5@marvell.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=michal.simek@xilinx.com \
    --cc=suneel.garapati@xilinx.com \
    --cc=ulf.hansson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.