From: zhangguijiang zhangguijiang@huawei.com
ascend inclusion category: feature feature: Ascend emmc adaption bugzilla: https://gitee.com/openeuler/kernel/issues/I4F4LL CVE: NA
--------------------
Modified sd suspend, resume, reset and init process for ascend HiSilicon chip.
Signed-off-by: zhangguijiang zhangguijiang@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/mmc/core/sd.c | 83 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index c179c4984e311..e439c0ad462b0 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -28,6 +28,7 @@ #include "mmc_ops.h" #include "sd.h" #include "sd_ops.h" +#include "hisi_core_mmc.h"
static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, @@ -167,6 +168,19 @@ static int mmc_decode_csd(struct mmc_card *card) m = UNSTUFF_BITS(resp, 48, 22); csd->capacity = (1 + m) << 10;
+ /* + * Bit 12 - temporary write protection + * Bit 13 - permanent write protection + * while do sd card detection, check write protection attribute + */ + if (mmc_is_ascend_customized(card->host->parent)) + if (UNSTUFF_BITS(resp, 12, 1) || + UNSTUFF_BITS(resp, 13, 1)) { + pr_info("%s, SD is on write protection\n", + mmc_hostname(card->host)); + mmc_card_set_readonly(card); + } + csd->read_blkbits = 9; csd->read_partial = 0; csd->write_misalign = 0; @@ -261,7 +275,10 @@ static int mmc_read_ssr(struct mmc_card *card)
for (i = 0; i < 16; i++) card->raw_ssr[i] = be32_to_cpu(raw_ssr[i]); - +#ifdef CONFIG_ASCEND_HISI_MMC + if (mmc_is_ascend_customized(card->host->parent)) + card->ssr.speed_class = UNSTUFF_BITS(raw_ssr, 440 - 384, 8); +#endif kfree(raw_ssr);
/* @@ -1047,6 +1064,10 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, err = mmc_sd_init_uhs_card(card); if (err) goto free_card; +#ifdef CONFIG_ASCEND_HISI_MMC + if (mmc_is_ascend_customized(card->host->parent)) + mmc_sd_card_set_uhs(card); +#endif } else { /* * Attempt to change to high-speed (if supported) @@ -1056,7 +1077,8 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, mmc_set_timing(card->host, MMC_TIMING_SD_HS); else if (err) goto free_card; - + else if (mmc_is_ascend_customized(card->host->parent)) + mmc_set_timing(card->host, MMC_TIMING_NEW_SD); /* * Set bus speed. */ @@ -1149,7 +1171,10 @@ static int _mmc_sd_suspend(struct mmc_host *host) err = mmc_deselect_cards(host);
if (!err) { - mmc_power_off(host); + if (!(mmc_is_ascend_customized(host->parent))) + mmc_power_off(host); + else if (mmc_card_keep_power(host)) + mmc_power_off(host); mmc_card_set_suspended(host->card); }
@@ -1186,9 +1211,23 @@ static int _mmc_sd_resume(struct mmc_host *host)
if (!mmc_card_suspended(host->card)) goto out; + if (mmc_is_ascend_customized(host->parent)) { + if (!mmc_card_keep_power(host)) { + mmc_power_up(host, host->card->ocr); + err = mmc_sd_init_card( + host, host->card->ocr, host->card); + err = mmc_sd_init_card( + host, host->card->ocr, host->card); + } else { + err = mmc_select_card(host->card); + if (err) + err = mmc_sd_reset(host); + }
- mmc_power_up(host, host->card->ocr); - err = mmc_sd_init_card(host, host->card->ocr, host->card); + } else { + mmc_power_up(host, host->card->ocr); + err = mmc_sd_init_card(host, host->card->ocr, host->card); + } mmc_card_clr_suspended(host->card);
out: @@ -1238,8 +1277,42 @@ static int mmc_sd_runtime_resume(struct mmc_host *host) return 0; }
+#ifdef CONFIG_ASCEND_HISI_MMC +/*********************sd ops begin**********************/ +static int mmc_do_sd_reset(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + + if (!host->bus_ops->power_restore) + return -EOPNOTSUPP; + + if (!card) + return -EINVAL; + + /* hw_reset for ip reset */ + if (host->ops->hw_reset) + host->ops->hw_reset(host); + + /* Only for K930/920 SD slow down clk*/ + if (host->ops->slowdown_clk) + host->ops->slowdown_clk(host, host->ios.timing); + + mmc_power_off(host); + mmc_set_clock(host, host->f_init); + /* Wait at least 200 ms */ + mmc_delay(200); + mmc_power_up(host, host->card->ocr); + (void)mmc_select_voltage(host, host->card->ocr); + + return host->bus_ops->power_restore(host); +} +#endif static int mmc_sd_hw_reset(struct mmc_host *host) { +#ifdef CONFIG_ASCEND_HISI_MMC + if (mmc_is_ascend_customized(host->parent)) + return mmc_do_sd_reset(host); +#endif mmc_power_cycle(host, host->card->ocr); return mmc_sd_init_card(host, host->card->ocr, host->card); }