Merge "ARM: dts: msm: enable SDR104 workaround for MSM8998"

This commit is contained in:
Linux Build Service Account 2017-04-05 12:16:57 -07:00 committed by Gerrit - the friendly Code Review server
commit bbc2d362eb
12 changed files with 92 additions and 3 deletions

View file

@ -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.

View file

@ -1575,6 +1575,8 @@
qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
100000000 200000000 4294967295>;
qcom,sdr104-wa;
status = "disabled";
};

View file

@ -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.
@ -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
@ -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:
@ -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) &&

View file

@ -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));
}

View file

@ -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);

View file

@ -1285,6 +1285,8 @@ static int _mmc_sd_resume(struct mmc_host *host)
#endif
mmc_card_clr_suspended(host->card);
if (host->card->sdr104_blocked)
goto out;
err = mmc_resume_clk_scaling(host);
if (err) {
pr_err("%s: %s: fail to resume clock scaling (%d)\n",

View file

@ -1960,6 +1960,8 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev,
if (of_get_property(np, "qcom,core_3_0v_support", NULL))
pdata->core_3_0v_support = true;
pdata->sdr104_wa = of_property_read_bool(np, "qcom,sdr104-wa");
return pdata;
out:
return NULL;
@ -4579,6 +4581,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
if (msm_host->pdata->nonhotplug)
msm_host->mmc->caps2 |= MMC_CAP2_NONHOTPLUG;
msm_host->mmc->sdr104_wa = msm_host->pdata->sdr104_wa;
/* Initialize ICE if present */
if (msm_host->ice.pdev) {

View file

@ -153,6 +153,7 @@ struct sdhci_msm_pltfm_data {
u32 ice_clk_min;
struct sdhci_msm_pm_qos_data pm_qos_data;
bool core_3_0v_support;
bool sdr104_wa;
};
struct sdhci_msm_bus_vote {

View file

@ -3083,7 +3083,10 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
mmc_hostname(host->mmc), intmask,
host->data->error, ktime_to_ms(ktime_sub(
ktime_get(), host->data_start_time)));
sdhci_dumpregs(host);
if (!host->mmc->sdr104_wa ||
(host->mmc->ios.timing != MMC_TIMING_UHS_SDR104))
sdhci_dumpregs(host);
}
sdhci_finish_data(host);
} else {

View file

@ -434,6 +434,8 @@ struct mmc_card {
enum mmc_pon_type pon_type;
bool cmdq_init;
struct mmc_bkops_info bkops;
bool err_in_sdr104;
bool sdr104_blocked;
};
/*

View file

@ -169,6 +169,7 @@ extern int __mmc_switch_cmdq_mode(struct mmc_command *cmd, u8 set, u8 index,
extern int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error);
extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
extern int mmc_set_auto_bkops(struct mmc_card *card, bool enable);
extern int mmc_suspend_clk_scaling(struct mmc_host *host);
#define MMC_ERASE_ARG 0x00000000
#define MMC_SECURE_ERASE_ARG 0x80000000

View file

@ -595,6 +595,7 @@ struct mmc_host {
struct io_latency_state io_lat_s;
#endif
bool sdr104_wa;
unsigned long private[0] ____cacheline_aligned;
};
@ -728,6 +729,16 @@ static inline int mmc_host_uhs(struct mmc_host *host)
MMC_CAP_UHS_DDR50);
}
static inline void mmc_host_clear_sdr104(struct mmc_host *host)
{
host->caps &= ~MMC_CAP_UHS_SDR104;
}
static inline void mmc_host_set_sdr104(struct mmc_host *host)
{
host->caps |= MMC_CAP_UHS_SDR104;
}
static inline int mmc_host_packed_wr(struct mmc_host *host)
{
return host->caps2 & MMC_CAP2_PACKED_WR;