diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-msm.c')
-rw-r--r-- | drivers/mmc/host/sdhci-msm.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 50c71e0ba5e4..e395411fb6fd 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -17,6 +17,7 @@ #include <linux/regulator/consumer.h> #include <linux/interconnect.h> #include <linux/pinctrl/consumer.h> +#include <linux/reset.h> #include "sdhci-pltfm.h" #include "cqhci.h" @@ -2434,8 +2435,33 @@ static const struct sdhci_msm_variant_info sdm845_sdhci_var = { }; static const struct of_device_id sdhci_msm_dt_match[] = { + /* Following two entries are deprecated (kept only for backward compatibility) */ {.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var}, {.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var}, + /* Add entries for sdcc versions less than 5.0 here */ + {.compatible = "qcom,apq8084-sdhci", .data = &sdhci_msm_mci_var}, + {.compatible = "qcom,msm8226-sdhci", .data = &sdhci_msm_mci_var}, + {.compatible = "qcom,msm8916-sdhci", .data = &sdhci_msm_mci_var}, + {.compatible = "qcom,msm8953-sdhci", .data = &sdhci_msm_mci_var}, + {.compatible = "qcom,msm8974-sdhci", .data = &sdhci_msm_mci_var}, + {.compatible = "qcom,msm8992-sdhci", .data = &sdhci_msm_mci_var}, + {.compatible = "qcom,msm8994-sdhci", .data = &sdhci_msm_mci_var}, + {.compatible = "qcom,msm8996-sdhci", .data = &sdhci_msm_mci_var}, + /* + * Add entries for sdcc version 5.0 here. For SDCC version 5.0.0, + * MCI registers are removed from SDCC interface and some registers + * are moved to HC. + */ + {.compatible = "qcom,qcs404-sdhci", .data = &sdhci_msm_v5_var}, + {.compatible = "qcom,sdx55-sdhci", .data = &sdhci_msm_v5_var}, + {.compatible = "qcom,sdx65-sdhci", .data = &sdhci_msm_v5_var}, + {.compatible = "qcom,sdm630-sdhci", .data = &sdhci_msm_v5_var}, + {.compatible = "qcom,sm6125-sdhci", .data = &sdhci_msm_v5_var}, + {.compatible = "qcom,sm6350-sdhci", .data = &sdhci_msm_v5_var}, + {.compatible = "qcom,sm8150-sdhci", .data = &sdhci_msm_v5_var}, + {.compatible = "qcom,sm8250-sdhci", .data = &sdhci_msm_v5_var}, + {.compatible = "qcom,sc7280-sdhci", .data = &sdhci_msm_v5_var}, + /* Add entries where soc specific handling is required, here */ {.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var}, {.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var}, {}, @@ -2482,6 +2508,43 @@ static inline void sdhci_msm_get_of_property(struct platform_device *pdev, of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config); } +static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host) +{ + struct reset_control *reset; + int ret = 0; + + reset = reset_control_get_optional_exclusive(dev, NULL); + if (IS_ERR(reset)) + return dev_err_probe(dev, PTR_ERR(reset), + "unable to acquire core_reset\n"); + + if (!reset) + return ret; + + ret = reset_control_assert(reset); + if (ret) { + reset_control_put(reset); + return dev_err_probe(dev, ret, "core_reset assert failed\n"); + } + + /* + * The hardware requirement for delay between assert/deassert + * is at least 3-4 sleep clock (32.7KHz) cycles, which comes to + * ~125us (4/32768). To be on the safe side add 200us delay. + */ + usleep_range(200, 210); + + ret = reset_control_deassert(reset); + if (ret) { + reset_control_put(reset); + return dev_err_probe(dev, ret, "core_reset deassert failed\n"); + } + + usleep_range(200, 210); + reset_control_put(reset); + + return ret; +} static int sdhci_msm_probe(struct platform_device *pdev) { @@ -2529,6 +2592,10 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host->saved_tuning_phase = INVALID_TUNING_PHASE; + ret = sdhci_msm_gcc_reset(&pdev->dev, host); + if (ret) + goto pltfm_free; + /* Setup SDCC bus voter clock. */ msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); if (!IS_ERR(msm_host->bus_clk)) { |