Skip to content

Commit

Permalink
mmc: sdhci-of-esdhc: add erratum A011334 support
Browse files Browse the repository at this point in the history
There are timing violations in case of few division ratio options
are selected for card clock frequency. prescaler*divisor options
/3,/5,/6,/7,/9,/10,/11,/13,/14 and /15 are not available in LX2
Rev1.0. prescaler*divisor options /4,/8 and /12 only available in
LX2 Rev1.0. Applicable only for HS400 mode. so by add the erratum
A011334 support to limit the prescaler*divisor in LX2 REV1.0

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Signed-off-by: Yinbo Zhu <yinbo.zhu@nxp.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
  • Loading branch information
Yangbo Lu authored and Ulf Hansson committed Dec 17, 2018
1 parent 54e08d9 commit 6079e63
Showing 1 changed file with 36 additions and 0 deletions.
36 changes: 36 additions & 0 deletions drivers/mmc/host/sdhci-of-esdhc.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ struct sdhci_esdhc {
u8 vendor_ver;
u8 spec_ver;
bool quirk_incorrect_hostver;
bool quirk_limited_clk_division;
bool quirk_fixup_tuning;
unsigned int peripheral_clock;
const struct esdhc_clk_fixup *clk_fixup;
Expand Down Expand Up @@ -544,6 +545,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
int pre_div = 1;
int div = 1;
int division;
ktime_t timeout;
long fixup = 0;
u32 temp;
Expand Down Expand Up @@ -579,6 +581,26 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
while (host->max_clk / pre_div / div > clock && div < 16)
div++;

if (esdhc->quirk_limited_clk_division &&
clock == MMC_HS200_MAX_DTR &&
(host->mmc->ios.timing == MMC_TIMING_MMC_HS400 ||
host->flags & SDHCI_HS400_TUNING)) {
division = pre_div * div;
if (division <= 4) {
pre_div = 4;
div = 1;
} else if (division <= 8) {
pre_div = 4;
div = 2;
} else if (division <= 12) {
pre_div = 4;
div = 3;
} else {
pr_warn("%s: using upsupported clock division.\n",
mmc_hostname(host->mmc));
}
}

dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
clock, host->max_clk / pre_div / div);
host->mmc->actual_clock = host->max_clk / pre_div / div;
Expand Down Expand Up @@ -778,6 +800,10 @@ static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
u32 val;
int ret;

if (esdhc->quirk_limited_clk_division &&
host->flags & SDHCI_HS400_TUNING)
esdhc_of_set_clock(host, host->clock);

esdhc_tuning_block_enable(host, true);

hs400_tuning = host->flags & SDHCI_HS400_TUNING;
Expand Down Expand Up @@ -908,6 +934,11 @@ static struct soc_device_attribute soc_incorrect_hostver[] = {
{ },
};

static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = {
{ .family = "QorIQ LX2160A", .revision = "1.0", },
{ },
};

static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
{
const struct of_device_id *match;
Expand All @@ -930,6 +961,11 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
else
esdhc->quirk_incorrect_hostver = false;

if (soc_device_match(soc_fixup_sdhc_clkdivs))
esdhc->quirk_limited_clk_division = true;
else
esdhc->quirk_limited_clk_division = false;

match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node);
if (match)
esdhc->clk_fixup = match->data;
Expand Down

0 comments on commit 6079e63

Please sign in to comment.