Add mmc-pwrseq file to provide a generic interface. Signed-off-by: Jaehoon Chung <jh80.ch...@samsung.com> --- Changelog on V2: - Remove "default y" in Kconfig --- drivers/mmc/Kconfig | 7 ++++++ drivers/mmc/Makefile | 1 + drivers/mmc/mmc-pwrseq.c | 51 ++++++++++++++++++++++++++++++++++++++++ include/mmc.h | 14 +++++++++++ 4 files changed, 73 insertions(+) create mode 100644 drivers/mmc/mmc-pwrseq.c
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index f8ea92172e44..f8ca52efb6b7 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -18,6 +18,13 @@ config MMC_WRITE help Enable write access to MMC and SD Cards +config MMC_PWRSEQ + bool "HW reset support for eMMC" + depends on PWRSEQ + help + Ths select Hardware reset support aka pwrseq-emmc for eMMC + devices. + config MMC_BROKEN_CD bool "Poll for broken card detection case" help diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 1c849cbab2f1..89d6af3db30b 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -6,6 +6,7 @@ obj-y += mmc.o obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o +obj-$(CONFIG_MMC_PWRSEQ) += mmc-pwrseq.o obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o ifndef CONFIG_$(SPL_)BLK diff --git a/drivers/mmc/mmc-pwrseq.c b/drivers/mmc/mmc-pwrseq.c new file mode 100644 index 000000000000..2539f61323d1 --- /dev/null +++ b/drivers/mmc/mmc-pwrseq.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2021 SAMSUNG Electronics + * Jaehoon Chung <jh80.ch...@samsung.com> + */ + +#include <common.h> +#include <dm.h> +#include <mmc.h> +#include <pwrseq.h> +#include <asm/gpio.h> +#include <linux/delay.h> + +int mmc_pwrseq_get_power(struct udevice *dev, struct mmc_config *cfg) +{ + /* Enable power if needed */ + return uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq", + &cfg->pwr_dev); +} + +static int mmc_pwrseq_set_power(struct udevice *dev, bool enable) +{ + struct gpio_desc reset; + int ret; + + ret = gpio_request_by_name(dev, "reset-gpios", 0, &reset, GPIOD_IS_OUT); + if (ret) + return ret; + dm_gpio_set_value(&reset, 1); + udelay(1); + dm_gpio_set_value(&reset, 0); + udelay(200); + + return 0; +} + +static const struct pwrseq_ops mmc_pwrseq_ops = { + .set_power = mmc_pwrseq_set_power, +}; + +static const struct udevice_id mmc_pwrseq_ids[] = { + { .compatible = "mmc-pwrseq-emmc" }, + { } +}; + +U_BOOT_DRIVER(mmc_pwrseq_drv) = { + .name = "mmc_pwrseq_emmc", + .id = UCLASS_PWRSEQ, + .of_match = mmc_pwrseq_ids, + .ops = &mmc_pwrseq_ops, +}; diff --git a/include/mmc.h b/include/mmc.h index 1d377e0281f1..637081415430 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -591,6 +591,9 @@ struct mmc_config { uint f_max; uint b_max; unsigned char part_type; +#ifdef CONFIG_MMC_PWRSEQ + struct udevice *pwr_dev; +#endif }; struct sd_ssr { @@ -801,6 +804,17 @@ int mmc_deinit(struct mmc *mmc); */ int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg); +#ifdef CONFIG_MMC_PWRSEQ +/** + * mmc_pwrseq_get_power() - get a power device from device tree + * + * @dev: MMC device + * @cfg: MMC configuration + * @return 0 if OK, -ve on error + */ +int mmc_pwrseq_get_power(struct udevice *dev, struct mmc_config *cfg); +#endif + int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size); /** -- 2.29.0