Skip to content

Commit

Permalink
mmc: tegra: Add a workaround for tap value change glitch
Browse files Browse the repository at this point in the history
Add quirk to disable the card clock during configuration of the tap
value in tegra_sdhci_set_tap() and issue sdhci_reset() after value
change. This is a workaround to avoid propagation of a potential
glitch caused by setting the tap value.

Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
  • Loading branch information
Aapo Vienamo authored and Ulf Hansson committed Oct 8, 2018
1 parent d943f6e commit d4501d8
Showing 1 changed file with 28 additions and 2 deletions.
30 changes: 28 additions & 2 deletions drivers/mmc/host/sdhci-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20
#define SDHCI_MISC_CTRL_ENABLE_DDR50 0x200

#define SDHCI_VNDR_TUN_CTRL0_0 0x1c0
#define SDHCI_VNDR_TUN_CTRL0_TUN_HW_TAP 0x20000

#define SDHCI_TEGRA_AUTO_CAL_CONFIG 0x1e4
#define SDHCI_AUTO_CAL_START BIT(31)
#define SDHCI_AUTO_CAL_ENABLE BIT(29)
Expand All @@ -68,6 +71,7 @@
#define NVQUIRK_ENABLE_DDR50 BIT(5)
#define NVQUIRK_HAS_PADCALIB BIT(6)
#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7)
#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8)

struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
Expand Down Expand Up @@ -515,12 +519,32 @@ static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host)

static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
bool card_clk_enabled = false;
u32 reg;

/*
* Touching the tap values is a bit tricky on some SoC generations.
* The quirk enables a workaround for a glitch that sometimes occurs if
* the tap values are changed.
*/

if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP)
card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);

reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK;
reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT;
sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);

if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP &&
card_clk_enabled) {
usleep_range(1, 2);
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
tegra_sdhci_configure_card_clk(host, card_clk_enabled);
}
}

static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
Expand Down Expand Up @@ -774,7 +798,8 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
.pdata = &sdhci_tegra210_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
NVQUIRK_HAS_PADCALIB,
NVQUIRK_HAS_PADCALIB |
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
};

static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
Expand All @@ -799,7 +824,8 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
.pdata = &sdhci_tegra186_pdata,
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
NVQUIRK_HAS_PADCALIB,
NVQUIRK_HAS_PADCALIB |
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP,
};

static const struct of_device_id sdhci_tegra_dt_match[] = {
Expand Down

0 comments on commit d4501d8

Please sign in to comment.