[PATCH 1/2] mmc:sdhci-msm:fix Qualcomm sd host 7180 SD card compatibility issue

From: Chevron Li
Date: Fri Jan 21 2022 - 06:10:02 EST


Improve the signal integrity for long SD bus trace by using SC7180+GGC SD host redriver chip
1.GGC is a SD bus signal re-timing IC that has been paired with the SC7180 sometimes.
2.The key points are initialized GGC chip during SD initialization and use GGC special tuning flow to re-timing SD bus signal.
3.GGC resource is initialized for GGC chip during Qualcomm host probe:
3.1 GGC structure initialization
3.2 GGC GPIO resource assignment
3.3 Reload host->mmc->detect with GGC chip special initiation flow.
3.4 Reload the host->mmc_host_ops.execute_tuning with GGC chip special tuning flow.
4.The function of the patch is already verified on Chrome OS, and Google request us to submit the patch to Linux for them future use.
5.GGC can work with any other standard SDHCI controller to improve SD signal SI and Timing.
6.GGC has cooperated with Intel/Qualcomm/MTK/SPRD sd host already and work well.

Signed-off-by: Chevron Li <chevron.li@xxxxxxxxxxxxxx>
---
Changes:
1.add a data member in sdhci_msm_host structure for extension
2.add an API to get the extension address from sdhci_msm_host structure
3.add an independent branch for GGC chip support according to the configure of DTSI
---
drivers/mmc/host/sdhci-bayhub.c | 34 ++++++++++++++++++++++++++++
drivers/mmc/host/sdhci-msm.c | 39 ++++++++++++++++++++++++++++++++-
2 files changed, 72 insertions(+), 1 deletion(-)
create mode 100644 drivers/mmc/host/sdhci-bayhub.c

diff --git a/drivers/mmc/host/sdhci-bayhub.c b/drivers/mmc/host/sdhci-bayhub.c
new file mode 100644
index 000000000000..867d465ce848
--- /dev/null
+++ b/drivers/mmc/host/sdhci-bayhub.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Bayhub Technologies, Inc. BH201 SDHCI bridge IC for
+ * VENDOR SDHCI platform driver source file
+ *
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ */
+
+struct sdhci_bht_host {
+};
+
+static void bht_signal_voltage_on_off(struct sdhci_host *host, u32 on_off)
+{
+}
+
+static void sdhci_bht_parse(struct mmc_host *mmc_host)
+{
+}
+
+static void sdhci_bht_resource_free(struct sdhci_msm_host *vendor_host)
+{
+}
+
+static void mmc_rescan_bht(struct work_struct *work)
+{
+}
+
+static int sdhci_bht_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ int ret = 0;
+
+ return ret;
+}
+
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 50c71e0ba5e4..5e19d34ef25c 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -285,8 +285,14 @@ struct sdhci_msm_host {
u32 dll_config;
u32 ddr_config;
bool vqmmc_enabled;
+ unsigned long private[] ____cacheline_aligned;
};

+static inline void *sdhci_msm_priv(struct sdhci_msm_host *msm_host)
+{
+ return (void *)msm_host->private;
+}
+
static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -1585,6 +1591,8 @@ static void sdhci_msm_dump_pwr_ctrl_regs(struct sdhci_host *host)
msm_host_readl(msm_host, host, msm_offset->core_pwrctl_mask),
msm_host_readl(msm_host, host, msm_offset->core_pwrctl_ctl));
}
+/* include bayhub patch for GGC chip support */
+#include "sdhci-bayhub.c"

static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
{
@@ -1628,10 +1636,16 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)

/* Handle BUS ON/OFF*/
if (irq_status & CORE_PWRCTL_BUS_ON) {
+ /* Bayhub patch: GGC chip power on patch */
+ if (of_find_property(msm_host->pdev->dev.of_node, "use-bayhub-bh201", NULL))
+ bht_signal_voltage_on_off(host, 1);
pwr_state = REQ_BUS_ON;
io_level = REQ_IO_HIGH;
}
if (irq_status & CORE_PWRCTL_BUS_OFF) {
+ /* Bayhub patch: GGC chip power off patch */
+ if (of_find_property(msm_host->pdev->dev.of_node, "use-bayhub-bh201", NULL))
+ bht_signal_voltage_on_off(host, 0);
pwr_state = REQ_BUS_OFF;
io_level = REQ_IO_LOW;
}
@@ -2497,7 +2511,12 @@ static int sdhci_msm_probe(struct platform_device *pdev)
const struct sdhci_msm_variant_info *var_info;
struct device_node *node = pdev->dev.of_node;

- host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host));
+ /* Bayhub patch: memory allocate for sdhci_bht_host structure */
+ if (of_find_property(node, "use-bayhub-bh201", NULL))
+ host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata,
+ sizeof(*msm_host) + sizeof(struct sdhci_bht_host));
+ else
+ host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host));
if (IS_ERR(host))
return PTR_ERR(host);

@@ -2511,6 +2530,15 @@ static int sdhci_msm_probe(struct platform_device *pdev)
if (ret)
goto pltfm_free;

+ /* Bayhub patch: resource assign and mmc_rescan routine overload */
+ if (of_find_property(node, "use-bayhub-bh201", NULL)) {
+ struct sdhci_bht_host *bht_host;
+
+ bht_host = sdhci_msm_priv(msm_host);
+ sdhci_bht_parse(msm_host->mmc);
+ INIT_DELAYED_WORK(&host->mmc->detect, mmc_rescan_bht);
+ }
+
/*
* Based on the compatible string, load the required msm host info from
* the data associated with the version info.
@@ -2727,6 +2755,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
host->mmc_host_ops.start_signal_voltage_switch =
sdhci_msm_start_signal_voltage_switch;
host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning;
+ /* Bayhub patch: overload the mmc_host_ops.execute_tuning routine */
+ if (of_find_property(node, "use-bayhub-bh201", NULL))
+ host->mmc_host_ops.execute_tuning = sdhci_bht_execute_tuning;
if (of_property_read_bool(node, "supports-cqe"))
ret = sdhci_msm_cqe_add_host(host, pdev);
else
@@ -2750,6 +2781,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
if (!IS_ERR(msm_host->bus_clk))
clk_disable_unprepare(msm_host->bus_clk);
pltfm_free:
+ /* Bayhub patch: release assigned resource */
+ if (of_find_property(node, "use-bayhub-bh201", NULL))
+ sdhci_bht_resource_free(msm_host);
sdhci_pltfm_free(pdev);
return ret;
}
@@ -2763,6 +2797,9 @@ static int sdhci_msm_remove(struct platform_device *pdev)
0xffffffff);

sdhci_remove_host(host, dead);
+ /* Bayhub patch: release assigned resource */
+ if (of_find_property(msm_host->pdev->dev.of_node, "use-bayhub-bh201", NULL))
+ sdhci_bht_resource_free(msm_host);

pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);

base-commit: c9e6606c7fe92b50a02ce51dda82586ebdf99b48
--
2.32.0