On 16 March 2016 at 12:37, Ulf Hansson <ulf.hansson@xxxxxxxxxx> wrote: > On 29 February 2016 at 21:56, Lucas Stach <dev@xxxxxxxxxx> wrote: >> The Tegra30+ SDMMC module has memcomp pads that are used to >> automatically find and set the correct drive strength settings to >> the sdmmc pads. The calibration needs to be manually kicked off >> when the card signal voltage is changed, after the card clock is >> supplied again. >> >> Signed-off-by: Lucas Stach <dev@xxxxxxxxxx> > > Thanks applied for next, with a minor trivial fixup to resolve the > conflict when applying. I noticed this one also caused a compile error, so I did one more additional trivial rebase to fix it. You should probably have look at my next branch, to make sure I haven't screwed up. Kind regards Uffe > > Kind regards > Uffe > >> --- >> This commit allows signal voltage changes on my Tegar30 Beaver to >> succeed, making UHS-I modes work. >> --- >> drivers/mmc/host/sdhci-tegra.c | 47 +++++++++++++++++++++++++++++++++++++++--- >> 1 file changed, 44 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c >> index 46a6bd1..9971732 100644 >> --- a/drivers/mmc/host/sdhci-tegra.c >> +++ b/drivers/mmc/host/sdhci-tegra.c >> @@ -12,6 +12,7 @@ >> * >> */ >> >> +#include "linux/delay.h" >> #include <linux/err.h> >> #include <linux/module.h> >> #include <linux/init.h> >> @@ -42,12 +43,17 @@ >> #define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20 >> #define SDHCI_MISC_CTRL_ENABLE_DDR50 0x200 >> >> +#define SDHCI_TEGRA_AUTO_CAL_CONFIG 0x1e4 >> +#define SDHCI_AUTO_CAL_START BIT(31) >> +#define SDHCI_AUTO_CAL_ENABLE BIT(29) >> + >> #define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0) >> #define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1) >> #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) >> #define NVQUIRK_ENABLE_SDR50 BIT(3) >> #define NVQUIRK_ENABLE_SDR104 BIT(4) >> #define NVQUIRK_ENABLE_DDR50 BIT(5) >> +#define NVQUIRK_HAS_PADCALIB BIT(6) >> >> struct sdhci_tegra_soc_data { >> const struct sdhci_pltfm_data *pdata; >> @@ -58,6 +64,7 @@ struct sdhci_tegra { >> const struct sdhci_tegra_soc_data *soc_data; >> struct gpio_desc *power_gpio; >> bool ddr_signaling; >> + bool pad_calib_required; >> }; >> >> static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) >> @@ -165,6 +172,9 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) >> clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE; >> sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); >> >> + if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) >> + tegra_host->pad_calib_required = true; >> + >> tegra_host->ddr_signaling = false; >> } >> >> @@ -187,6 +197,17 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width) >> sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); >> } >> >> +static void tegra_sdhci_pad_autocalib(struct sdhci_host *host) >> +{ >> + u32 val; >> + >> + mdelay(1); >> + >> + val = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG); >> + val |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START; >> + sdhci_writel(host,val, SDHCI_TEGRA_AUTO_CAL_CONFIG); >> +} >> + >> static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) >> { >> struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); >> @@ -200,7 +221,12 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) >> clk_set_rate(pltfm_host->clk, host_clk); >> host->max_clk = clk_get_rate(pltfm_host->clk); >> >> - return sdhci_set_clock(host, clock); >> + sdhci_set_clock(host, clock); >> + >> + if (tegra_host->pad_calib_required) { >> + tegra_sdhci_pad_autocalib(host); >> + tegra_host->pad_calib_required = false; >> + } >> } >> >> static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host, >> @@ -270,6 +296,16 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) >> return mmc_send_tuning(host->mmc, opcode, NULL); >> } >> >> +static void tegra_sdhci_voltage_switch(struct sdhci_host *host) >> +{ >> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); >> + struct sdhci_tegra *tegra_host = pltfm_host->priv; >> + const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; >> + >> + if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) >> + tegra_host->pad_calib_required = true; >> +} >> + >> static const struct sdhci_ops tegra_sdhci_ops = { >> .get_ro = tegra_sdhci_get_ro, >> .read_w = tegra_sdhci_readw, >> @@ -279,6 +315,7 @@ static const struct sdhci_ops tegra_sdhci_ops = { >> .reset = tegra_sdhci_reset, >> .platform_execute_tuning = tegra_sdhci_execute_tuning, >> .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, >> + .voltage_switch = tegra_sdhci_voltage_switch, >> .get_max_clock = tegra_sdhci_get_max_clock, >> }; >> >> @@ -312,7 +349,8 @@ static const struct sdhci_tegra_soc_data soc_data_tegra30 = { >> .pdata = &sdhci_tegra30_pdata, >> .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 | >> NVQUIRK_ENABLE_SDR50 | >> - NVQUIRK_ENABLE_SDR104, >> + NVQUIRK_ENABLE_SDR104 | >> + NVQUIRK_HAS_PADCALIB, >> }; >> >> static const struct sdhci_ops tegra114_sdhci_ops = { >> @@ -325,6 +363,7 @@ static const struct sdhci_ops tegra114_sdhci_ops = { >> .reset = tegra_sdhci_reset, >> .platform_execute_tuning = tegra_sdhci_execute_tuning, >> .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, >> + .voltage_switch = tegra_sdhci_voltage_switch, >> .get_max_clock = tegra_sdhci_get_max_clock, >> }; >> >> @@ -347,7 +386,8 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 = { >> .pdata = &sdhci_tegra114_pdata, >> .nvquirks = NVQUIRK_ENABLE_SDR50 | >> NVQUIRK_ENABLE_DDR50 | >> - NVQUIRK_ENABLE_SDR104, >> + NVQUIRK_ENABLE_SDR104 | >> + NVQUIRK_HAS_PADCALIB, >> }; >> >> static const struct sdhci_pltfm_data sdhci_tegra210_pdata = { >> @@ -402,6 +442,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) >> goto err_alloc_tegra_host; >> } >> tegra_host->ddr_signaling = false; >> + tegra_host->pad_calib_required = false; >> tegra_host->soc_data = soc_data; >> pltfm_host->priv = tegra_host; >> >> -- >> 2.5.0 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in >> the body of a message to majordomo@xxxxxxxxxxxxxxx >> More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html