[PATCH 1/2] mmc: stm32_sdmmc2: Add support for probing bus voltage level translator
Patrice CHOTARD
patrice.chotard at foss.st.com
Tue Nov 30 11:34:07 CET 2021
Hi Marek
On 11/13/21 3:29 AM, Marek Vasut wrote:
> Add support for testing whether bus voltage level translator is present
> and operational. This is useful on systems where the bus voltage level
> translator is optional, as the translator can be auto-detected by the
> driver and the feedback clock functionality can be disabled if it is
> not present.
>
> The translator test sets CMD high to avoid interfering with a card, and
> then verifies whether signal set on CK is detected on CKIN. If the signal
> is detected, translator is present, otherwise the CKIN feedback clock are
> disabled.
>
> Signed-off-by: Marek Vasut <marex at denx.de>
> Cc: Patrice Chotard <patrice.chotard at foss.st.com>
> Cc: Patrick Delaunay <patrick.delaunay at foss.st.com>
> ---
> drivers/mmc/stm32_sdmmc2.c | 63 +++++++++++++++++++++++++++++++++++++-
> 1 file changed, 62 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c
> index a3cdf7bcd9f..44bfc911af2 100644
> --- a/drivers/mmc/stm32_sdmmc2.c
> +++ b/drivers/mmc/stm32_sdmmc2.c
> @@ -16,6 +16,7 @@
> #include <asm/bitops.h>
> #include <asm/cache.h>
> #include <dm/device_compat.h>
> +#include <dm/pinctrl.h>
> #include <linux/bitops.h>
> #include <linux/delay.h>
> #include <linux/libfdt.h>
> @@ -645,6 +646,66 @@ static const struct dm_mmc_ops stm32_sdmmc2_ops = {
> .host_power_cycle = stm32_sdmmc2_host_power_cycle,
> };
>
> +static int stm32_sdmmc2_probe_level_translator(struct udevice *dev)
> +{
> + struct stm32_sdmmc2_priv *priv = dev_get_priv(dev);
> + struct gpio_desc cmd_gpio;
> + struct gpio_desc ck_gpio;
> + struct gpio_desc ckin_gpio;
> + int clk_hi, clk_lo, ret;
> +
> + /*
> + * Assume the level translator is present if st,use-ckin is set.
> + * This is to cater for DTs which do not implement this test.
> + */
> + priv->clk_reg_msk |= SDMMC_CLKCR_SELCLKRX_CKIN;
> +
> + ret = gpio_request_by_name(dev, "st,cmd-gpios", 0, &cmd_gpio,
> + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
> + if (ret)
> + goto exit_cmd;
> +
> + ret = gpio_request_by_name(dev, "st,ck-gpios", 0, &ck_gpio,
> + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
> + if (ret)
> + goto exit_ck;
> +
> + ret = gpio_request_by_name(dev, "st,ckin-gpios", 0, &ckin_gpio,
> + GPIOD_IS_IN);
> + if (ret)
> + goto exit_ckin;
> +
> + /* All GPIOs are valid, test whether level translator works */
> +
> + /* Sample CKIN */
> + clk_hi = !!dm_gpio_get_value(&ckin_gpio);
> +
> + /* Set CK low */
> + dm_gpio_set_value(&ck_gpio, 0);
> +
> + /* Sample CKIN */
> + clk_lo = !!dm_gpio_get_value(&ckin_gpio);
> +
> + /* Tristate all */
> + dm_gpio_set_dir_flags(&cmd_gpio, GPIOD_IS_IN);
> + dm_gpio_set_dir_flags(&ck_gpio, GPIOD_IS_IN);
> +
> + /* Level translator is present if CK signal is propagated to CKIN */
> + if (!clk_hi || clk_lo)
> + priv->clk_reg_msk &= ~SDMMC_CLKCR_SELCLKRX_CKIN;
> +
> + dm_gpio_free(dev, &ckin_gpio);
> +
> +exit_ckin:
> + dm_gpio_free(dev, &ck_gpio);
> +exit_ck:
> + dm_gpio_free(dev, &cmd_gpio);
> +exit_cmd:
> + pinctrl_select_state(dev, "default");
> +
> + return 0;
> +}
> +
> static int stm32_sdmmc2_probe(struct udevice *dev)
> {
> struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
> @@ -662,7 +723,7 @@ static int stm32_sdmmc2_probe(struct udevice *dev)
> if (dev_read_bool(dev, "st,sig-dir"))
> priv->pwr_reg_msk |= SDMMC_POWER_DIRPOL;
> if (dev_read_bool(dev, "st,use-ckin"))
> - priv->clk_reg_msk |= SDMMC_CLKCR_SELCLKRX_CKIN;
> + stm32_sdmmc2_probe_level_translator(dev);
>
> ret = clk_get_by_index(dev, 0, &priv->clk);
> if (ret)
>
For the series, applied to u-boot-stm32/next
Thanks
Patrice
More information about the U-Boot
mailing list