diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c index d3adeab13..2102782ad 100644 --- a/drivers/st/mmc/stm32_sdmmc2.c +++ b/drivers/st/mmc/stm32_sdmmc2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved + * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,10 +8,6 @@ #include #include -#include - -#include - #include #include #include @@ -22,8 +18,11 @@ #include #include #include +#include #include +#include + /* Registers offsets */ #define SDMMC_POWER 0x00U #define SDMMC_CLKCR 0x04U @@ -50,6 +49,7 @@ /* SDMMC power control register */ #define SDMMC_POWER_PWRCTRL GENMASK(1, 0) +#define SDMMC_POWER_PWRCTRL_PWR_CYCLE BIT(1) #define SDMMC_POWER_DIRPOL BIT(4) /* SDMMC clock control register */ @@ -117,6 +117,13 @@ #define TIMEOUT_US_10_MS 10000U #define TIMEOUT_US_1_S 1000000U +/* Power cycle delays in ms */ +#define VCC_POWER_OFF_DELAY 2 +#define VCC_POWER_ON_DELAY 2 +#define POWER_CYCLE_DELAY 2 +#define POWER_OFF_DELAY 2 +#define POWER_ON_DELAY 1 + #define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" static void stm32_sdmmc2_init(void); @@ -154,6 +161,25 @@ static void stm32_sdmmc2_init(void) freq = MIN(sdmmc2_params.max_freq, freq); } + if (sdmmc2_params.vmmc_regu != NULL) { + regulator_disable(sdmmc2_params.vmmc_regu); + } + + mdelay(VCC_POWER_OFF_DELAY); + + mmio_write_32(base + SDMMC_POWER, + SDMMC_POWER_PWRCTRL_PWR_CYCLE | sdmmc2_params.dirpol); + mdelay(POWER_CYCLE_DELAY); + + if (sdmmc2_params.vmmc_regu != NULL) { + regulator_enable(sdmmc2_params.vmmc_regu); + } + + mdelay(VCC_POWER_ON_DELAY); + + mmio_write_32(base + SDMMC_POWER, sdmmc2_params.dirpol); + mdelay(POWER_OFF_DELAY); + clock_div = div_round_up(sdmmc2_params.clk_rate, freq * 2U); mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | @@ -163,7 +189,7 @@ static void stm32_sdmmc2_init(void) mmio_write_32(base + SDMMC_POWER, SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol); - mdelay(1); + mdelay(POWER_ON_DELAY); } static int stm32_sdmmc2_stop_transfer(void) @@ -689,6 +715,8 @@ static int stm32_sdmmc2_dt_get_config(void) sdmmc2_params.max_freq = fdt32_to_cpu(*cuint); } + sdmmc2_params.vmmc_regu = regulator_get_by_supply_name(fdt, sdmmc_node, "vmmc"); + return 0; } @@ -709,6 +737,8 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params)); + sdmmc2_params.vmmc_regu = NULL; + if (stm32_sdmmc2_dt_get_config() != 0) { ERROR("%s: DT error\n", __func__); return -ENOMEM; diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h index 4853208c2..c83f62509 100644 --- a/include/drivers/st/stm32_sdmmc2.h +++ b/include/drivers/st/stm32_sdmmc2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -10,6 +10,7 @@ #include #include +#include struct stm32_sdmmc2_params { uintptr_t reg_base; @@ -24,6 +25,7 @@ struct stm32_sdmmc2_params { unsigned int reset_id; unsigned int max_freq; bool use_dma; + struct rdev *vmmc_regu; }; unsigned long long stm32_sdmmc2_mmc_get_device_size(void);