On Tue, 31 Jul 2018 11:15:41 +0200 Stefan Agner <stefan@xxxxxxxx> wrote: > On 27.07.2018 10:44, Aapo Vienamo wrote: > > On Thu, 26 Jul 2018 15:33:11 +0200 > > Stefan Agner <stefan@xxxxxxxx> wrote: > > > >> On 26.07.2018 14:19, Aapo Vienamo wrote: > >> > Parse the pinctrl state and nvidia,only-1-8-v properties from the device > >> > tree and implement pad voltage state reconfiguration in the mmc > >> > start_signal_voltage_switch() callback. Validate the pinctrl and > >> > regulator configuration before unmasking UHS modes. Add > >> > NVQUIRK_NEEDS_PAD_CONTROL and add set it for Tegra210 and Tegra186. > >> > > >> > The pad configuration is done in the mmc callback because the order of > >> > pad reconfiguration and sdhci voltage switch depend on the voltage to > >> > which the transition occurs. > >> > > >> > Signed-off-by: Aapo Vienamo <avienamo@xxxxxxxxxx> > >> > --- > >> > drivers/mmc/host/sdhci-tegra.c | 140 +++++++++++++++++++++++++++++++++++++---- > >> > 1 file changed, 127 insertions(+), 13 deletions(-) > >> > > >> > diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c > >> > index ddf00166..9587365 100644 > >> > --- a/drivers/mmc/host/sdhci-tegra.c > >> > +++ b/drivers/mmc/host/sdhci-tegra.c > >> > @@ -21,6 +21,7 @@ > >> > #include <linux/io.h> > >> > #include <linux/of.h> > >> > #include <linux/of_device.h> > >> > +#include <linux/pinctrl/consumer.h> > >> > #include <linux/reset.h> > >> > #include <linux/mmc/card.h> > >> > #include <linux/mmc/host.h> > >> > @@ -55,6 +56,7 @@ > >> > #define NVQUIRK_ENABLE_SDR104 BIT(4) > >> > #define NVQUIRK_ENABLE_DDR50 BIT(5) > >> > #define NVQUIRK_HAS_PADCALIB BIT(6) > >> > +#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7) > >> > > >> > struct sdhci_tegra_soc_data { > >> > const struct sdhci_pltfm_data *pdata; > >> > @@ -66,8 +68,13 @@ struct sdhci_tegra { > >> > struct gpio_desc *power_gpio; > >> > bool ddr_signaling; > >> > bool pad_calib_required; > >> > + bool pad_control_available; > >> > + bool only_1v8; > >> > > >> > struct reset_control *rst; > >> > + struct pinctrl *pinctrl_sdmmc; > >> > + struct pinctrl_state *pinctrl_state_3v3; > >> > + struct pinctrl_state *pinctrl_state_1v8; > >> > }; > >> > > >> > static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) > >> > @@ -138,12 +145,47 @@ static unsigned int tegra_sdhci_get_ro(struct > >> > sdhci_host *host) > >> > return mmc_gpio_get_ro(host->mmc); > >> > } > >> > > >> > +static bool tegra_sdhci_is_uhs_valid(struct sdhci_host *host) > >> > +{ > >> > + 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; > >> > + > >> > + /* > >> > + * The 1.8 V only host controllers don't need to have configurable > >> > + * regulators and pad voltages. In this case the UHS modes can be > >> > + * enabled regardless. > >> > + */ > >> > + if (tegra_host->only_1v8) > >> > + return true; > >> > >> Hm, SD always needs 3.3V capabilities, not? > > > > Yes, the controllers used for eMMCs should have the only_1v8 property > > set and they exit the function here. With controllers used for SD cards, > > the regulator and pad configurations are verified later in the function. > > > > By returning true you ask the controller to enable UHS modes. However, > if you have 1.8V only, there should be no UHS modes advertised (since SD > cards require 1.8V). > > That assumes that UHS modes are a SD card thing only (which I think > strictly speaking should be the case). > > However, at least on Tegra 3 it seems that enabling SD 3.0 is also > required for higher eMMC speeds: > https://patchwork.kernel.org/patch/10521147/ > > So UHS is probably not so much about SD card UHS modes but more about > higher speed modes in general... True. > >> So if the controller is 1.8V only, then only eMMC modes are allowed. > >> > >> You can use MMC_CAP2_HSX00_1_8V in caps2. > > > > I can't quite follow you, how this should be used here? > > > > Similar to > > if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) > > host->mmc->caps |= MMC_CAP_1_8V_DDR > > You can enable higher speed eMMC modes without advertising SD card > modes. Makes sense. Thanks for clearing that up. > >> So far the Tegra SDHCI driver did not use device tree to indicate modes, > >> but maybe we should start doing that. In this case you can use > >> mmc-hs200-1_8v/mmc-hs400-1_8v to indicate higher eMMC speed modes. > >> > >> > + > >> > + /* > >> > + * If the board does not define a regulator for the SDHCI IO voltage, > >> > + * then don't advertise support for UHS modes even if the device > >> > + * supports it because the IO voltage cannot be configured. > >> > + */ > >> > + if (IS_ERR(host->mmc->supply.vqmmc)) > >> > + return false; > >> > >> The stack should already check that and mask caps1 accordingly (see > >> sdhci_setup_host). > > > > True, the logic seems to be duplicated here. Although also > > tegra_sdhci_reset() needs to be change so that the bits masked off by > > sdhci_setup_host() aren't set if this check is removed. > > > > sdhci_setup_host() calls reset before doing initialization (e.g. in > __sdhci_read_caps). > > Checking just for vqmmc presence is bogus IMHO. It does not say anything > about the exact capabilities of that regulator. Yes, by itself it doesn't make much sense. It looks like the regulator voltage checking code from sdhci_setup_host() has to be duplicated to the tegra driver because the regulator checks are done after the reset callback. The sdhci-tegra driver needs to make sure that the faster signaling modes are enabled only if pinctrl properties are present on SD controllers with variable voltage regulators. > I think we should do something like this: > > if (there is a host->mmc->supply.vqmmc) { > if (host->mmc->supply.vqmmc can do 1.8V (or/and also 1.2V?)) { > /* > * Enable SDHCI spec v3.00 support > * This is required for SD UHS modes as well as higher eMMC speeds > */ > if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) > misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; > > if (host->mmc->supply.vqmmc can do 3.3V) { > /* > * Proper SD voltage switching is possible, advertise SD UHS > * modes as supported by host > */ > if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50) > misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR50; > if (soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) > misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50; > if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104) > misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104; > if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50) > clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE; > } > } > } > > > > > >> > + > >> > + /* > >> > + * Later SoC generations require software pad voltage configuration. > >> > + * The UHS modes should only be enabled if the pad configuration states > >> > + * are available on platforms where they are required in order to switch > >> > + * the signaling voltage. > >> > + */ > >> > + if (soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL) > >> > + return tegra_host->pad_control_available; > >> > + > >> > + return false; > >> > +} > >> > + > >> > static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) > >> > { > >> > 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; > >> > u32 misc_ctrl, clk_ctrl; > >> > + bool uhs_valid; > >> > > >> > sdhci_reset(host, mask); > >> > > >> > @@ -160,13 +202,8 @@ static void tegra_sdhci_reset(struct sdhci_host > >> > *host, u8 mask) > >> > > >> > clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE; > >> > > >> > - /* > >> > - * If the board does not define a regulator for the SDHCI > >> > - * IO voltage, then don't advertise support for UHS modes > >> > - * even if the device supports it because the IO voltage > >> > - * cannot be configured. > >> > - */ > >> > - if (!IS_ERR(host->mmc->supply.vqmmc)) { > >> > + uhs_valid = tegra_sdhci_is_uhs_valid(host); > >> > + if (uhs_valid) { > >> > /* Erratum: Enable SDHCI spec v3.00 support */ > >> > if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) > >> > misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; > >> > @@ -286,14 +323,80 @@ 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) > >> > +static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage) > >> > { > >> > 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; > >> > + int ret; > >> > + > >> > + if (!tegra_host->pad_control_available) > >> > + return 0; > >> > + > >> > + if (voltage == MMC_SIGNAL_VOLTAGE_180) { > >> > + ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, > >> > + tegra_host->pinctrl_state_1v8); > >> > + if (ret < 0) > >> > + dev_err(mmc_dev(host->mmc), > >> > + "setting 1.8V failed, ret: %d\n", ret); > >> > + } else { > >> > + ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, > >> > + tegra_host->pinctrl_state_3v3); > >> > + if (ret < 0) > >> > + dev_err(mmc_dev(host->mmc), > >> > + "setting 3.3V failed, ret: %d\n", ret); > >> > + } > >> > > >> > - if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) > >> > - tegra_host->pad_calib_required = true; > > Is this really not needed anymore? Good catch. That probably happened accidentally during a rebase. > >> > + return ret; > >> > +} > >> > + > >> > +static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc, > >> > + struct mmc_ios *ios) > >> > +{ > >> > + struct sdhci_host *host = mmc_priv(mmc); > >> > + int ret = 0; > >> > + > >> > + if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { > >> > + ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage); > >> > + if (ret < 0) > >> > + return ret; > >> > + ret = sdhci_start_signal_voltage_switch(mmc, ios); > >> > + } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { > >> > + ret = sdhci_start_signal_voltage_switch(mmc, ios); > >> > + if (ret < 0) > >> > + return ret; > >> > + ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage); > >> > >> So depending on voltage you first set the pads setting and then do the > >> signaling voltage switch. Is this necessary? Why? > > > > This is done to enforce the constraint of keeping the signaling voltage > > always less or equal to the pad voltage. Driving 3.3 V into a pad that > > has been configured to 1.8 V will damage it. This is stated in the > > Tegra210 and Tegra186 TRMs in SDMMC Initialization Sequece sections of > > controllers supporting voltage switching. > > > > Here when switching from 3.3 V to 1.8 V the regulator is first > > configured to 1.8 V by sdhci_start_signal_voltage_switch() and after > > that the pad is configured to 1.8 V. When going in the other direction > > the pad needs to be first configured to 3.3 V before the regulator > > voltage can be raised. > > Ok makes sense. Can you add a comment, e.g. /* Order of operation > matters, it make sure to keep signaling voltage below pad voltage */ > > > > >> > + } > >> > + > >> > + return ret; > >> > +} > >> > + > >> > +static void tegra_sdhci_init_pinctrl_info(struct device *dev, > >> > + struct sdhci_tegra *tegra_host) > >> > +{ > >> > + tegra_host->pinctrl_sdmmc = devm_pinctrl_get(dev); > >> > + if (IS_ERR(tegra_host->pinctrl_sdmmc)) { > >> > + dev_dbg(dev, "No pinctrl info, err: %ld\n", > >> > + PTR_ERR(tegra_host->pinctrl_sdmmc)); > >> > + return; > >> > + } > >> > + > >> > + tegra_host->pinctrl_state_3v3 = > >> > + pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-3v3"); > >> > + if (IS_ERR(tegra_host->pinctrl_state_3v3)) { > >> > + dev_err(dev, "Missing 3.3V pad state, err: %ld\n", > >> > + PTR_ERR(tegra_host->pinctrl_state_3v3)); > >> > + return; > >> > + } > >> > + > >> > + tegra_host->pinctrl_state_1v8 = > >> > + pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-1v8"); > >> > + if (IS_ERR(tegra_host->pinctrl_state_1v8)) { > >> > + dev_err(dev, "Missing 1.8V pad state, err: %ld\n", > >> > + PTR_ERR(tegra_host->pinctrl_state_3v3)); > >> > >> Is missing pad states considered as error? If yes, we should return a > >> error code and make the probe function fail. > >> > >> If it is ok to run it without the states, then this should be dev_warn > >> or dev_info. > > > > I don't think failing probe due to missing pinctrl entries can be done > > because it would break backwards compatibility with pre-existing dtbs. > > Also SDHCI controllers with fixed signaling voltage don't support pad > > voltage reconfiguration and therefore the pinctrl properties won't be > > there either. In the case of fixed voltage SDHCI controllers the > > "nvidia,only-1-8-v" property is used to signal that pad reconfiguration > > doesn't need to be performed. > > Ok, if they are not mandatory, just use dev_warn(...). > > Btw, > > + if (soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL) { > + host->mmc_host_ops.start_signal_voltage_switch = > + sdhci_tegra_start_signal_voltage_switch; > + tegra_sdhci_init_pinctrl_info(&pdev->dev, tegra_host); > + } > + > > Can we make tegra_sdhci_init_pinctrl_info return a boolean and do the > tegra_host->pad_control_available assignment here? I think this would be > cleaner. > > It also won't assign host->mmc_host_ops.start_signal_voltage_switch if > not needed. > > if (soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL && > tegra_sdhci_init_pinctrl_info(&pdev->dev, tegra_host)) { > host->mmc_host_ops.start_signal_voltage_switch = > sdhci_tegra_start_signal_voltage_switch; > tegra_host->pad_control_available = true; > } -Aapo -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html