From: Yao Zi <me@ziyao.cc>
To: Iker Pedrosa <ikerpedrosam@gmail.com>,
Ulf Hansson <ulf.hansson@linaro.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Adrian Hunter <adrian.hunter@intel.com>,
Paul Walmsley <pjw@kernel.org>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Alexandre Ghiti <alex@ghiti.fr>, Yixun Lan <dlan@kernel.org>
Cc: Michael Opdenacker <michael.opdenacker@rootcommit.com>,
Javier Martinez Canillas <javierm@redhat.com>,
linux-mmc@vger.kernel.org, devicetree@vger.kernel.org,
linux-riscv@lists.infradead.org, spacemit@lists.linux.dev,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 4/7] mmc: sdhci-of-k1: add comprehensive SDR tuning support
Date: Fri, 13 Mar 2026 14:15:23 +0000 [thread overview]
Message-ID: <abQb-wU4S1NrBPXk@pie> (raw)
In-Reply-To: <20260309-orangepi-sd-card-uhs-v2-4-5bb2b574df5d@gmail.com>
On Mon, Mar 09, 2026 at 12:40:14PM +0100, Iker Pedrosa wrote:
> Implement software tuning algorithm to enable UHS-I SDR modes for SD
> card operation. This adds both TX and RX delay line tuning based on the
> SpacemiT K1 controller capabilities.
>
> Key features:
> - Conditional tuning: only tune when SD card is present and for
> high-speed modes (≥100MHz)
> - TX tuning: configure transmit delay line with default values
> (dline_reg=0, delaycode=127) to ensure optimal signal output timing
> - RX tuning: test full delay range (0-255) with window detection
> algorithm to find optimal receive timing
> - Retry mechanism: multiple fallback delays within optimal window for
> improved reliability
> - Complete register support: add delay line control and configuration
> register definitions for fine-grained timing control
>
> Signed-off-by: Iker Pedrosa <ikerpedrosam@gmail.com>
Sorry for raising this late: I think PATCH 3 and PATCH 4 (this one)
should also be squashed together to form a complete functionality, I
also doubt otherwise whether compilers complain about unused static
functions with only PATCH 3 applied.
> ---
> drivers/mmc/host/sdhci-of-k1.c | 119 +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 119 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c
> index 79cb7c8d0b6d9c4206bf01721651c8efe8a173c9..d903851b9be0e1d21a2b30636f5e63a52cad0dc2 100644
> --- a/drivers/mmc/host/sdhci-of-k1.c
> +++ b/drivers/mmc/host/sdhci-of-k1.c
> @@ -84,6 +84,12 @@
> #define SDHC_TX_DLINE_REG_MASK GENMASK(23, 16)
>
> #define SPACEMIT_RX_DLINE_REG 9
> +#define SPACEMIT_RX_TUNE_DELAY_MIN 0x0
> +#define SPACEMIT_RX_TUNE_DELAY_MAX 0xFF
> +#define SPACEMIT_RX_TUNE_DELAY_STEP 0x1
I think the STEP constant isn't very helpful, to me its purpose is
quite obvious in spacemit_sdhci_execute_tuning(), and you could simplify
the tuning function without adding confusing magic numbers -- since the
constant is literally one.
> +#define SPACEMIT_TX_TUNING_DLINE_REG 0x00
> +#define SPACEMIT_TX_TUNING_DELAYCODE 127
...
> +static int spacemit_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
> +{
> + int ret = 0;
> + int i;
> + bool pass_window[SPACEMIT_RX_TUNE_DELAY_MAX + 1] = {false};
> + int pass_len = 0, pass_start = 0, max_pass_len = 0, max_pass_start = 0;
> + u8 final_delay;
> + struct mmc_host *mmc = host->mmc;
> + struct mmc_ios ios = mmc->ios;
> +
> + /*
> + * Tuning is required for SDR50/SDR104, HS200/HS400 cards and
> + * if clock frequency is greater than 100MHz in these modes.
> + */
> + if (host->clock < 100 * 1000 * 1000 ||
> + !(ios.timing == MMC_TIMING_MMC_HS200 ||
> + ios.timing == MMC_TIMING_UHS_SDR50 ||
> + ios.timing == MMC_TIMING_UHS_SDR104))
> + return 0;
> +
> + if (!(mmc->caps2 & MMC_CAP2_NO_SD) && !mmc->ops->get_cd(mmc))
> + return 0;
Is this check really necessary? Shouldn't this be handled in MMC core
instead?
> + if (mmc->caps2 & MMC_CAP2_NO_MMC) {
> + spacemit_sdhci_set_tx_dline_reg(host, SPACEMIT_TX_TUNING_DLINE_REG);
> + spacemit_sdhci_set_tx_delay(host, SPACEMIT_TX_TUNING_DELAYCODE);
> + spacemit_sdhci_tx_tuning_prepare(host);
> +
> + dev_dbg(mmc_dev(host->mmc), "TX tuning: dline_reg=%d, delaycode=%d\n",
> + SPACEMIT_TX_TUNING_DLINE_REG, SPACEMIT_TX_TUNING_DELAYCODE);
> + }
> +
> + spacemit_sdhci_prepare_tuning(host);
> +
> + for (i = SPACEMIT_RX_TUNE_DELAY_MIN; i <= SPACEMIT_RX_TUNE_DELAY_MAX;
> + i += SPACEMIT_RX_TUNE_DELAY_STEP) {
The last expression could be simply i++ if you drop
SPACEMIT_RX_TUNE_DELAY_STEP, this is still quite readable. Same for the
loop below.
> + spacemit_sdhci_set_rx_delay(host, i);
> +
> + ret = mmc_send_tuning(host->mmc, opcode, NULL);
> + pass_window[i] = (ret == 0);
> +
> + dev_dbg(mmc_dev(host->mmc), "RX delay %d: %s\n",
> + i, pass_window[i] ? "pass" : "fail");
> + }
> +
> + for (i = SPACEMIT_RX_TUNE_DELAY_MIN; i <= SPACEMIT_RX_TUNE_DELAY_MAX;
> + i += SPACEMIT_RX_TUNE_DELAY_STEP) {
> + if (pass_window[i]) {
> + if (pass_len == 0)
> + pass_start = i;
> + pass_len++;
> + } else {
> + if (pass_len > max_pass_len) {
> + max_pass_len = pass_len;
> + max_pass_start = pass_start;
> + }
> + pass_len = 0;
> + }
> + }
It seems pass_window is only used once in the later loop, why not
calculate and maintain the best window and its size on the fly? Then you
could get avoid of the pass_window buffer, and refactor a loop away.
Something like,
int current_size, max_window, max_size;
current_size = 0;
max_size = 0;
for (i = SPACEMIT_RX_TUNE_DELAY_MIN; i < SPACEMIT_RX_TUNE_DELAY_MAX;
i++) {
ret = /* try tuning ... */
if (ret) {
if (max_size < current_size) {
max_window = i - current_size;
max_size = current_size;
}
current_size = 0;
} else {
current_size++;
}
}
if (current_size > max_size) {
max_window = i - current_size;
max_size = current_size;
current_size = 0;
}
should work, too, and is simpler.
Regards,
Yao Zi
next prev parent reply other threads:[~2026-03-13 14:15 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-09 11:40 [PATCH v2 0/7] riscv: spacemit: enable SD card support with UHS modes for OrangePi RV2 Iker Pedrosa
2026-03-09 11:40 ` [PATCH v2 1/7] mmc: sdhci-of-k1: enable essential clock infrastructure for SD operation Iker Pedrosa
2026-03-13 13:04 ` Adrian Hunter
2026-03-16 9:04 ` Iker Pedrosa
2026-03-16 9:34 ` Adrian Hunter
2026-03-09 11:40 ` [PATCH v2 2/7] mmc: sdhci-of-k1: add regulator and pinctrl voltage switching support Iker Pedrosa
2026-03-09 13:22 ` Yixun Lan
2026-03-12 9:38 ` Iker Pedrosa
2026-03-13 13:04 ` Adrian Hunter
2026-03-09 11:40 ` [PATCH v2 3/7] mmc: sdhci-of-k1: add SDR tuning infrastructure Iker Pedrosa
2026-03-13 13:04 ` Adrian Hunter
2026-03-09 11:40 ` [PATCH v2 4/7] mmc: sdhci-of-k1: add comprehensive SDR tuning support Iker Pedrosa
2026-03-13 13:04 ` Adrian Hunter
2026-03-13 14:15 ` Yao Zi [this message]
2026-03-09 11:40 ` [PATCH v2 5/7] riscv: dts: spacemit: k1: add SD card controller and pinctrl support Iker Pedrosa
2026-03-09 11:40 ` [PATCH v2 6/7] riscv: dts: spacemit: k1-orangepi-rv2: add PMIC and power infrastructure Iker Pedrosa
2026-03-11 18:27 ` Trevor Gamblin
2026-03-13 0:19 ` Yixun Lan
2026-03-13 9:42 ` Iker Pedrosa
2026-03-13 11:11 ` Yixun Lan
2026-03-13 15:06 ` Iker Pedrosa
2026-03-09 11:40 ` [PATCH v2 7/7] riscv: dts: spacemit: k1-orangepi-rv2: add SD card support with UHS modes Iker Pedrosa
2026-03-13 11:20 ` Anand Moon
2026-03-13 13:54 ` Trevor Gamblin
2026-03-13 14:42 ` Anand Moon
2026-03-13 17:08 ` Trevor Gamblin
2026-03-09 18:49 ` [PATCH v2 0/7] riscv: spacemit: enable SD card support with UHS modes for OrangePi RV2 Anand Moon
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=abQb-wU4S1NrBPXk@pie \
--to=me@ziyao.cc \
--cc=adrian.hunter@intel.com \
--cc=alex@ghiti.fr \
--cc=aou@eecs.berkeley.edu \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dlan@kernel.org \
--cc=ikerpedrosam@gmail.com \
--cc=javierm@redhat.com \
--cc=krzk+dt@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mmc@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=michael.opdenacker@rootcommit.com \
--cc=palmer@dabbelt.com \
--cc=pjw@kernel.org \
--cc=robh@kernel.org \
--cc=spacemit@lists.linux.dev \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox