Loading Documentation/devicetree/bindings/mmc/sdhci-msm.txt +5 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,11 @@ Optional Properties: during clock scaling. If this property is not defined, then it falls back to the default HS bus speed mode to maintain backward compatibility. - qcom,sdr104-wa: On Certain chipsets, SDR104 mode might be unstable causing CRC errors on the interface. So there is a workaround implemented to skip printing register dumps on CRC errors and also downgrade bus speed mode to SDR50/DDR50 in case of continuous CRC errors. Set this flag to enable this workaround. In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltage). - qcom,<supply>-always-on - specifies whether supply should be kept "on" always. Loading arch/arm/boot/dts/qcom/sdx20-v2-nand-dualwifi-cdp.dts +2 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ qcom,core_3_0v_support; qcom,nonremovable; qcom,sdr104-wa; pinctrl-names = "active", "sleep"; pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_wlan_gpio_active>; Loading arch/arm/boot/dts/qcom/sdx20-v2-nand-dualwifi-mtp.dts +2 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ qcom,core_3_0v_support; qcom,nonremovable; qcom,sdr104-wa; pinctrl-names = "active", "sleep"; pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_wlan_gpio_active>; Loading drivers/mmc/core/core.c +27 −7 Original line number Diff line number Diff line Loading @@ -961,6 +961,21 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) EXPORT_SYMBOL(mmc_request_done); static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { int err; /* Assumes host controller has been runtime resumed by mmc_claim_host */ err = mmc_retune(host); if (err) { mrq->cmd->error = err; mmc_request_done(host, mrq); return; } host->ops->request(host, mrq); } static void mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { Loading @@ -968,6 +983,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) unsigned int i, sz; struct scatterlist *sg; #endif mmc_retune_hold(host); if (mrq->sbc) { pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n", Loading Loading @@ -1032,7 +1048,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mmc_clk_scaling_start_busy(host, true); } host->ops->request(host, mrq); __mmc_start_request(host, mrq); } static void mmc_start_cmdq_request(struct mmc_host *host, Loading Loading @@ -1353,22 +1369,22 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, host->areq); break; /* return err */ } else { mmc_retune_recheck(host); pr_info("%s: req failed (CMD%u): %d, retrying...\n", mmc_hostname(host), cmd->opcode, cmd->error); cmd->retries--; cmd->error = 0; host->ops->request(host, mrq); __mmc_start_request(host, mrq); continue; /* wait for done/new event again */ } } else if (context_info->is_new_req) { context_info->is_new_req = false; if (!next_req) { err = MMC_BLK_NEW_REQUEST; break; /* return err */ } if (!next_req) return MMC_BLK_NEW_REQUEST; } } mmc_retune_release(host); return err; } Loading Loading @@ -1403,12 +1419,16 @@ static void mmc_wait_for_req_done(struct mmc_host *host, mmc_card_removed(host->card)) break; mmc_retune_recheck(host); pr_debug("%s: req failed (CMD%u): %d, retrying...\n", mmc_hostname(host), cmd->opcode, cmd->error); cmd->retries--; cmd->error = 0; host->ops->request(host, mrq); __mmc_start_request(host, mrq); } mmc_retune_release(host); } /** Loading drivers/mmc/core/host.c +68 −0 Original line number Diff line number Diff line Loading @@ -312,6 +312,73 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) #endif void mmc_retune_enable(struct mmc_host *host) { host->can_retune = 1; if (host->retune_period) mod_timer(&host->retune_timer, jiffies + host->retune_period * HZ); } void mmc_retune_disable(struct mmc_host *host) { host->can_retune = 0; del_timer_sync(&host->retune_timer); host->retune_now = 0; host->need_retune = 0; } void mmc_retune_timer_stop(struct mmc_host *host) { del_timer_sync(&host->retune_timer); } EXPORT_SYMBOL(mmc_retune_timer_stop); void mmc_retune_hold(struct mmc_host *host) { if (!host->hold_retune) host->retune_now = 1; host->hold_retune += 1; } void mmc_retune_release(struct mmc_host *host) { if (host->hold_retune) host->hold_retune -= 1; else WARN_ON(1); } int mmc_retune(struct mmc_host *host) { int err; if (host->retune_now) host->retune_now = 0; else return 0; if (!host->need_retune || host->doing_retune || !host->card) return 0; host->need_retune = 0; host->doing_retune = 1; err = mmc_execute_tuning(host->card); host->doing_retune = 0; return err; } static void mmc_retune_timer(unsigned long data) { struct mmc_host *host = (struct mmc_host *)data; mmc_retune_needed(host); } /** * mmc_of_parse() - parse host's device-tree node * @host: host whose node should be parsed. Loading Loading @@ -527,6 +594,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) #ifdef CONFIG_PM host->pm_notify.notifier_call = mmc_pm_notify; #endif setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host); /* * By default, hosts do not support SGIO or large requests. Loading Loading
Documentation/devicetree/bindings/mmc/sdhci-msm.txt +5 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,11 @@ Optional Properties: during clock scaling. If this property is not defined, then it falls back to the default HS bus speed mode to maintain backward compatibility. - qcom,sdr104-wa: On Certain chipsets, SDR104 mode might be unstable causing CRC errors on the interface. So there is a workaround implemented to skip printing register dumps on CRC errors and also downgrade bus speed mode to SDR50/DDR50 in case of continuous CRC errors. Set this flag to enable this workaround. In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltage). - qcom,<supply>-always-on - specifies whether supply should be kept "on" always. Loading
arch/arm/boot/dts/qcom/sdx20-v2-nand-dualwifi-cdp.dts +2 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ qcom,core_3_0v_support; qcom,nonremovable; qcom,sdr104-wa; pinctrl-names = "active", "sleep"; pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_wlan_gpio_active>; Loading
arch/arm/boot/dts/qcom/sdx20-v2-nand-dualwifi-mtp.dts +2 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ qcom,core_3_0v_support; qcom,nonremovable; qcom,sdr104-wa; pinctrl-names = "active", "sleep"; pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_wlan_gpio_active>; Loading
drivers/mmc/core/core.c +27 −7 Original line number Diff line number Diff line Loading @@ -961,6 +961,21 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) EXPORT_SYMBOL(mmc_request_done); static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { int err; /* Assumes host controller has been runtime resumed by mmc_claim_host */ err = mmc_retune(host); if (err) { mrq->cmd->error = err; mmc_request_done(host, mrq); return; } host->ops->request(host, mrq); } static void mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { Loading @@ -968,6 +983,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) unsigned int i, sz; struct scatterlist *sg; #endif mmc_retune_hold(host); if (mrq->sbc) { pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n", Loading Loading @@ -1032,7 +1048,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mmc_clk_scaling_start_busy(host, true); } host->ops->request(host, mrq); __mmc_start_request(host, mrq); } static void mmc_start_cmdq_request(struct mmc_host *host, Loading Loading @@ -1353,22 +1369,22 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, host->areq); break; /* return err */ } else { mmc_retune_recheck(host); pr_info("%s: req failed (CMD%u): %d, retrying...\n", mmc_hostname(host), cmd->opcode, cmd->error); cmd->retries--; cmd->error = 0; host->ops->request(host, mrq); __mmc_start_request(host, mrq); continue; /* wait for done/new event again */ } } else if (context_info->is_new_req) { context_info->is_new_req = false; if (!next_req) { err = MMC_BLK_NEW_REQUEST; break; /* return err */ } if (!next_req) return MMC_BLK_NEW_REQUEST; } } mmc_retune_release(host); return err; } Loading Loading @@ -1403,12 +1419,16 @@ static void mmc_wait_for_req_done(struct mmc_host *host, mmc_card_removed(host->card)) break; mmc_retune_recheck(host); pr_debug("%s: req failed (CMD%u): %d, retrying...\n", mmc_hostname(host), cmd->opcode, cmd->error); cmd->retries--; cmd->error = 0; host->ops->request(host, mrq); __mmc_start_request(host, mrq); } mmc_retune_release(host); } /** Loading
drivers/mmc/core/host.c +68 −0 Original line number Diff line number Diff line Loading @@ -312,6 +312,73 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) #endif void mmc_retune_enable(struct mmc_host *host) { host->can_retune = 1; if (host->retune_period) mod_timer(&host->retune_timer, jiffies + host->retune_period * HZ); } void mmc_retune_disable(struct mmc_host *host) { host->can_retune = 0; del_timer_sync(&host->retune_timer); host->retune_now = 0; host->need_retune = 0; } void mmc_retune_timer_stop(struct mmc_host *host) { del_timer_sync(&host->retune_timer); } EXPORT_SYMBOL(mmc_retune_timer_stop); void mmc_retune_hold(struct mmc_host *host) { if (!host->hold_retune) host->retune_now = 1; host->hold_retune += 1; } void mmc_retune_release(struct mmc_host *host) { if (host->hold_retune) host->hold_retune -= 1; else WARN_ON(1); } int mmc_retune(struct mmc_host *host) { int err; if (host->retune_now) host->retune_now = 0; else return 0; if (!host->need_retune || host->doing_retune || !host->card) return 0; host->need_retune = 0; host->doing_retune = 1; err = mmc_execute_tuning(host->card); host->doing_retune = 0; return err; } static void mmc_retune_timer(unsigned long data) { struct mmc_host *host = (struct mmc_host *)data; mmc_retune_needed(host); } /** * mmc_of_parse() - parse host's device-tree node * @host: host whose node should be parsed. Loading Loading @@ -527,6 +594,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) #ifdef CONFIG_PM host->pm_notify.notifier_call = mmc_pm_notify; #endif setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host); /* * By default, hosts do not support SGIO or large requests. Loading