379 lines
11 KiB
Diff
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
|
|
|