mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-20 19:44:23 +00:00
feat(st-sdmmc2): manage cards power cycle
To correctly initialize the MMC devices, a power cycle is required. For this we need to: - disable vmmc-supply regulator - make the power cycle required for SDMMC2 peripheral - enable regulators Change-Id: I2be6d9082d1cc4c864a82cf2c31ff8522e2d31a2 Signed-off-by: Yann Gautier <yann.gautier@st.com>
This commit is contained in:
parent
967a8e63c3
commit
258bef913a
2 changed files with 39 additions and 7 deletions
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -8,10 +8,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <libfdt.h>
|
|
||||||
|
|
||||||
#include <platform_def.h>
|
|
||||||
|
|
||||||
#include <arch.h>
|
#include <arch.h>
|
||||||
#include <arch_helpers.h>
|
#include <arch_helpers.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
@ -22,8 +18,11 @@
|
||||||
#include <drivers/st/stm32mp_reset.h>
|
#include <drivers/st/stm32mp_reset.h>
|
||||||
#include <lib/mmio.h>
|
#include <lib/mmio.h>
|
||||||
#include <lib/utils.h>
|
#include <lib/utils.h>
|
||||||
|
#include <libfdt.h>
|
||||||
#include <plat/common/platform.h>
|
#include <plat/common/platform.h>
|
||||||
|
|
||||||
|
#include <platform_def.h>
|
||||||
|
|
||||||
/* Registers offsets */
|
/* Registers offsets */
|
||||||
#define SDMMC_POWER 0x00U
|
#define SDMMC_POWER 0x00U
|
||||||
#define SDMMC_CLKCR 0x04U
|
#define SDMMC_CLKCR 0x04U
|
||||||
|
@ -50,6 +49,7 @@
|
||||||
|
|
||||||
/* SDMMC power control register */
|
/* SDMMC power control register */
|
||||||
#define SDMMC_POWER_PWRCTRL GENMASK(1, 0)
|
#define SDMMC_POWER_PWRCTRL GENMASK(1, 0)
|
||||||
|
#define SDMMC_POWER_PWRCTRL_PWR_CYCLE BIT(1)
|
||||||
#define SDMMC_POWER_DIRPOL BIT(4)
|
#define SDMMC_POWER_DIRPOL BIT(4)
|
||||||
|
|
||||||
/* SDMMC clock control register */
|
/* SDMMC clock control register */
|
||||||
|
@ -117,6 +117,13 @@
|
||||||
#define TIMEOUT_US_10_MS 10000U
|
#define TIMEOUT_US_10_MS 10000U
|
||||||
#define TIMEOUT_US_1_S 1000000U
|
#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"
|
#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2"
|
||||||
|
|
||||||
static void stm32_sdmmc2_init(void);
|
static void stm32_sdmmc2_init(void);
|
||||||
|
@ -154,6 +161,25 @@ static void stm32_sdmmc2_init(void)
|
||||||
freq = MIN(sdmmc2_params.max_freq, freq);
|
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);
|
clock_div = div_round_up(sdmmc2_params.clk_rate, freq * 2U);
|
||||||
|
|
||||||
mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div |
|
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,
|
mmio_write_32(base + SDMMC_POWER,
|
||||||
SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol);
|
SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol);
|
||||||
|
|
||||||
mdelay(1);
|
mdelay(POWER_ON_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_sdmmc2_stop_transfer(void)
|
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.max_freq = fdt32_to_cpu(*cuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sdmmc2_params.vmmc_regu = regulator_get_by_supply_name(fdt, sdmmc_node, "vmmc");
|
||||||
|
|
||||||
return 0;
|
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));
|
memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params));
|
||||||
|
|
||||||
|
sdmmc2_params.vmmc_regu = NULL;
|
||||||
|
|
||||||
if (stm32_sdmmc2_dt_get_config() != 0) {
|
if (stm32_sdmmc2_dt_get_config() != 0) {
|
||||||
ERROR("%s: DT error\n", __func__);
|
ERROR("%s: DT error\n", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -10,6 +10,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include <drivers/mmc.h>
|
#include <drivers/mmc.h>
|
||||||
|
#include <drivers/st/regulator.h>
|
||||||
|
|
||||||
struct stm32_sdmmc2_params {
|
struct stm32_sdmmc2_params {
|
||||||
uintptr_t reg_base;
|
uintptr_t reg_base;
|
||||||
|
@ -24,6 +25,7 @@ struct stm32_sdmmc2_params {
|
||||||
unsigned int reset_id;
|
unsigned int reset_id;
|
||||||
unsigned int max_freq;
|
unsigned int max_freq;
|
||||||
bool use_dma;
|
bool use_dma;
|
||||||
|
struct rdev *vmmc_regu;
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned long long stm32_sdmmc2_mmc_get_device_size(void);
|
unsigned long long stm32_sdmmc2_mmc_get_device_size(void);
|
||||||
|
|
Loading…
Add table
Reference in a new issue