Loading Documentation/devicetree/bindings/mmc/sdhci-msm.txt +5 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,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/msm8998.dtsi +2 −0 Original line number Diff line number Diff line Loading @@ -1575,6 +1575,8 @@ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 100000000 200000000 4294967295>; qcom,sdr104-wa; status = "disabled"; }; Loading drivers/mmc/card/block.c +57 −1 Original line number Diff line number Diff line Loading @@ -2189,6 +2189,17 @@ static int mmc_blk_err_check(struct mmc_card *card, int need_retune = card->host->need_retune; int ecc_err = 0, gen_err = 0; if (card->host->sdr104_wa && mmc_card_sd(card) && (card->host->ios.timing == MMC_TIMING_UHS_SDR104) && !card->sdr104_blocked && (brq->data.error == -EILSEQ || brq->data.error == -EIO || brq->data.error == -ETIMEDOUT || brq->cmd.error == -EILSEQ || brq->cmd.error == -EIO || brq->cmd.error == -ETIMEDOUT)) card->err_in_sdr104 = true; /* * sbc.error indicates a problem with the set block count * command. No data will have been transferred. Loading Loading @@ -3645,6 +3656,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) struct mmc_async_req *areq; const u8 packed_nr = 2; u8 reqs = 0; bool reset = false; #ifdef CONFIG_MMC_SIMULATE_MAX_SPEED unsigned long waitfor = jiffies; #endif Loading Loading @@ -3690,6 +3702,26 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; mmc_queue_bounce_post(mq_rq); if (card->err_in_sdr104) { /* * Data CRC/timeout errors will manifest as CMD/DATA * ERR. But we'd like to retry these too. * Moreover, no harm done if this fails too for multiple * times, we anyway reduce the bus-speed and retry the * same request. * If that fails too, we don't override this status. */ if (status == MMC_BLK_ABORT || status == MMC_BLK_CMD_ERR || status == MMC_BLK_DATA_ERR || status == MMC_BLK_RETRY) /* reset on all of these errors and retry */ reset = true; status = MMC_BLK_RETRY; card->err_in_sdr104 = false; } switch (status) { case MMC_BLK_SUCCESS: case MMC_BLK_PARTIAL: Loading Loading @@ -3730,8 +3762,32 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) break; case MMC_BLK_RETRY: retune_retry_done = brq->retune_retry_done; if (retry++ < MMC_BLK_MAX_RETRIES) if (retry++ < MMC_BLK_MAX_RETRIES) { break; } else if (reset) { reset = false; /* * If we exhaust all the retries due to * CRC/timeout errors in SDR140 mode with UHS SD * cards, re-configure the card in SDR50 * bus-speed mode. * All subsequent re-init of this card will be * in SDR50 mode, unless it is removed and * re-inserted. When new UHS SD cards are * inserted, it may start at SDR104 mode if * supported by the card. */ pr_err("%s: blocked SDR104, lower the bus-speed (SDR50 / DDR50)\n", req->rq_disk->disk_name); mmc_host_clear_sdr104(card->host); mmc_suspend_clk_scaling(card->host); mmc_blk_reset(md, card->host, type); /* SDR104 mode is blocked from now on */ card->sdr104_blocked = true; /* retry 5 times again */ retry = 0; break; } /* Fall through */ case MMC_BLK_ABORT: if (!mmc_blk_reset(md, card->host, type) && Loading drivers/mmc/core/core.c +4 −0 Original line number Diff line number Diff line Loading @@ -4040,6 +4040,10 @@ int _mmc_detect_card_removed(struct mmc_host *host) if (ret) { mmc_card_set_removed(host->card); if (host->card->sdr104_blocked) { mmc_host_set_sdr104(host); host->card->sdr104_blocked = false; } pr_debug("%s: card remove detected\n", mmc_hostname(host)); } Loading drivers/mmc/core/core.h +0 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,6 @@ void mmc_init_context_info(struct mmc_host *host); extern bool mmc_can_scale_clk(struct mmc_host *host); extern int mmc_init_clk_scaling(struct mmc_host *host); extern int mmc_suspend_clk_scaling(struct mmc_host *host); extern int mmc_resume_clk_scaling(struct mmc_host *host); extern int mmc_exit_clk_scaling(struct mmc_host *host); extern unsigned long mmc_get_max_frequency(struct mmc_host *host); Loading Loading
Documentation/devicetree/bindings/mmc/sdhci-msm.txt +5 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,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/msm8998.dtsi +2 −0 Original line number Diff line number Diff line Loading @@ -1575,6 +1575,8 @@ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 100000000 200000000 4294967295>; qcom,sdr104-wa; status = "disabled"; }; Loading
drivers/mmc/card/block.c +57 −1 Original line number Diff line number Diff line Loading @@ -2189,6 +2189,17 @@ static int mmc_blk_err_check(struct mmc_card *card, int need_retune = card->host->need_retune; int ecc_err = 0, gen_err = 0; if (card->host->sdr104_wa && mmc_card_sd(card) && (card->host->ios.timing == MMC_TIMING_UHS_SDR104) && !card->sdr104_blocked && (brq->data.error == -EILSEQ || brq->data.error == -EIO || brq->data.error == -ETIMEDOUT || brq->cmd.error == -EILSEQ || brq->cmd.error == -EIO || brq->cmd.error == -ETIMEDOUT)) card->err_in_sdr104 = true; /* * sbc.error indicates a problem with the set block count * command. No data will have been transferred. Loading Loading @@ -3645,6 +3656,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) struct mmc_async_req *areq; const u8 packed_nr = 2; u8 reqs = 0; bool reset = false; #ifdef CONFIG_MMC_SIMULATE_MAX_SPEED unsigned long waitfor = jiffies; #endif Loading Loading @@ -3690,6 +3702,26 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; mmc_queue_bounce_post(mq_rq); if (card->err_in_sdr104) { /* * Data CRC/timeout errors will manifest as CMD/DATA * ERR. But we'd like to retry these too. * Moreover, no harm done if this fails too for multiple * times, we anyway reduce the bus-speed and retry the * same request. * If that fails too, we don't override this status. */ if (status == MMC_BLK_ABORT || status == MMC_BLK_CMD_ERR || status == MMC_BLK_DATA_ERR || status == MMC_BLK_RETRY) /* reset on all of these errors and retry */ reset = true; status = MMC_BLK_RETRY; card->err_in_sdr104 = false; } switch (status) { case MMC_BLK_SUCCESS: case MMC_BLK_PARTIAL: Loading Loading @@ -3730,8 +3762,32 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) break; case MMC_BLK_RETRY: retune_retry_done = brq->retune_retry_done; if (retry++ < MMC_BLK_MAX_RETRIES) if (retry++ < MMC_BLK_MAX_RETRIES) { break; } else if (reset) { reset = false; /* * If we exhaust all the retries due to * CRC/timeout errors in SDR140 mode with UHS SD * cards, re-configure the card in SDR50 * bus-speed mode. * All subsequent re-init of this card will be * in SDR50 mode, unless it is removed and * re-inserted. When new UHS SD cards are * inserted, it may start at SDR104 mode if * supported by the card. */ pr_err("%s: blocked SDR104, lower the bus-speed (SDR50 / DDR50)\n", req->rq_disk->disk_name); mmc_host_clear_sdr104(card->host); mmc_suspend_clk_scaling(card->host); mmc_blk_reset(md, card->host, type); /* SDR104 mode is blocked from now on */ card->sdr104_blocked = true; /* retry 5 times again */ retry = 0; break; } /* Fall through */ case MMC_BLK_ABORT: if (!mmc_blk_reset(md, card->host, type) && Loading
drivers/mmc/core/core.c +4 −0 Original line number Diff line number Diff line Loading @@ -4040,6 +4040,10 @@ int _mmc_detect_card_removed(struct mmc_host *host) if (ret) { mmc_card_set_removed(host->card); if (host->card->sdr104_blocked) { mmc_host_set_sdr104(host); host->card->sdr104_blocked = false; } pr_debug("%s: card remove detected\n", mmc_hostname(host)); } Loading
drivers/mmc/core/core.h +0 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,6 @@ void mmc_init_context_info(struct mmc_host *host); extern bool mmc_can_scale_clk(struct mmc_host *host); extern int mmc_init_clk_scaling(struct mmc_host *host); extern int mmc_suspend_clk_scaling(struct mmc_host *host); extern int mmc_resume_clk_scaling(struct mmc_host *host); extern int mmc_exit_clk_scaling(struct mmc_host *host); extern unsigned long mmc_get_max_frequency(struct mmc_host *host); Loading