kernel/0053-fix-optimize-SDHCI-driver-tuning.patch
2024-12-19 16:34:44 -05:00

379 lines
11 KiB
Diff

From f982f99a479e566de3d92cb80bfd084c3d71f260 Mon Sep 17 00:00:00 2001
From: liangshuang <liangshuang@eswincomputing.com>
Date: Thu, 13 Jun 2024 14:55:45 +0800
Subject: [PATCH 053/219] fix:optimize SDHCI driver tuning.
Changelogs:
1.rmmove delay tuning in sd driver.
---
arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts | 10 +-
arch/riscv/boot/dts/eswin/eic7700-evb.dts | 8 +-
.../boot/dts/eswin/hifive-premier-550.dts | 7 +-
drivers/mmc/host/sdhci-of-eswin-sdio.c | 160 +++++-------------
4 files changed, 47 insertions(+), 138 deletions(-)
diff --git a/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts b/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts
index 7a3702e88b19..3b90f64fcdb2 100644
--- a/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts
+++ b/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts
@@ -482,12 +482,10 @@ &sdhci_emmc {
&sdio0 {
/* sd card */
status = "okay";
- delay_code = <0x23>;
- phase_code = <0x5>;
+ delay_code = <0x29>;
drive-impedance-ohm = <33>;
enable-cmd-pullup;
enable-data-pullup;
- enable_sw_tuning;
no-sdio;
no-mmc;
};
@@ -495,12 +493,10 @@ &sdio0 {
&sdio1 {
/* wifi module */
status = "okay";
- delay_code = <0x23>;
- phase_code = <0x5>;
+ delay_code = <0x29>;
drive-impedance-ohm = <33>;
enable-cmd-pullup;
enable-data-pullup;
- enable_sw_tuning;
non-removable;
no-sd;
no-mmc;
@@ -923,4 +919,4 @@ &gpio0 {
};
&dev_llc_d0{
apply_npu_high_freq;
-};
\ No newline at end of file
+};
diff --git a/arch/riscv/boot/dts/eswin/eic7700-evb.dts b/arch/riscv/boot/dts/eswin/eic7700-evb.dts
index 5e18922ba44a..fd94c6a3aeea 100644
--- a/arch/riscv/boot/dts/eswin/eic7700-evb.dts
+++ b/arch/riscv/boot/dts/eswin/eic7700-evb.dts
@@ -453,11 +453,10 @@ &sdhci_emmc {
&sdio0 {
/* sd card */
status = "okay";
- delay_code = <0x16>;
+ delay_code = <0x29>;
drive-impedance-ohm = <33>;
enable-cmd-pullup;
enable-data-pullup;
- enable_sw_tuning;
no-sdio;
no-mmc;
};
@@ -465,11 +464,10 @@ &sdio0 {
&sdio1 {
/* wifi module */
status = "okay";
- delay_code = <0x21>;
+ delay_code = <0x29>;
drive-impedance-ohm = <33>;
enable-cmd-pullup;
enable-data-pullup;
- enable_sw_tuning;
non-removable;
no-sd;
no-mmc;
@@ -900,4 +898,4 @@ &gpio0 {
};
&dev_llc_d0{
apply_npu_high_freq;
-};
\ No newline at end of file
+};
diff --git a/arch/riscv/boot/dts/eswin/hifive-premier-550.dts b/arch/riscv/boot/dts/eswin/hifive-premier-550.dts
index 2b08a6bbfd2a..bfb59b7d6eb5 100644
--- a/arch/riscv/boot/dts/eswin/hifive-premier-550.dts
+++ b/arch/riscv/boot/dts/eswin/hifive-premier-550.dts
@@ -390,12 +390,10 @@ &sdhci_emmc {
&sdio0 {
/* sd card */
status = "okay";
- delay_code = <0x16>;
- phase_code = <0x1f>;
+ delay_code = <0x29>;
drive-impedance-ohm = <33>;
enable-cmd-pullup;
enable-data-pullup;
- enable_sw_tuning;
no-sdio;
no-mmc;
};
@@ -403,11 +401,10 @@ &sdio0 {
&sdio1 {
/* wifi module */
status = "okay";
- delay_code = <0x21>;
+ delay_code = <0x29>;
drive-impedance-ohm = <33>;
enable-cmd-pullup;
enable-data-pullup;
- enable_sw_tuning;
non-removable;
no-sd;
no-mmc;
diff --git a/drivers/mmc/host/sdhci-of-eswin-sdio.c b/drivers/mmc/host/sdhci-of-eswin-sdio.c
index badbee00b39e..d5ae6a5694f6 100644
--- a/drivers/mmc/host/sdhci-of-eswin-sdio.c
+++ b/drivers/mmc/host/sdhci-of-eswin-sdio.c
@@ -42,12 +42,7 @@
#define ESWIN_SDHCI_SD1_INT_STATUS 0x708
#define ESWIN_SDHCI_SD1_PWR_CTRL 0x70c
-#define DELAY_RANGE_THRESHOLD 20
-
-struct eswin_sdio_private {
- int phase_code;
- unsigned int enable_sw_tuning;
-};
+#define TUNING_RANGE_THRESHOLD 40
static inline void *sdhci_sdio_priv(struct eswin_sdhci_data *sdio)
{
@@ -177,109 +172,54 @@ static void eswin_sdhci_sdio_reset(struct sdhci_host *host, u8 mask)
}
}
-static int eswin_sdhci_sdio_delay_tuning(struct sdhci_host *host, u32 opcode)
-{
- int ret;
- int delay = -1;
- int i = 0;
- int delay_min = -1;
- int delay_max = -1;
- int delay_range = -1;
-
- int cmd_error = 0;
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct eswin_sdhci_data *eswin_sdhci =
- sdhci_pltfm_priv(pltfm_host);
-
- for (i = 0; i <= PHY_DELAY_CODE_MAX; i++) {
- eswin_sdhci_disable_card_clk(host);
- eswin_sdhci_sdio_config_phy_delay(host, i);
- eswin_sdhci_enable_card_clk(host);
- ret = mmc_send_tuning(host->mmc, opcode, &cmd_error);
- host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
- if (ret) {
- pr_debug("%s: bad delay:0x%x!\n", mmc_hostname(host->mmc), i);
- if (delay_min != -1 && delay_max != -1) {
- if (delay_max - delay_min > delay_range) {
- delay_range = delay_max - delay_min;
- delay = (delay_min + delay_max) / 2;
- if (delay_range > DELAY_RANGE_THRESHOLD)
- break;
- }
- delay_min = -1;
- delay_max = -1;
- }
- } else {
- pr_debug("%s: ok delay:0x%x\n", mmc_hostname(host->mmc), i);
- if (delay_min == -1) {
- delay_min = i;
- }
- delay_max = i;
- if (i == PHY_DELAY_CODE_MAX) {
- if (delay_max - delay_min > delay_range) {
- delay_range = delay_max - delay_min;
- delay = (delay_min + delay_max) / 2;
- }
- }
- continue;
- }
- }
-
- if (delay == -1) {
- pr_err("%s: delay code tuning failed!\n",
- mmc_hostname(host->mmc));
- eswin_sdhci_disable_card_clk(host);
- eswin_sdhci_sdio_config_phy_delay(host,
- eswin_sdhci->phy.delay_code);
- eswin_sdhci_enable_card_clk(host);
-
- return ret;
- }
-
- pr_info("%s: set delay:0x%x\n", mmc_hostname(host->mmc), delay);
- eswin_sdhci_disable_card_clk(host);
- eswin_sdhci_sdio_config_phy_delay(host, delay);
- eswin_sdhci_enable_card_clk(host);
-
- ret = mmc_send_tuning(host->mmc, opcode, &cmd_error);
- host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
- if (ret) {
- pr_err("%s: delay code(0x%x) not work, tuning failed!\n",
- mmc_hostname(host->mmc), delay);
- return ret;
- }
-
- return 0;
-}
-
static int eswin_sdhci_sdio_phase_code_tuning(struct sdhci_host *host,
u32 opcode)
{
int cmd_error = 0;
int ret = 0;
- int phase_code = 0;
+ int phase_code = -1;
int code_min = -1;
int code_max = -1;
+ int code_range = -1;
+ int i = 0;
- for (phase_code = 0; phase_code <= MAX_PHASE_CODE; phase_code++) {
+ for (i = 0; i <= MAX_PHASE_CODE; i++) {
eswin_sdhci_disable_card_clk(host);
- sdhci_writew(host, phase_code, VENDOR_AT_SATA_R);
+ sdhci_writew(host, i, VENDOR_AT_SATA_R);
eswin_sdhci_enable_card_clk(host);
ret = mmc_send_tuning(host->mmc, opcode, &cmd_error);
host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
if (ret) {
- pr_debug("%s: bad phase_code:0x%x\n", mmc_hostname(host->mmc), phase_code);
- if (code_min != -1 && code_max != -1)
- break;
+ udelay(200);
+ pr_debug("%s: bad phase_code:0x%x!\n", mmc_hostname(host->mmc), i);
+ if (code_min != -1 && code_max != -1) {
+ if (code_max - code_min > code_range) {
+ code_range = code_max - code_min;
+ phase_code = (code_min + code_max) / 2;
+ if (code_range > TUNING_RANGE_THRESHOLD)
+ break;
+ }
+ code_min = -1;
+ code_max = -1;
+ }
} else {
+ pr_debug("%s: ok phase_code:0x%x\n", mmc_hostname(host->mmc), i);
if (code_min == -1) {
- code_min = phase_code;
+ code_min = i;
}
- code_max = phase_code;
+ code_max = i;
+ if (i == MAX_PHASE_CODE) {
+ if (code_max - code_min > code_range) {
+ code_range = code_max - code_min;
+ phase_code = (code_min + code_max) / 2;
+ }
+ }
+ continue;
}
}
- if (code_min == -1 && code_max == -1) {
+
+ if (phase_code == -1) {
pr_err("%s: phase code tuning failed!\n",
mmc_hostname(host->mmc));
eswin_sdhci_disable_card_clk(host);
@@ -288,13 +228,20 @@ static int eswin_sdhci_sdio_phase_code_tuning(struct sdhci_host *host,
return -EIO;
}
- phase_code = (code_min + code_max) / 2;
pr_info("%s: set phase_code:0x%x\n", mmc_hostname(host->mmc), phase_code);
eswin_sdhci_disable_card_clk(host);
sdhci_writew(host, phase_code, VENDOR_AT_SATA_R);
eswin_sdhci_enable_card_clk(host);
+ ret = mmc_send_tuning(host->mmc, opcode, &cmd_error);
+ host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ if (ret) {
+ pr_err("%s: phase_code code(0x%x) not work, tuning failed!\n",
+ mmc_hostname(host->mmc), phase_code);
+ return ret;
+ }
+
return 0;
}
@@ -306,20 +253,9 @@ static int eswin_sdhci_sdio_executing_tuning(struct sdhci_host *host,
int ret = 0;
struct sdhci_pltfm_host *pltfm_host;
struct eswin_sdhci_data *eswin_sdhci_sdio;
- struct eswin_sdio_private *eswin_sdio_priv;
pltfm_host = sdhci_priv(host);
eswin_sdhci_sdio = sdhci_pltfm_priv(pltfm_host);
- eswin_sdio_priv = sdhci_sdio_priv(eswin_sdhci_sdio);
-
- if (!eswin_sdio_priv->enable_sw_tuning) {
- if (eswin_sdio_priv->phase_code != -1) {
- eswin_sdhci_disable_card_clk(host);
- sdhci_writew(host, eswin_sdio_priv->phase_code, VENDOR_AT_SATA_R);
- eswin_sdhci_enable_card_clk(host);
- }
- return 0;
- }
eswin_sdhci_disable_card_clk(host);
@@ -336,11 +272,6 @@ static int eswin_sdhci_sdio_executing_tuning(struct sdhci_host *host,
sdhci_writew(host, 0x0, SDHCI_CMD_DATA);
- ret = eswin_sdhci_sdio_delay_tuning(host, opcode);
- if (ret < 0) {
- return ret;
- }
-
ret = eswin_sdhci_sdio_phase_code_tuning(host, opcode);
if (ret < 0) {
return ret;
@@ -837,14 +768,13 @@ static int eswin_sdhci_sdio_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct eswin_sdhci_data *eswin_sdhci_sdio;
- struct eswin_sdio_private *eswin_sdio_priv;
struct regmap *regmap;
const struct eswin_sdhci_of_data *data;
unsigned int sdio_id = 0;
unsigned int val = 0;
data = of_device_get_match_data(dev);
- host = sdhci_pltfm_init(pdev, data->pdata, sizeof(*eswin_sdhci_sdio) + sizeof(*eswin_sdio_priv));
+ host = sdhci_pltfm_init(pdev, data->pdata, sizeof(*eswin_sdhci_sdio));
if (IS_ERR(host))
return PTR_ERR(host);
@@ -853,7 +783,6 @@ static int eswin_sdhci_sdio_probe(struct platform_device *pdev)
eswin_sdhci_sdio = sdhci_pltfm_priv(pltfm_host);
eswin_sdhci_sdio->host = host;
eswin_sdhci_sdio->has_cqe = false;
- eswin_sdio_priv = sdhci_sdio_priv(eswin_sdhci_sdio);
ret = of_property_read_u32(dev->of_node, "core-clk-reg", &val);
if (ret) {
@@ -982,17 +911,6 @@ static int eswin_sdhci_sdio_probe(struct platform_device *pdev)
else
eswin_sdhci_sdio->phy.enable_data_pullup = DISABLE;
- if (of_property_read_bool(dev->of_node, "enable_sw_tuning"))
- eswin_sdio_priv->enable_sw_tuning = ENABLE;
- else
- eswin_sdio_priv->enable_sw_tuning = DISABLE;
-
- if (!of_property_read_u32(dev->of_node, "phase_code", &val)) {
- eswin_sdio_priv->phase_code = val;
- } else {
- eswin_sdio_priv->phase_code = -1;
- }
-
eswin_sdhci_dt_parse_clk_phases(dev, &eswin_sdhci_sdio->clk_data);
ret = mmc_of_parse(host->mmc);
if (ret) {
--
2.47.0