summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/arm/dts/k3-am65-main.dtsi12
-rw-r--r--arch/arm/dts/k3-am654-base-board-u-boot.dtsi11
-rw-r--r--arch/arm/dts/k3-j721e-main.dtsi15
-rw-r--r--arch/arm/dts/k3-j721e-r5-common-proc-board.dts4
-rw-r--r--arch/arm/mach-imx/imx8/image.c3
-rw-r--r--arch/arm/mach-k3/am6_init.c33
-rw-r--r--arch/arm/mach-k3/include/mach/sysfw-loader.h2
-rw-r--r--arch/arm/mach-k3/j721e_init.c33
-rw-r--r--arch/arm/mach-k3/sysfw-loader.c6
-rw-r--r--common/spl/spl_mmc.c11
-rw-r--r--configs/am65x_evm_a53_defconfig1
-rw-r--r--configs/am65x_evm_r5_defconfig1
-rw-r--r--configs/cortina_presidio-asic-emmc_defconfig33
-rw-r--r--configs/j721e_evm_a72_defconfig3
-rw-r--r--configs/j721e_evm_r5_defconfig3
-rw-r--r--drivers/mmc/Kconfig11
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/am654_sdhci.c173
-rw-r--r--drivers/mmc/ca_dw_mmc.c181
-rw-r--r--drivers/mmc/fsl_esdhc_imx.c1
-rw-r--r--drivers/mmc/mmc-uclass.c15
-rw-r--r--drivers/mmc/mmc.c20
-rw-r--r--drivers/mmc/omap_hsmmc.c1
-rw-r--r--drivers/mmc/sdhci.c15
-rw-r--r--drivers/mmc/zynq_sdhci.c1
-rw-r--r--include/configs/am65x_evm.h2
-rw-r--r--include/mmc.h20
-rw-r--r--include/sdhci.h1
29 files changed, 531 insertions, 84 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 37ff21a037..2c43573ff5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -180,6 +180,7 @@ F: board/cortina/common/
F: drivers/gpio/cortina_gpio.c
F: drivers/watchdog/cortina_wdt.c
F: drivers/serial/serial_cortina.c
+F: drivers/mmc/ca_dw_mmc.c
ARM/CZ.NIC TURRIS MOX SUPPORT
M: Marek Behun <marek.behun@nic.cz>
@@ -672,6 +673,7 @@ F: board/cortina/common/
F: drivers/gpio/cortina_gpio.c
F: drivers/watchdog/cortina_wdt.c
F: drivers/serial/serial_cortina.c
+F: drivers/mmc/ca_dw_mmc.c
MIPS MSCC
M: Gregory CLEMENT <gregory.clement@bootlin.com>
diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi
index ab40dafceb..028f57379b 100644
--- a/arch/arm/dts/k3-am65-main.dtsi
+++ b/arch/arm/dts/k3-am65-main.dtsi
@@ -98,7 +98,17 @@
interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
- ti,otap-del-sel = <0x2>;
+ ti,otap-del-sel-legacy = <0x0>;
+ ti,otap-del-sel-mmc-hs = <0x0>;
+ ti,otap-del-sel-sd-hs = <0x0>;
+ ti,otap-del-sel-sdr12 = <0x0>;
+ ti,otap-del-sel-sdr25 = <0x0>;
+ ti,otap-del-sel-sdr50 = <0x8>;
+ ti,otap-del-sel-sdr104 = <0x5>;
+ ti,otap-del-sel-ddr50 = <0x5>;
+ ti,otap-del-sel-ddr52 = <0x5>;
+ ti,otap-del-sel-hs200 = <0x5>;
+ ti,otap-del-sel-hs400 = <0x0>;
ti,trm-icp = <0x8>;
dma-coherent;
};
diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
index a349edcfa5..54ecb3d444 100644
--- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
+++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
@@ -29,7 +29,16 @@
clock-names = "clk_ahb", "clk_xin";
power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>;
max-frequency = <25000000>;
- ti,otap-del-sel = <0x2>;
+ ti,otap-del-sel-legacy = <0x0>;
+ ti,otap-del-sel-mmc-hs = <0x0>;
+ ti,otap-del-sel-sd-hs = <0x0>;
+ ti,otap-del-sel-sdr12 = <0x0>;
+ ti,otap-del-sel-sdr25 = <0x0>;
+ ti,otap-del-sel-sdr50 = <0x8>;
+ ti,otap-del-sel-sdr104 = <0x7>;
+ ti,otap-del-sel-ddr50 = <0x4>;
+ ti,otap-del-sel-ddr52 = <0x4>;
+ ti,otap-del-sel-hs200 = <0x7>;
ti,trm-icp = <0x8>;
};
diff --git a/arch/arm/dts/k3-j721e-main.dtsi b/arch/arm/dts/k3-j721e-main.dtsi
index 45ac98c47e..1433932e7f 100644
--- a/arch/arm/dts/k3-j721e-main.dtsi
+++ b/arch/arm/dts/k3-j721e-main.dtsi
@@ -232,9 +232,14 @@
assigned-clocks = <&k3_clks 91 1>;
assigned-clock-parents = <&k3_clks 91 2>;
bus-width = <8>;
- ti,otap-del-sel = <0x2>;
ti,trm-icp = <0x8>;
dma-coherent;
+ mmc-ddr-1_8v;
+ ti,otap-del-sel-legacy = <0x0>;
+ ti,otap-del-sel-mmc-hs = <0x0>;
+ ti,otap-del-sel-ddr52 = <0x5>;
+ ti,otap-del-sel-hs200 = <0x6>;
+ ti,otap-del-sel-hs400 = <0x0>;
};
main_sdhci1: sdhci@4fb0000 {
@@ -246,7 +251,13 @@
clocks = <&k3_clks 92 0>, <&k3_clks 92 5>;
assigned-clocks = <&k3_clks 92 0>;
assigned-clock-parents = <&k3_clks 92 1>;
- ti,otap-del-sel = <0x2>;
+ ti,otap-del-sel-legacy = <0x0>;
+ ti,otap-del-sel-sd-hs = <0xf>;
+ ti,otap-del-sel-sdr12 = <0xf>;
+ ti,otap-del-sel-sdr25 = <0xf>;
+ ti,otap-del-sel-sdr50 = <0xc>;
+ ti,otap-del-sel-sdr104 = <0x5>;
+ ti,otap-del-sel-ddr50 = <0xc>;
ti,trm-icp = <0x8>;
dma-coherent;
};
diff --git a/arch/arm/dts/k3-j721e-r5-common-proc-board.dts b/arch/arm/dts/k3-j721e-r5-common-proc-board.dts
index eb577cdbc6..5973e211c3 100644
--- a/arch/arm/dts/k3-j721e-r5-common-proc-board.dts
+++ b/arch/arm/dts/k3-j721e-r5-common-proc-board.dts
@@ -34,14 +34,14 @@
u-boot,dm-spl;
};
- clk_200mhz: dummy_clock {
+ clk_200mhz: dummy_clock_200mhz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <200000000>;
u-boot,dm-spl;
};
- clk_19_2mhz: dummy_clock {
+ clk_19_2mhz: dummy_clock_19_2mhz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <19200000>;
diff --git a/arch/arm/mach-imx/imx8/image.c b/arch/arm/mach-imx/imx8/image.c
index c956a8092d..e6b299691d 100644
--- a/arch/arm/mach-imx/imx8/image.c
+++ b/arch/arm/mach-imx/imx8/image.c
@@ -197,7 +197,8 @@ unsigned long spl_spi_get_uboot_offs(struct spi_flash *flash)
#endif
#ifdef CONFIG_SPL_MMC_SUPPORT
-unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
+unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
+ unsigned long raw_sect)
{
int end;
diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c
index 63cd7e0458..d0b10e58ad 100644
--- a/arch/arm/mach-k3/am6_init.c
+++ b/arch/arm/mach-k3/am6_init.c
@@ -17,6 +17,7 @@
#include <dm/uclass-internal.h>
#include <dm/pinctrl.h>
#include <linux/soc/ti/ti_sci_protocol.h>
+#include <mmc.h>
#ifdef CONFIG_SPL_BUILD
#ifdef CONFIG_K3_LOAD_SYSFW
@@ -86,6 +87,33 @@ static void store_boot_index_from_rom(void)
bootindex = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX);
}
+#if defined(CONFIG_K3_LOAD_SYSFW)
+void k3_mmc_stop_clock(void)
+{
+ if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+ struct mmc *mmc = find_mmc_device(0);
+
+ if (!mmc)
+ return;
+
+ mmc->saved_clock = mmc->clock;
+ mmc_set_clock(mmc, 0, true);
+ }
+}
+
+void k3_mmc_restart_clock(void)
+{
+ if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+ struct mmc *mmc = find_mmc_device(0);
+
+ if (!mmc)
+ return;
+
+ mmc_set_clock(mmc, mmc->saved_clock, false);
+ }
+}
+#endif
+
void board_init_f(ulong dummy)
{
#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM654_DDRSS)
@@ -138,7 +166,10 @@ void board_init_f(ulong dummy)
* callback hook, effectively switching on (or over) the console
* output.
*/
- k3_sysfw_loader(preloader_console_init);
+ k3_sysfw_loader(k3_mmc_stop_clock, k3_mmc_restart_clock);
+
+ /* Prepare console output */
+ preloader_console_init();
/* Disable ROM configured firewalls right after loading sysfw */
#ifdef CONFIG_TI_SECURE_DEVICE
diff --git a/arch/arm/mach-k3/include/mach/sysfw-loader.h b/arch/arm/mach-k3/include/mach/sysfw-loader.h
index 36eb265348..6f5612b4fd 100644
--- a/arch/arm/mach-k3/include/mach/sysfw-loader.h
+++ b/arch/arm/mach-k3/include/mach/sysfw-loader.h
@@ -7,6 +7,6 @@
#ifndef _SYSFW_LOADER_H_
#define _SYSFW_LOADER_H_
-void k3_sysfw_loader(void (*config_pm_done_callback)(void));
+void k3_sysfw_loader(void (*config_pm_pre_callback)(void), void (*config_pm_done_callback)(void));
#endif
diff --git a/arch/arm/mach-k3/j721e_init.c b/arch/arm/mach-k3/j721e_init.c
index f7f7398081..0994522f6c 100644
--- a/arch/arm/mach-k3/j721e_init.c
+++ b/arch/arm/mach-k3/j721e_init.c
@@ -18,6 +18,7 @@
#include <dm.h>
#include <dm/uclass-internal.h>
#include <dm/pinctrl.h>
+#include <mmc.h>
#ifdef CONFIG_SPL_BUILD
#ifdef CONFIG_K3_LOAD_SYSFW
@@ -100,6 +101,33 @@ static void ctrl_mmr_unlock(void)
mmr_unlock(CTRL_MMR0_BASE, 7);
}
+#if defined(CONFIG_K3_LOAD_SYSFW)
+void k3_mmc_stop_clock(void)
+{
+ if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+ struct mmc *mmc = find_mmc_device(0);
+
+ if (!mmc)
+ return;
+
+ mmc->saved_clock = mmc->clock;
+ mmc_set_clock(mmc, 0, true);
+ }
+}
+
+void k3_mmc_restart_clock(void)
+{
+ if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+ struct mmc *mmc = find_mmc_device(0);
+
+ if (!mmc)
+ return;
+
+ mmc_set_clock(mmc, mmc->saved_clock, false);
+ }
+}
+#endif
+
/*
* This uninitialized global variable would normal end up in the .bss section,
* but the .bss is cleared between writing and reading this variable, so move
@@ -154,7 +182,10 @@ void board_init_f(ulong dummy)
* callback hook, effectively switching on (or over) the console
* output.
*/
- k3_sysfw_loader(preloader_console_init);
+ k3_sysfw_loader(k3_mmc_stop_clock, k3_mmc_restart_clock);
+
+ /* Prepare console output */
+ preloader_console_init();
/* Disable ROM configured firewalls right after loading sysfw */
#ifdef CONFIG_TI_SECURE_DEVICE
diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c
index 94dbeb9437..db02607b17 100644
--- a/arch/arm/mach-k3/sysfw-loader.c
+++ b/arch/arm/mach-k3/sysfw-loader.c
@@ -197,7 +197,8 @@ exit:
}
#endif
-void k3_sysfw_loader(void (*config_pm_done_callback)(void))
+void k3_sysfw_loader(void (*config_pm_pre_callback) (void),
+ void (*config_pm_done_callback)(void))
{
struct spl_image_info spl_image = { 0 };
struct spl_boot_device bootdev = { 0 };
@@ -291,6 +292,9 @@ void k3_sysfw_loader(void (*config_pm_done_callback)(void))
/* Get handle for accessing SYSFW services */
ti_sci = get_ti_sci_handle();
+ if (config_pm_pre_callback)
+ config_pm_pre_callback();
+
/* Parse and apply the different SYSFW configuration fragments */
k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci);
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 3e6a17c110..a2ea363e96 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -317,13 +317,10 @@ int spl_boot_partition(const u32 boot_device)
}
#endif
-unsigned long __weak spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
+unsigned long __weak spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
+ unsigned long raw_sect)
{
-#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
- return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR;
-#else
- return 0;
-#endif
+ return raw_sect;
}
int spl_mmc_load(struct spl_image_info *spl_image,
@@ -392,7 +389,7 @@ int spl_mmc_load(struct spl_image_info *spl_image,
return err;
}
- raw_sect = spl_mmc_get_uboot_raw_sector(mmc);
+ raw_sect = spl_mmc_get_uboot_raw_sector(mmc, raw_sect);
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
err = mmc_load_image_raw_partition(spl_image, mmc, raw_part,
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig
index 121d8de231..df7723b71e 100644
--- a/configs/am65x_evm_a53_defconfig
+++ b/configs/am65x_evm_a53_defconfig
@@ -74,6 +74,7 @@ CONFIG_DM_KEYBOARD=y
CONFIG_DM_MAILBOX=y
CONFIG_K3_SEC_PROXY=y
CONFIG_DM_MMC=y
+CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ADMA=y
CONFIG_SPL_MMC_SDHCI_ADMA=y
diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig
index 69055d5536..b475aceefe 100644
--- a/configs/am65x_evm_r5_defconfig
+++ b/configs/am65x_evm_r5_defconfig
@@ -73,6 +73,7 @@ CONFIG_K3_SEC_PROXY=y
CONFIG_MISC=y
CONFIG_K3_AVS0=y
CONFIG_DM_MMC=y
+CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_SDHCI=y
CONFIG_SPL_MMC_SDHCI_ADMA=y
CONFIG_MMC_SDHCI_AM654=y
diff --git a/configs/cortina_presidio-asic-emmc_defconfig b/configs/cortina_presidio-asic-emmc_defconfig
new file mode 100644
index 0000000000..e10008a2b7
--- /dev/null
+++ b/configs/cortina_presidio-asic-emmc_defconfig
@@ -0,0 +1,33 @@
+CONFIG_ARM=y
+# CONFIG_SYS_ARCH_TIMER is not set
+CONFIG_TARGET_PRESIDIO_ASIC=y
+CONFIG_SYS_TEXT_BASE=0x04000000
+CONFIG_ENV_SIZE=0x20000
+CONFIG_DM_GPIO=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_IDENT_STRING="Presidio-SoC"
+CONFIG_SHOW_BOOT_PROGRESS=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_SYS_PROMPT="G3#"
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_WDT=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_DEFAULT_DEVICE_TREE="ca-presidio-engboard"
+# CONFIG_NET is not set
+CONFIG_DM=y
+CONFIG_CORTINA_GPIO=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_CORTINA=y
+CONFIG_DM_SERIAL=y
+CONFIG_CORTINA_UART=y
+CONFIG_WDT=y
+CONFIG_WDT_CORTINA=y
diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig
index ef44ed0367..b27f9ba27b 100644
--- a/configs/j721e_evm_a72_defconfig
+++ b/configs/j721e_evm_a72_defconfig
@@ -29,6 +29,8 @@ CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_SPL_DM_MAILBOX=y
@@ -99,6 +101,7 @@ CONFIG_SYS_I2C_OMAP24XX=y
CONFIG_DM_MAILBOX=y
CONFIG_K3_SEC_PROXY=y
CONFIG_DM_MMC=y
+CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ADMA=y
CONFIG_SPL_MMC_SDHCI_ADMA=y
diff --git a/configs/j721e_evm_r5_defconfig b/configs/j721e_evm_r5_defconfig
index 607e748ef7..ea70c34c5a 100644
--- a/configs/j721e_evm_r5_defconfig
+++ b/configs/j721e_evm_r5_defconfig
@@ -27,6 +27,8 @@ CONFIG_USE_BOOTCOMMAND=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_SEPARATE_BSS=y
CONFIG_SPL_EARLY_BSS=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_SPL_DM_MAILBOX=y
@@ -77,6 +79,7 @@ CONFIG_MISC=y
CONFIG_FS_LOADER=y
CONFIG_K3_AVS0=y
CONFIG_DM_MMC=y
+CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_SDHCI=y
CONFIG_SPL_MMC_SDHCI_ADMA=y
CONFIG_MMC_SDHCI_AM654=y
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 2f0eedc22f..bb38787eca 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -205,6 +205,17 @@ config MMC_DW
block, this provides host support for SD and MMC interfaces, in both
PIO, internal DMA mode and external DMA mode.
+config MMC_DW_CORTINA
+ bool "Cortina specific extensions for Synopsys DW Memory Card Interface"
+ depends on DM_MMC
+ depends on MMC_DW
+ depends on BLK
+ default n
+ help
+ This selects support for Cortina SoC specific extensions to the
+ Synopsys DesignWare Memory Card Interface driver. Select this option
+ for platforms based on Cortina CAxxxx Soc's.
+
config MMC_DW_EXYNOS
bool "Exynos specific extensions for Synopsys DW Memory Card Interface"
depends on ARCH_EXYNOS
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 9c1f8e56e2..615b724bf0 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -20,6 +20,7 @@ endif
obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
obj-$(CONFIG_MMC_DAVINCI) += davinci_mmc.o
obj-$(CONFIG_MMC_DW) += dw_mmc.o
+obj-$(CONFIG_MMC_DW_CORTINA) += ca_dw_mmc.o
obj-$(CONFIG_MMC_DW_EXYNOS) += exynos_dw_mmc.o
obj-$(CONFIG_MMC_DW_K3) += hi6220_dw_mmc.o
obj-$(CONFIG_MMC_DW_ROCKCHIP) += rockchip_dw_mmc.o
diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index aad9d8b85b..ca76e1f559 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -74,7 +74,7 @@ struct am654_sdhci_plat {
struct mmc mmc;
struct regmap *base;
bool non_removable;
- u32 otap_del_sel;
+ u32 otap_del_sel[11];
u32 trm_icp;
u32 drv_strength;
u32 strb_sel;
@@ -86,6 +86,25 @@ struct am654_sdhci_plat {
bool dll_on;
};
+struct timing_data {
+ const char *binding;
+ u32 capability;
+};
+
+static const struct timing_data td[] = {
+ [MMC_LEGACY] = {"ti,otap-del-sel-legacy", 0},
+ [MMC_HS] = {"ti,otap-del-sel-mmc-hs", MMC_CAP(MMC_HS)},
+ [SD_HS] = {"ti,otap-del-sel-sd-hs", MMC_CAP(SD_HS)},
+ [UHS_SDR12] = {"ti,otap-del-sel-sdr12", MMC_CAP(UHS_SDR12)},
+ [UHS_SDR25] = {"ti,otap-del-sel-sdr25", MMC_CAP(UHS_SDR25)},
+ [UHS_SDR50] = {"ti,otap-del-sel-sdr50", MMC_CAP(UHS_SDR50)},
+ [UHS_SDR104] = {"ti,otap-del-sel-sdr104", MMC_CAP(UHS_SDR104)},
+ [UHS_DDR50] = {"ti,otap-del-sel-ddr50", MMC_CAP(UHS_DDR50)},
+ [MMC_DDR_52] = {"ti,otap-del-sel-ddr52", MMC_CAP(MMC_DDR_52)},
+ [MMC_HS_200] = {"ti,otap-del-sel-hs200", MMC_CAP(MMC_HS_200)},
+ [MMC_HS_400] = {"ti,otap-del-sel-hs400", MMC_CAP(MMC_HS_400)},
+};
+
struct am654_driver_data {
const struct sdhci_ops *ops;
u32 flags;
@@ -112,6 +131,7 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host)
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
unsigned int speed = host->mmc->clock;
int sel50, sel100, freqsel;
+ u32 otap_del_sel;
u32 mask, val;
int ret;
@@ -132,9 +152,10 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host)
/* switch phy back on */
if (speed > AM654_SDHCI_MIN_FREQ) {
+ otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode];
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
val = (1 << OTAPDLYENA_SHIFT) |
- (plat->otap_del_sel << OTAPDLYSEL_SHIFT);
+ (otap_del_sel << OTAPDLYSEL_SHIFT);
/* Write to STRBSEL for HS400 speed mode */
if (host->mmc->selected_mode == MMC_HS_400) {
@@ -197,44 +218,6 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host)
return 0;
}
-const struct sdhci_ops am654_sdhci_ops = {
- .set_ios_post = &am654_sdhci_set_ios_post,
- .set_control_reg = &am654_sdhci_set_control_reg,
-};
-
-const struct am654_driver_data am654_drv_data = {
- .ops = &am654_sdhci_ops,
- .flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | STRBSEL_4_BIT,
-};
-
-const struct am654_driver_data j721e_8bit_drv_data = {
- .ops = &am654_sdhci_ops,
- .flags = DLL_PRESENT,
-};
-
-static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host)
-{
- struct udevice *dev = host->mmc->dev;
- struct am654_sdhci_plat *plat = dev_get_platdata(dev);
- u32 mask, val;
-
- mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
- val = (1 << OTAPDLYENA_SHIFT) |
- (plat->otap_del_sel << OTAPDLYSEL_SHIFT);
- regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
-
- return 0;
-}
-
-const struct sdhci_ops j721e_4bit_sdhci_ops = {
- .set_ios_post = &j721e_4bit_sdhci_set_ios_post,
-};
-
-const struct am654_driver_data j721e_4bit_drv_data = {
- .ops = &j721e_4bit_sdhci_ops,
- .flags = IOMUX_PRESENT,
-};
-
int am654_sdhci_init(struct am654_sdhci_plat *plat)
{
u32 ctl_cfg_2 = 0;
@@ -281,6 +264,104 @@ int am654_sdhci_init(struct am654_sdhci_plat *plat)
return 0;
}
+#define MAX_SDCD_DEBOUNCE_TIME 2000
+static int am654_sdhci_deferred_probe(struct sdhci_host *host)
+{
+ struct udevice *dev = host->mmc->dev;
+ struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+ unsigned long start;
+ int val;
+
+ /*
+ * The controller takes about 1 second to debounce the card detect line
+ * and doesn't let us power on until that time is up. Instead of waiting
+ * for 1 second at every stage, poll on the CARD_PRESENT bit upto a
+ * maximum of 2 seconds to be safe..
+ */
+ start = get_timer(0);
+ do {
+ if (get_timer(start) > MAX_SDCD_DEBOUNCE_TIME)
+ return -ENOMEDIUM;
+
+ val = mmc_getcd(host->mmc);
+ } while (!val);
+
+ am654_sdhci_init(plat);
+
+ return sdhci_probe(dev);
+}
+
+const struct sdhci_ops am654_sdhci_ops = {
+ .deferred_probe = am654_sdhci_deferred_probe,
+ .set_ios_post = &am654_sdhci_set_ios_post,
+ .set_control_reg = &am654_sdhci_set_control_reg,
+};
+
+const struct am654_driver_data am654_drv_data = {
+ .ops = &am654_sdhci_ops,
+ .flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | STRBSEL_4_BIT,
+};
+
+const struct am654_driver_data j721e_8bit_drv_data = {
+ .ops = &am654_sdhci_ops,
+ .flags = DLL_PRESENT,
+};
+
+static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host)
+{
+ struct udevice *dev = host->mmc->dev;
+ struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+ u32 otap_del_sel, mask, val;
+
+ otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode];
+ mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+ val = (1 << OTAPDLYENA_SHIFT) | (otap_del_sel << OTAPDLYSEL_SHIFT);
+ regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
+
+ return 0;
+}
+
+const struct sdhci_ops j721e_4bit_sdhci_ops = {
+ .deferred_probe = am654_sdhci_deferred_probe,
+ .set_ios_post = &j721e_4bit_sdhci_set_ios_post,
+};
+
+const struct am654_driver_data j721e_4bit_drv_data = {
+ .ops = &j721e_4bit_sdhci_ops,
+ .flags = IOMUX_PRESENT,
+};
+
+static int sdhci_am654_get_otap_delay(struct udevice *dev,
+ struct mmc_config *cfg)
+{
+ struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+ int ret;
+ int i;
+
+ /* ti,otap-del-sel-legacy is mandatory */
+ ret = dev_read_u32(dev, "ti,otap-del-sel-legacy",
+ &plat->otap_del_sel[0]);
+ if (ret)
+ return ret;
+ /*
+ * Remove the corresponding capability if an otap-del-sel
+ * value is not found
+ */
+ for (i = MMC_HS; i <= MMC_HS_400; i++) {
+ ret = dev_read_u32(dev, td[i].binding, &plat->otap_del_sel[i]);
+ if (ret) {
+ dev_dbg(dev, "Couldn't find %s\n", td[i].binding);
+ /*
+ * Remove the corresponding capability
+ * if an otap-del-sel value is not found
+ */
+ cfg->host_caps &= ~td[i].capability;
+ }
+ }
+
+ return 0;
+}
+
static int am654_sdhci_probe(struct udevice *dev)
{
struct am654_driver_data *drv_data =
@@ -313,15 +394,17 @@ static int am654_sdhci_probe(struct udevice *dev)
if (ret)
return ret;
+ ret = sdhci_am654_get_otap_delay(dev, cfg);
+ if (ret)
+ return ret;
+
host->ops = drv_data->ops;
host->mmc->priv = host;
upriv->mmc = host->mmc;
regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
- am654_sdhci_init(plat);
-
- return sdhci_probe(dev);
+ return 0;
}
static int am654_sdhci_ofdata_to_platdata(struct udevice *dev)
@@ -336,10 +419,6 @@ static int am654_sdhci_ofdata_to_platdata(struct udevice *dev)
host->ioaddr = (void *)dev_read_addr(dev);
plat->non_removable = dev_read_bool(dev, "non-removable");
- ret = dev_read_u32(dev, "ti,otap-del-sel", &plat->otap_del_sel);
- if (ret)
- return ret;
-
if (plat->flags & DLL_PRESENT) {
ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp);
if (ret)
diff --git a/drivers/mmc/ca_dw_mmc.c b/drivers/mmc/ca_dw_mmc.c
new file mode 100644
index 0000000000..acbc850fcb
--- /dev/null
+++ b/drivers/mmc/ca_dw_mmc.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Cortina Access
+ * Arthur Li <arthur.li@cortina-access.com>
+ */
+
+#include <common.h>
+#include <dwmmc.h>
+#include <fdtdec.h>
+#include <linux/libfdt.h>
+#include <malloc.h>
+#include <errno.h>
+#include <dm.h>
+#include <mapmem.h>
+
+#define SD_CLK_SEL_MASK (0x3)
+#define SD_DLL_DEFAULT (0x143000)
+#define SD_SCLK_MAX (200000000)
+
+#define SD_CLK_SEL_200MHZ (0x2)
+#define SD_CLK_SEL_100MHZ (0x1)
+
+#define IO_DRV_SD_DS_OFFSET (16)
+#define IO_DRV_SD_DS_MASK (0xff << IO_DRV_SD_DS_OFFSET)
+
+#define MIN_FREQ (400000)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ca_mmc_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
+struct ca_dwmmc_priv_data {
+ struct dwmci_host host;
+ void __iomem *sd_dll_reg;
+ void __iomem *io_drv_reg;
+ u8 ds;
+};
+
+static void ca_dwmci_clksel(struct dwmci_host *host)
+{
+ struct ca_dwmmc_priv_data *priv = host->priv;
+ u32 val = readl(priv->sd_dll_reg);
+
+ if (host->bus_hz >= 200000000) {
+ val &= ~SD_CLK_SEL_MASK;
+ val |= SD_CLK_SEL_200MHZ;
+ } else if (host->bus_hz >= 100000000) {
+ val &= ~SD_CLK_SEL_MASK;
+ val |= SD_CLK_SEL_100MHZ;
+ } else {
+ val &= ~SD_CLK_SEL_MASK;
+ }
+
+ writel(val, priv->sd_dll_reg);
+}
+
+static void ca_dwmci_board_init(struct dwmci_host *host)
+{
+ struct ca_dwmmc_priv_data *priv = host->priv;
+ u32 val = readl(priv->io_drv_reg);
+
+ writel(SD_DLL_DEFAULT, priv->sd_dll_reg);
+
+ val &= ~IO_DRV_SD_DS_MASK;
+ if (priv && priv->ds)
+ val |= priv->ds << IO_DRV_SD_DS_OFFSET;
+ writel(val, priv->io_drv_reg);
+}
+
+unsigned int ca_dwmci_get_mmc_clock(struct dwmci_host *host, uint freq)
+{
+ struct ca_dwmmc_priv_data *priv = host->priv;
+ u8 sd_clk_sel = readl(priv->sd_dll_reg) & SD_CLK_SEL_MASK;
+ u8 clk_div;
+
+ switch (sd_clk_sel) {
+ case 2:
+ clk_div = 1;
+ break;
+ case 1:
+ clk_div = 2;
+ break;
+ default:
+ clk_div = 4;
+ }
+
+ return SD_SCLK_MAX / clk_div / (host->div + 1);
+}
+
+static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
+{
+ struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
+ struct dwmci_host *host = &priv->host;
+ u32 tmp;
+
+ host->name = dev->name;
+ host->dev_index = 0;
+
+ host->buswidth = dev_read_u32_default(dev, "bus-width", 1);
+ if (host->buswidth != 1 && host->buswidth != 4)
+ return -EINVAL;
+
+ host->bus_hz = dev_read_u32_default(dev, "max-frequency", 50000000);
+ priv->ds = dev_read_u32_default(dev, "io_ds", 0x33);
+ host->fifo_mode = dev_read_bool(dev, "fifo-mode");
+
+ dev_read_u32(dev, "sd_dll_ctrl", &tmp);
+ priv->sd_dll_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
+ if (!priv->sd_dll_reg)
+ return -EINVAL;
+
+ dev_read_u32(dev, "io_drv_ctrl", &tmp);
+ priv->io_drv_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
+ if (!priv->io_drv_reg)
+ return -EINVAL;
+
+ host->ioaddr = dev_read_addr_ptr(dev);
+ if (host->ioaddr == (void *)FDT_ADDR_T_NONE) {
+ printf("DWMMC: base address is invalid\n");
+ return -EINVAL;
+ }
+
+ host->priv = priv;
+
+ return 0;
+}
+
+struct dm_mmc_ops ca_dwmci_dm_ops;
+
+static int ca_dwmmc_probe(struct udevice *dev)
+{
+ struct ca_mmc_plat *plat = dev_get_platdata(dev);
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
+ struct dwmci_host *host = &priv->host;
+
+ memcpy(&ca_dwmci_dm_ops, &dm_dwmci_ops, sizeof(struct dm_mmc_ops));
+
+ dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, MIN_FREQ);
+ if (host->buswidth == 1) {
+ (&plat->cfg)->host_caps &= ~MMC_MODE_8BIT;
+ (&plat->cfg)->host_caps &= ~MMC_MODE_4BIT;
+ }
+
+ host->mmc = &plat->mmc;
+ host->mmc->priv = &priv->host;
+ upriv->mmc = host->mmc;
+ host->mmc->dev = dev;
+ host->clksel = ca_dwmci_clksel;
+ host->board_init = ca_dwmci_board_init;
+ host->get_mmc_clk = ca_dwmci_get_mmc_clock;
+
+ return dwmci_probe(dev);
+}
+
+static int ca_dwmmc_bind(struct udevice *dev)
+{
+ struct ca_mmc_plat *plat = dev_get_platdata(dev);
+
+ return dwmci_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static const struct udevice_id ca_dwmmc_ids[] = {
+ { .compatible = "snps,dw-cortina" },
+ { }
+};
+
+U_BOOT_DRIVER(ca_dwmmc_drv) = {
+ .name = "cortina_dwmmc",
+ .id = UCLASS_MMC,
+ .of_match = ca_dwmmc_ids,
+ .ofdata_to_platdata = ca_dwmmc_ofdata_to_platdata,
+ .bind = ca_dwmmc_bind,
+ .ops = &ca_dwmci_dm_ops,
+ .probe = ca_dwmmc_probe,
+ .priv_auto_alloc_size = sizeof(struct ca_dwmmc_priv_data),
+ .platdata_auto_alloc_size = sizeof(struct ca_mmc_plat),
+};
diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c
index 4900498e9b..6bca2a9c82 100644
--- a/drivers/mmc/fsl_esdhc_imx.c
+++ b/drivers/mmc/fsl_esdhc_imx.c
@@ -743,7 +743,6 @@ static int esdhc_set_timing(struct mmc *mmc)
switch (mmc->selected_mode) {
case MMC_LEGACY:
- case SD_LEGACY:
esdhc_reset_tuning(mmc);
writel(mixctrl, &regs->mixctrl);
break;
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 0b90a97650..c75892a72c 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -138,6 +138,21 @@ int mmc_host_power_cycle(struct mmc *mmc)
return dm_mmc_host_power_cycle(mmc->dev);
}
+int dm_mmc_deferred_probe(struct udevice *dev)
+{
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+ if (ops->deferred_probe)
+ return ops->deferred_probe(dev);
+
+ return 0;
+}
+
+int mmc_deferred_probe(struct mmc *mmc)
+{
+ return dm_mmc_deferred_probe(mmc->dev);
+}
+
int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
{
int val;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index b50fcbf6cf..3e36566693 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -132,7 +132,6 @@ const char *mmc_mode_name(enum bus_mode mode)
{
static const char *const names[] = {
[MMC_LEGACY] = "MMC legacy",
- [SD_LEGACY] = "SD Legacy",
[MMC_HS] = "MMC High Speed (26MHz)",
[SD_HS] = "SD High Speed (50MHz)",
[UHS_SDR12] = "UHS SDR12 (25MHz)",
@@ -158,7 +157,6 @@ static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
{
static const int freqs[] = {
[MMC_LEGACY] = 25000000,
- [SD_LEGACY] = 25000000,
[MMC_HS] = 26000000,
[SD_HS] = 50000000,
[MMC_HS_52] = 52000000,
@@ -1239,7 +1237,7 @@ static int sd_get_capabilities(struct mmc *mmc)
u32 sd3_bus_mode;
#endif
- mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(SD_LEGACY);
+ mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
if (mmc_host_is_spi(mmc))
return 0;
@@ -1352,7 +1350,7 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
return 0;
switch (mode) {
- case SD_LEGACY:
+ case MMC_LEGACY:
speed = UHS_SDR12_BUS_SPEED;
break;
case SD_HS:
@@ -1695,7 +1693,7 @@ static const struct mode_width_tuning sd_modes_by_pref[] = {
},
#endif
{
- .mode = SD_LEGACY,
+ .mode = MMC_LEGACY,
.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
}
};
@@ -1725,7 +1723,7 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
if (mmc_host_is_spi(mmc)) {
mmc_set_bus_width(mmc, 1);
- mmc_select_mode(mmc, SD_LEGACY);
+ mmc_select_mode(mmc, MMC_LEGACY);
mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
return 0;
}
@@ -1784,7 +1782,7 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
error:
/* revert to a safer bus speed */
- mmc_select_mode(mmc, SD_LEGACY);
+ mmc_select_mode(mmc, MMC_LEGACY);
mmc_set_clock(mmc, mmc->tran_speed,
MMC_CLK_ENABLE);
}
@@ -2561,7 +2559,7 @@ static int mmc_startup(struct mmc *mmc)
#if CONFIG_IS_ENABLED(MMC_TINY)
mmc_set_clock(mmc, mmc->legacy_speed, false);
- mmc_select_mode(mmc, IS_SD(mmc) ? SD_LEGACY : MMC_LEGACY);
+ mmc_select_mode(mmc, MMC_LEGACY);
mmc_set_bus_width(mmc, 1);
#else
if (IS_SD(mmc)) {
@@ -2843,9 +2841,11 @@ int mmc_start_init(struct mmc *mmc)
* all hosts are capable of 1 bit bus-width and able to use the legacy
* timings.
*/
- mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(SD_LEGACY) |
+ mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) |
MMC_CAP(MMC_LEGACY) | MMC_MODE_1BIT;
-
+#if CONFIG_IS_ENABLED(DM_MMC)
+ mmc_deferred_probe(mmc);
+#endif
#if !defined(CONFIG_MMC_BROKEN_CD)
no_card = mmc_getcd(mmc) == 0;
#else
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 5334723a9f..4d0dc33936 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -392,7 +392,6 @@ static void omap_hsmmc_set_timing(struct mmc *mmc)
break;
case MMC_LEGACY:
case MMC_HS:
- case SD_LEGACY:
case UHS_SDR12:
val |= AC12_UHSMC_SDR12;
break;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 9b7c5f8f68..520c9f9feb 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -658,6 +658,20 @@ int sdhci_probe(struct udevice *dev)
return sdhci_init(mmc);
}
+static int sdhci_deferred_probe(struct udevice *dev)
+{
+ int err;
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+ struct sdhci_host *host = mmc->priv;
+
+ if (host->ops && host->ops->deferred_probe) {
+ err = host->ops->deferred_probe(host);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
static int sdhci_get_cd(struct udevice *dev)
{
struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -692,6 +706,7 @@ const struct dm_mmc_ops sdhci_ops = {
.send_cmd = sdhci_send_command,
.set_ios = sdhci_set_ios,
.get_cd = sdhci_get_cd,
+ .deferred_probe = sdhci_deferred_probe,
#ifdef MMC_SUPPORTS_TUNING
.execute_tuning = sdhci_execute_tuning,
#endif
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 24fabeee95..da3ff53da1 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -37,7 +37,6 @@ struct arasan_sdhci_priv {
static const u8 mode2timing[] = {
[MMC_LEGACY] = UHS_SDR12_BUS_SPEED,
- [SD_LEGACY] = UHS_SDR12_BUS_SPEED,
[MMC_HS] = HIGH_SPEED_BUS_SPEED,
[SD_HS] = HIGH_SPEED_BUS_SPEED,
[MMC_HS_52] = HIGH_SPEED_BUS_SPEED,
diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h
index 7d7f86a059..23ee2254ed 100644
--- a/include/configs/am65x_evm.h
+++ b/include/configs/am65x_evm.h
@@ -127,8 +127,6 @@
#define CONFIG_SYS_MMC_ENV_PART 1
#endif
-#define CONFIG_SUPPORT_EMMC_BOOT
-
/* Now for the remaining common defines */
#include <configs/ti_armv7_common.h>
diff --git a/include/mmc.h b/include/mmc.h
index 71e2e1735a..e83c22423b 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -15,6 +15,8 @@
#include <linux/dma-direction.h>
#include <part.h>
+struct bd_info;
+
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
#define MMC_SUPPORTS_TUNING
#endif
@@ -408,6 +410,14 @@ struct mmc;
#if CONFIG_IS_ENABLED(DM_MMC)
struct dm_mmc_ops {
/**
+ * deferred_probe() - Some configurations that need to be deferred
+ * to just before enumerating the device
+ *
+ * @dev: Device to init
+ * @return 0 if Ok, -ve if error
+ */
+ int (*deferred_probe)(struct udevice *dev);
+ /**
* send_cmd() - Send a command to the MMC device
*
* @dev: Device to receive the command
@@ -490,6 +500,7 @@ int dm_mmc_get_wp(struct udevice *dev);
int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us);
int dm_mmc_host_power_cycle(struct udevice *dev);
+int dm_mmc_deferred_probe(struct udevice *dev);
/* Transition functions for compatibility */
int mmc_set_ios(struct mmc *mmc);
@@ -499,6 +510,7 @@ int mmc_execute_tuning(struct mmc *mmc, uint opcode);
int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us);
int mmc_set_enhanced_strobe(struct mmc *mmc);
int mmc_host_power_cycle(struct mmc *mmc);
+int mmc_deferred_probe(struct mmc *mmc);
#else
struct mmc_ops {
@@ -533,7 +545,6 @@ struct sd_ssr {
enum bus_mode {
MMC_LEGACY,
- SD_LEGACY,
MMC_HS,
SD_HS,
MMC_HS_52,
@@ -603,6 +614,7 @@ struct mmc {
bool clk_disable; /* true if the clock can be turned off */
uint bus_width;
uint clock;
+ uint saved_clock;
enum mmc_voltage signal_voltage;
uint card_caps;
uint host_caps;
@@ -712,7 +724,7 @@ void mmc_destroy(struct mmc *mmc);
* @return 0 if OK, -ve on error
*/
int mmc_unbind(struct udevice *dev);
-int mmc_initialize(bd_t *bis);
+int mmc_initialize(struct bd_info *bis);
int mmc_init_device(int num);
int mmc_init(struct mmc *mmc);
int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
@@ -857,8 +869,8 @@ void mmc_set_preinit(struct mmc *mmc, int preinit);
#endif
void board_mmc_power_init(void);
-int board_mmc_init(bd_t *bis);
-int cpu_mmc_init(bd_t *bis);
+int board_mmc_init(struct bd_info *bis);
+int cpu_mmc_init(struct bd_info *bis);
int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
# ifdef CONFIG_SYS_MMC_ENV_PART
extern uint mmc_get_env_part(struct mmc *mmc);
diff --git a/include/sdhci.h b/include/sdhci.h
index 7f8feefa45..aa4378fd57 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -268,6 +268,7 @@ struct sdhci_ops {
void (*set_clock)(struct sdhci_host *host, u32 div);
int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
void (*set_delay)(struct sdhci_host *host);
+ int (*deferred_probe)(struct sdhci_host *host);
};
#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)