public inbox for linux-mmc@vger.kernel.org
 help / color / mirror / Atom feed
From: Adrian Hunter <adrian.hunter@intel.com>
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>,
	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 15:04:27 +0200	[thread overview]
Message-ID: <a1e4f4fd-18b6-4bc0-a504-919d81dd4842@intel.com> (raw)
In-Reply-To: <20260309-orangepi-sd-card-uhs-v2-4-5bb2b574df5d@gmail.com>

On 09/03/2026 13:40, 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.

Need to say something about the HS200 support since it is
eMMC only

> 
> 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>
> ---
>  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
> +
> +#define SPACEMIT_TX_TUNING_DLINE_REG	0x00
> +#define SPACEMIT_TX_TUNING_DELAYCODE	127
>  
>  struct spacemit_sdhci_host {
>  	struct clk *clk_core;
> @@ -251,6 +257,118 @@ static unsigned int spacemit_sdhci_clk_get_max_clock(struct sdhci_host *host)
>  	return clk_get_rate(pltfm_host->clk);
>  }
>  
> +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;

Prefer to arrange local definitions/declarations in order of
descending line length e.g.

	int pass_len = 0, pass_start = 0, max_pass_len = 0, max_pass_start = 0;
	bool pass_window[SPACEMIT_RX_TUNE_DELAY_MAX + 1] = {false};
	struct mmc_host *mmc = host->mmc;
	struct mmc_ios ios = mmc->ios;
	u8 final_delay;
	int ret = 0;
	int i;

> +
> +	/*
> +	 * 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;
> +
> +	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) {
> +		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;
> +		}
> +	}
> +
> +	if (pass_len > max_pass_len) {
> +		max_pass_len = pass_len;
> +		max_pass_start = pass_start;
> +	}
> +
> +	if (max_pass_len < 3) {
> +		dev_err(mmc_dev(host->mmc), "Tuning failed: no stable window found\n");
> +		return -EIO;
> +	}
> +
> +	final_delay = max_pass_start + max_pass_len / 2;
> +	spacemit_sdhci_set_rx_delay(host, final_delay);
> +	ret = mmc_send_tuning(host->mmc, opcode, NULL);
> +	if (ret) {
> +		u8 retry_delays[] = {
> +			max_pass_start + max_pass_len / 4,
> +			max_pass_start + (3 * max_pass_len) / 4,
> +			max_pass_start,
> +			max_pass_start + max_pass_len - 1
> +		};
> +		int retry_count = ARRAY_SIZE(retry_delays);
> +
> +		dev_warn(mmc_dev(mmc), "Primary delay %d failed, trying alternatives\n",
> +			 final_delay);
> +
> +		for (i = 0; i < retry_count; i++) {
> +			if (retry_delays[i] >= SPACEMIT_RX_TUNE_DELAY_MIN &&
> +			    retry_delays[i] <= SPACEMIT_RX_TUNE_DELAY_MAX) {
> +				spacemit_sdhci_set_rx_delay(host, retry_delays[i]);
> +				ret = mmc_send_tuning(host->mmc, opcode, NULL);
> +				if (!ret) {
> +					final_delay = retry_delays[i];
> +					dev_info(mmc_dev(mmc), "Retry successful with delay %d\n",
> +						 final_delay);
> +					break;
> +				}
> +			}
> +		}
> +
> +		if (ret) {
> +			dev_err(mmc_dev(mmc), "All retry attempts failed\n");
> +			return -EIO;
> +		}
> +	}
> +
> +	dev_dbg(mmc_dev(host->mmc),
> +		"Tuning successful: window %d-%d, using delay %d\n",
> +		max_pass_start, max_pass_start + max_pass_len - 1, final_delay);
> +
> +	return 0;
> +}
> +
>  static int spacemit_sdhci_pre_select_hs400(struct mmc_host *mmc)
>  {
>  	struct sdhci_host *host = mmc_priv(mmc);
> @@ -344,6 +462,7 @@ static const struct sdhci_ops spacemit_sdhci_ops = {
>  	.set_clock		= spacemit_sdhci_set_clock,
>  	.set_uhs_signaling	= spacemit_sdhci_set_uhs_signaling,
>  	.voltage_switch         = spacemit_sdhci_voltage_switch,
> +	.platform_execute_tuning = spacemit_sdhci_execute_tuning,
>  };
>  
>  static const struct sdhci_pltfm_data spacemit_sdhci_k1_pdata = {
> 


  reply	other threads:[~2026-03-13 13:04 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 [this message]
2026-03-13 14:15   ` Yao Zi
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=a1e4f4fd-18b6-4bc0-a504-919d81dd4842@intel.com \
    --to=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