diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/Kconfig | 4 | ||||
-rw-r--r-- | drivers/mmc/Makefile | 6 | ||||
-rw-r--r-- | drivers/mmc/am654_sdhci.c | 25 | ||||
-rw-r--r-- | drivers/mmc/mmc-uclass.c | 29 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 24 | ||||
-rw-r--r-- | drivers/mmc/mmc_boot.c | 173 | ||||
-rw-r--r-- | drivers/mmc/mmc_write.c | 11 | ||||
-rw-r--r-- | drivers/mmc/omap_hsmmc.c | 13 | ||||
-rw-r--r-- | drivers/mmc/rockchip_dw_mmc.c | 1 | ||||
-rw-r--r-- | drivers/mmc/rockchip_sdhci.c | 54 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 8 | ||||
-rw-r--r-- | drivers/mmc/sunxi_mmc.c | 20 |
12 files changed, 289 insertions, 79 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 6740591a653..38867f30a7e 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -528,6 +528,7 @@ config SPL_MMC_SDHCI_ADMA config MMC_SDHCI_ADMA_FORCE_32BIT bool "Force 32 bit mode for ADMA on 64 bit platforms" + depends on MMC_SDHCI_ADMA || SPL_MMC_SDHCI_ADMA help This forces SDHCI ADMA to be built for 32 bit descriptors, even on a 64 bit platform where they would otherwise be assumed to @@ -537,6 +538,7 @@ config MMC_SDHCI_ADMA_FORCE_32BIT config MMC_SDHCI_ADMA_64BIT bool "Use SHDCI ADMA with 64 bit descriptors" + depends on MMC_SDHCI_ADMA || SPL_MMC_SDHCI_ADMA depends on !MMC_SDHCI_ADMA_FORCE_32BIT default y if DMA_ADDR_T_64BIT help @@ -869,7 +871,7 @@ config FTSDC010_SDIO config MMC_MTK bool "MediaTek SD/MMC Card Interface support" - depends on ARCH_MEDIATEK || ARCH_MTMIPS + depends on ARCH_MEDIATEK || ARCH_MTMIPS || ARCH_AIROHA depends on OF_CONTROL help This selects the MediaTek(R) Secure digital and Multimedia card Interface. diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 94ed28ead71..360706f53d2 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -4,17 +4,17 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-y += mmc.o -obj-$(CONFIG_$(XPL_)DM_MMC) += mmc-uclass.o +obj-$(CONFIG_$(PHASE_)DM_MMC) += mmc-uclass.o ifdef CONFIG_$(PHASE_)DM_MMC obj-$(CONFIG_$(PHASE_)BOOTSTD) += mmc_bootdev.o endif obj-$(CONFIG_$(PHASE_)MMC_WRITE) += mmc_write.o -obj-$(CONFIG_$(XPL_)MMC_PWRSEQ) += mmc-pwrseq.o +obj-$(CONFIG_$(PHASE_)MMC_PWRSEQ) += mmc-pwrseq.o obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o -ifndef CONFIG_$(XPL_)BLK +ifndef CONFIG_$(PHASE_)BLK obj-y += mmc_legacy.o endif diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c index b4c60a48d2e..0df3568f073 100644 --- a/drivers/mmc/am654_sdhci.c +++ b/drivers/mmc/am654_sdhci.c @@ -125,12 +125,15 @@ static const struct timing_data td[] = { [MMC_LEGACY] = {"ti,otap-del-sel-legacy", "ti,itap-del-sel-legacy", 0}, - [MMC_HS] = {"ti,otap-del-sel-mmc-hs", - "ti,itap-del-sel-mms-hs", + [MMC_HS] = {"ti,otap-del-sel-mmc-hs26", + "ti,itap-del-sel-mmc-hs26", MMC_CAP(MMC_HS)}, [SD_HS] = {"ti,otap-del-sel-sd-hs", "ti,itap-del-sel-sd-hs", MMC_CAP(SD_HS)}, + [MMC_HS_52] = {"ti,otap-del-sel-mmc-hs", + "ti,itap-del-sel-mmc-hs", + MMC_CAP(MMC_HS_52)}, [UHS_SDR12] = {"ti,otap-del-sel-sdr12", "ti,itap-del-sel-sdr12", MMC_CAP(UHS_SDR12)}, @@ -409,8 +412,7 @@ static void am654_sdhci_write_b(struct sdhci_host *host, u8 val, int reg) */ case SD_HS: case MMC_HS: - case UHS_SDR12: - case UHS_SDR25: + case MMC_HS_52: val &= ~SDHCI_CTRL_HISPD; default: break; @@ -521,13 +523,24 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) return 0; } #endif + +void am654_sdhci_set_control_reg(struct sdhci_host *host) +{ + struct mmc *mmc = host->mmc; + + sdhci_set_voltage(host); + + if (mmc->selected_mode > MMC_HS_52) + sdhci_set_uhs_timing(host); +} + const struct sdhci_ops am654_sdhci_ops = { #if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .platform_execute_tuning = am654_sdhci_execute_tuning, #endif .deferred_probe = am654_sdhci_deferred_probe, .set_ios_post = &am654_sdhci_set_ios_post, - .set_control_reg = sdhci_set_control_reg, + .set_control_reg = am654_sdhci_set_control_reg, .write_b = am654_sdhci_write_b, }; @@ -587,7 +600,7 @@ const struct sdhci_ops j721e_4bit_sdhci_ops = { #endif .deferred_probe = am654_sdhci_deferred_probe, .set_ios_post = &j721e_4bit_sdhci_set_ios_post, - .set_control_reg = sdhci_set_control_reg, + .set_control_reg = am654_sdhci_set_control_reg, .write_b = am654_sdhci_write_b, }; diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index c8db4f811c2..2f4dc5bd887 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -83,6 +83,19 @@ int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us) return dm_mmc_wait_dat0(mmc->dev, state, timeout_us); } +void dm_mmc_send_init_stream(struct udevice *dev) +{ + struct dm_mmc_ops *ops = mmc_get_ops(dev); + + if (ops->send_init_stream) + ops->send_init_stream(dev); +} + +void mmc_send_init_stream(struct mmc *mmc) +{ + dm_mmc_send_init_stream(mmc->dev); +} + static int dm_mmc_get_wp(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -498,22 +511,12 @@ static int mmc_blk_probe(struct udevice *dev) return ret; } - ret = device_probe(dev); - if (ret) { - debug("Probing %s failed (err=%d)\n", dev->name, ret); - - mmc_deinit(mmc); - - return ret; - } - return 0; } -static int mmc_blk_remove(struct udevice *dev) +static int mmc_remove(struct udevice *dev) { - struct udevice *mmc_dev = dev_get_parent(dev); - struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct mmc *mmc = upriv->mmc; return mmc_deinit(mmc); @@ -533,7 +536,6 @@ U_BOOT_DRIVER(mmc_blk) = { .id = UCLASS_BLK, .ops = &mmc_blk_ops, .probe = mmc_blk_probe, - .remove = mmc_blk_remove, .flags = DM_FLAG_OS_PREPARE, }; #endif /* CONFIG_BLK */ @@ -543,4 +545,5 @@ UCLASS_DRIVER(mmc) = { .name = "mmc", .flags = DM_UC_FLAG_SEQ_ALIAS, .per_device_auto = sizeof(struct mmc_uclass_priv), + .pre_remove = mmc_remove, }; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 31a72366206..cdcf2e0c8fe 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1663,6 +1663,10 @@ static int mmc_execute_tuning(struct mmc *mmc, uint opcode) } #endif +static void mmc_send_init_stream(struct mmc *mmc) +{ +} + static int mmc_set_ios(struct mmc *mmc) { int ret = 0; @@ -2550,7 +2554,7 @@ static int mmc_startup(struct mmc *mmc) /* * For MMC cards, set the Relative Address. - * For SD cards, get the Relatvie Address. + * For SD cards, get the Relative Address. * This also puts the cards into Standby State */ if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */ @@ -2929,6 +2933,8 @@ int mmc_get_op_cond(struct mmc *mmc, bool quiet) retry: mmc_set_initial_state(mmc); + mmc_send_init_stream(mmc); + /* Reset the Card */ err = mmc_go_idle(mmc); @@ -3040,9 +3046,9 @@ static int mmc_complete_init(struct mmc *mmc) return err; } -static void __maybe_unused mmc_cyclic_cd_poll(struct cyclic_info *c) +static void mmc_cyclic_cd_poll(struct cyclic_info *c) { - struct mmc *m = CONFIG_IS_ENABLED(CYCLIC, (container_of(c, struct mmc, cyclic)), (NULL)); + struct mmc *m = container_of(c, struct mmc, cyclic); if (!m->has_init) return; @@ -3073,15 +3079,15 @@ int mmc_init(struct mmc *mmc) if (!err) err = mmc_complete_init(mmc); - if (err) + if (err) { pr_info("%s: %d, time %lu\n", __func__, err, get_timer(start)); + return err; + } if (CONFIG_IS_ENABLED(CYCLIC, (!mmc->cyclic.func), (NULL))) { /* Register cyclic function for card detect polling */ - CONFIG_IS_ENABLED(CYCLIC, (cyclic_register(&mmc->cyclic, - mmc_cyclic_cd_poll, - 100 * 1000, - mmc->cfg->name))); + cyclic_register(&mmc->cyclic, mmc_cyclic_cd_poll, 100 * 1000, + mmc->cfg->name); } return err; @@ -3092,7 +3098,7 @@ int mmc_deinit(struct mmc *mmc) u32 caps_filtered; if (CONFIG_IS_ENABLED(CYCLIC, (mmc->cyclic.func), (NULL))) - CONFIG_IS_ENABLED(CYCLIC, (cyclic_unregister(&mmc->cyclic))); + cyclic_unregister(&mmc->cyclic); if (!CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) && !CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) && diff --git a/drivers/mmc/mmc_boot.c b/drivers/mmc/mmc_boot.c index 367c957b518..986e6c500b1 100644 --- a/drivers/mmc/mmc_boot.c +++ b/drivers/mmc/mmc_boot.c @@ -8,20 +8,107 @@ #include <mmc.h> #include "mmc_private.h" -/* - * This function changes the size of boot partition and the size of rpmb - * partition present on EMMC devices. - * - * Input Parameters: - * struct *mmc: pointer for the mmc device strcuture - * bootsize: size of boot partition - * rpmbsize: size of rpmb partition - * - * Returns 0 on success. - */ +static int mmc_resize_boot_micron(struct mmc *mmc, unsigned long bootsize, + unsigned long rpmbsize) +{ + int err; -int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, - unsigned long rpmbsize) + /* Micron eMMC doesn't support resizing RPMB partition */ + (void)rpmbsize; + + /* BOOT partition size is multiple of 128KB */ + bootsize = (bootsize * 1024) / 128; + + if (bootsize > 0xff) + bootsize = 0xff; + + /* Set EXT_CSD[175] ERASE_GROUP_DEF to 0x01 */ + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_ERASE_GROUP_DEF, 0x01); + if (err) + goto error; + + /* Set EXT_CSD[127:125] for BOOT partition size, [125] is low byte */ + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BOOT_SIZE_MULT_MICRON, bootsize); + if (err) + goto error; + + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BOOT_SIZE_MULT_MICRON + 1, 0x00); + if (err) + goto error; + + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BOOT_SIZE_MULT_MICRON + 2, 0x00); + if (err) + goto error; + + /* Set EXT_CSD[155] PARTITION_SETTING_COMPLETE to 0x01 */ + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_PARTITION_SETTING, 0x01); + if (err) + goto error; + + return 0; + +error: + debug("%s: Error = %d\n", __func__, err); + return err; +} + +static int mmc_resize_boot_sandisk(struct mmc *mmc, unsigned long bootsize, + unsigned long rpmbsize) +{ + int err; + struct mmc_cmd cmd; + + /* BOOT/RPMB partition size is multiple of 128KB */ + bootsize = (bootsize * 1024) / 128; + rpmbsize = (rpmbsize * 1024) / 128; + + if (bootsize > 0xff) + bootsize = 0xff; + + if (rpmbsize > 0xff) + rpmbsize = 0xff; + + /* Send BOOT/RPMB resize op code */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = MMC_CMD62_ARG_SANDISK; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) + goto error; + + /* Arg: BOOT partition size */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = bootsize; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) + goto error; + + /* Arg: RPMB partition size */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = rpmbsize; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) + goto error; + + return 0; + +error: + debug("%s: Error = %d\n", __func__, err); + return err; +} + +static int mmc_resize_boot_samsung(struct mmc *mmc, unsigned long bootsize, + unsigned long rpmbsize) { int err; struct mmc_cmd cmd; @@ -32,10 +119,8 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, cmd.cmdarg = MMC_CMD62_ARG1; err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - debug("mmc_boot_partition_size_change: Error1 = %d\n", err); - return err; - } + if (err) + goto error; /* Boot partition changing mode */ cmd.cmdidx = MMC_CMD_RES_MAN; @@ -43,10 +128,9 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, cmd.cmdarg = MMC_CMD62_ARG2; err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - debug("mmc_boot_partition_size_change: Error2 = %d\n", err); - return err; - } + if (err) + goto error; + /* boot partition size is multiple of 128KB */ bootsize = (bootsize * 1024) / 128; @@ -56,10 +140,9 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, cmd.cmdarg = bootsize; err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - debug("mmc_boot_partition_size_change: Error3 = %d\n", err); - return err; - } + if (err) + goto error; + /* RPMB partition size is multiple of 128KB */ rpmbsize = (rpmbsize * 1024) / 128; /* Arg: RPMB partition size */ @@ -68,11 +151,43 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, cmd.cmdarg = rpmbsize; err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - debug("mmc_boot_partition_size_change: Error4 = %d\n", err); - return err; - } + if (err) + goto error; + return 0; + +error: + debug("%s: Error = %d\n", __func__, err); + return err; +} + +/* + * This function changes the size of BOOT partition and the size of RPMB + * partition present on eMMC devices. + * + * Input Parameters: + * struct *mmc: pointer for the mmc device strcuture + * bootsize: size of BOOT partition + * rpmbsize: size of RPMB partition + * + * Returns 0 on success. + */ + +int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, + unsigned long rpmbsize) +{ + switch (mmc->cid[0] >> 24) { + case CID_MANFID_MICRON: + return mmc_resize_boot_micron(mmc, bootsize, rpmbsize); + case CID_MANFID_SAMSUNG: + return mmc_resize_boot_samsung(mmc, bootsize, rpmbsize); + case CID_MANFID_SANDISK: + return mmc_resize_boot_sandisk(mmc, bootsize, rpmbsize); + default: + printf("Unsupported manufacturer id 0x%02x\n", + mmc->cid[0] >> 24); + return -EPERM; + } } /* diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index c023d15e52a..90fcf2679bb 100644 --- a/drivers/mmc/mmc_write.c +++ b/drivers/mmc/mmc_write.c @@ -80,6 +80,8 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt) struct mmc *mmc = find_mmc_device(dev_num); lbaint_t blk = 0, blk_r = 0; int timeout_ms = 1000; + u32 grpcnt; + if (!mmc) return -1; @@ -123,6 +125,15 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt) } else { blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ? mmc->erase_grp_size : (blkcnt - blk); + + grpcnt = (blkcnt - blk) / mmc->erase_grp_size; + /* Max 2GB per spec */ + if ((blkcnt - blk) > 0x400000) + blk_r = 0x400000; + else if (grpcnt) + blk_r = grpcnt * mmc->erase_grp_size; + else + blk_r = blkcnt - blk; } err = mmc_erase_t(mmc, start + blk, blk_r, erase_args); if (err) diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index e66ab25d02a..92bc72b267c 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -780,6 +780,14 @@ tuning_error: return ret; } #endif + +static void omap_hsmmc_send_init_stream(struct udevice *dev) +{ + struct omap_hsmmc_data *priv = dev_get_priv(dev); + struct hsmmc *mmc_base = priv->base_addr; + + mmc_init_stream(mmc_base); +} #endif static void mmc_enable_irq(struct mmc *mmc, struct mmc_cmd *cmd) @@ -1515,9 +1523,10 @@ static const struct dm_mmc_ops omap_hsmmc_ops = { .get_wp = omap_hsmmc_getwp, #endif #if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) - .execute_tuning = omap_hsmmc_execute_tuning, + .execute_tuning = omap_hsmmc_execute_tuning, #endif - .wait_dat0 = omap_hsmmc_wait_dat0, + .send_init_stream = omap_hsmmc_send_init_stream, + .wait_dat0 = omap_hsmmc_wait_dat0, }; #else static const struct mmc_ops omap_hsmmc_ops = { diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index 422b8f7e4c8..7a72abaa38a 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -171,6 +171,7 @@ static int rockchip_dwmmc_bind(struct udevice *dev) static const struct udevice_id rockchip_dwmmc_ids[] = { { .compatible = "rockchip,rk2928-dw-mshc" }, { .compatible = "rockchip,rk3288-dw-mshc" }, + { .compatible = "rockchip,rk3576-dw-mshc" }, { } }; diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index da630b9d97a..761e3619329 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -50,6 +50,10 @@ #define DWCMSHC_EMMC_EMMC_CTRL 0x52c #define DWCMSHC_CARD_IS_EMMC BIT(0) #define DWCMSHC_ENHANCED_STROBE BIT(8) +#define DWCMSHC_EMMC_AT_CTRL 0x540 +#define EMMC_AT_CTRL_TUNE_CLK_STOP_EN BIT(16) +#define EMMC_AT_CTRL_PRE_CHANGE_DLY 17 +#define EMMC_AT_CTRL_POST_CHANGE_DLY 19 #define DWCMSHC_EMMC_DLL_CTRL 0x800 #define DWCMSHC_EMMC_DLL_CTRL_RESET BIT(1) #define DWCMSHC_EMMC_DLL_RXCLK 0x804 @@ -156,6 +160,9 @@ struct sdhci_data { u32 flags; u8 hs200_txclk_tapnum; u8 hs400_txclk_tapnum; + u8 hs400_cmdout_tapnum; + u8 hs400_strbin_tapnum; + u8 ddr50_strbin_delay_num; }; static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock) @@ -323,6 +330,11 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab udelay(1); sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); + extra = 0x3 << EMMC_AT_CTRL_POST_CHANGE_DLY | + 0x3 << EMMC_AT_CTRL_PRE_CHANGE_DLY | + EMMC_AT_CTRL_TUNE_CLK_STOP_EN; + sdhci_writel(host, extra, DWCMSHC_EMMC_AT_CTRL); + /* Init DLL settings */ extra = DWCMSHC_EMMC_DLL_START_DEFAULT << DWCMSHC_EMMC_DLL_START_POINT | DWCMSHC_EMMC_DLL_INC_VALUE << DWCMSHC_EMMC_DLL_INC | @@ -348,7 +360,7 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab extra = DLL_CMDOUT_SRC_CLK_NEG | DLL_CMDOUT_BOTH_CLK_EDGE | DWCMSHC_EMMC_DLL_DLYENA | - DLL_CMDOUT_TAPNUM_90_DEGREES | + data->hs400_cmdout_tapnum | DLL_CMDOUT_TAPNUM_FROM_SW; sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CMDOUT); } @@ -360,7 +372,7 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); extra = DWCMSHC_EMMC_DLL_DLYENA | - DLL_STRBIN_TAPNUM_DEFAULT | + data->hs400_strbin_tapnum | DLL_STRBIN_TAPNUM_FROM_SW; sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); } else { @@ -380,7 +392,7 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab */ extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_STRBIN_DELAY_NUM_SEL | - DLL_STRBIN_DELAY_NUM_DEFAULT << DLL_STRBIN_DELAY_NUM_OFFSET; + data->ddr50_strbin_delay_num << DLL_STRBIN_DELAY_NUM_OFFSET; sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); } @@ -647,6 +659,17 @@ static const struct sdhci_data rk3399_data = { .set_enhanced_strobe = rk3399_sdhci_set_enhanced_strobe, }; +static const struct sdhci_data rk3528_data = { + .set_ios_post = rk3568_sdhci_set_ios_post, + .set_clock = rk3568_sdhci_set_clock, + .config_dll = rk3568_sdhci_config_dll, + .hs200_txclk_tapnum = 0xc, + .hs400_txclk_tapnum = 0x6, + .hs400_cmdout_tapnum = 0x6, + .hs400_strbin_tapnum = 0x3, + .ddr50_strbin_delay_num = 0xa, +}; + static const struct sdhci_data rk3568_data = { .set_ios_post = rk3568_sdhci_set_ios_post, .set_clock = rk3568_sdhci_set_clock, @@ -654,6 +677,20 @@ static const struct sdhci_data rk3568_data = { .flags = FLAG_INVERTER_FLAG_IN_RXCLK, .hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT, .hs400_txclk_tapnum = 0x8, + .hs400_cmdout_tapnum = DLL_CMDOUT_TAPNUM_90_DEGREES, + .hs400_strbin_tapnum = DLL_STRBIN_TAPNUM_DEFAULT, + .ddr50_strbin_delay_num = DLL_STRBIN_DELAY_NUM_DEFAULT, +}; + +static const struct sdhci_data rk3576_data = { + .set_ios_post = rk3568_sdhci_set_ios_post, + .set_clock = rk3568_sdhci_set_clock, + .config_dll = rk3568_sdhci_config_dll, + .hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT, + .hs400_txclk_tapnum = 0x7, + .hs400_cmdout_tapnum = 0x7, + .hs400_strbin_tapnum = 0x5, + .ddr50_strbin_delay_num = 0xa, }; static const struct sdhci_data rk3588_data = { @@ -662,6 +699,9 @@ static const struct sdhci_data rk3588_data = { .config_dll = rk3568_sdhci_config_dll, .hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT, .hs400_txclk_tapnum = 0x9, + .hs400_cmdout_tapnum = DLL_CMDOUT_TAPNUM_90_DEGREES, + .hs400_strbin_tapnum = DLL_STRBIN_TAPNUM_DEFAULT, + .ddr50_strbin_delay_num = DLL_STRBIN_DELAY_NUM_DEFAULT, }; static const struct udevice_id sdhci_ids[] = { @@ -670,10 +710,18 @@ static const struct udevice_id sdhci_ids[] = { .data = (ulong)&rk3399_data, }, { + .compatible = "rockchip,rk3528-dwcmshc", + .data = (ulong)&rk3528_data, + }, + { .compatible = "rockchip,rk3568-dwcmshc", .data = (ulong)&rk3568_data, }, { + .compatible = "rockchip,rk3576-dwcmshc", + .data = (ulong)&rk3576_data, + }, + { .compatible = "rockchip,rk3588-dwcmshc", .data = (ulong)&rk3588_data, }, diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 4833b5158c7..648dfa4b5ef 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -177,8 +177,10 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data) } while (!(stat & SDHCI_INT_DATA_END)); #if (CONFIG_IS_ENABLED(MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)) - dma_unmap_single(host->start_addr, data->blocks * data->blocksize, - mmc_get_dma_dir(data)); + if (host->flags & USE_DMA) { + dma_unmap_single(host->start_addr, data->blocks * data->blocksize, + mmc_get_dma_dir(data)); + } #endif return 0; @@ -547,7 +549,7 @@ void sdhci_set_uhs_timing(struct sdhci_host *host) sdhci_writew(host, reg, SDHCI_HOST_CONTROL2); } -static void sdhci_set_voltage(struct sdhci_host *host) +void sdhci_set_voltage(struct sdhci_host *host) { if (IS_ENABLED(CONFIG_MMC_IO_VOLTAGE)) { struct mmc *mmc = (struct mmc *)host->mmc; diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 951e6acd34d..06c1e09bf26 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -478,29 +478,29 @@ struct sunxi_mmc_priv mmc_host[4]; static int mmc_resource_init(int sdc_no) { struct sunxi_mmc_priv *priv = &mmc_host[sdc_no]; - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + void *ccm = (void *)SUNXI_CCM_BASE; debug("init mmc %d resource\n", sdc_no); switch (sdc_no) { case 0: priv->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE; - priv->mclkreg = &ccm->sd0_clk_cfg; + priv->mclkreg = ccm + CCU_MMC0_CLK_CFG; break; case 1: priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE; - priv->mclkreg = &ccm->sd1_clk_cfg; + priv->mclkreg = ccm + CCU_MMC1_CLK_CFG; break; #ifdef SUNXI_MMC2_BASE case 2: priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE; - priv->mclkreg = &ccm->sd2_clk_cfg; + priv->mclkreg = ccm + CCU_MMC2_CLK_CFG; break; #endif #ifdef SUNXI_MMC3_BASE case 3: priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE; - priv->mclkreg = &ccm->sd3_clk_cfg; + priv->mclkreg = ccm + CCU_MMC3_CLK_CFG; break; #endif default: @@ -545,7 +545,7 @@ static const struct mmc_ops sunxi_mmc_ops = { struct mmc *sunxi_mmc_init(int sdc_no) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + void *ccm = (void *)SUNXI_CCM_BASE; struct sunxi_mmc_priv *priv = &mmc_host[sdc_no]; struct mmc_config *cfg = &priv->cfg; int ret; @@ -574,11 +574,11 @@ struct mmc *sunxi_mmc_init(int sdc_no) /* config ahb clock */ debug("init mmc %d clock and io\n", sdc_no); #if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2) - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no)); + setbits_le32(ccm + CCU_AHB_GATE0, 1 << AHB_GATE_OFFSET_MMC(sdc_no)); #ifdef CONFIG_SUNXI_GEN_SUN6I /* unassert reset */ - setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no)); + setbits_le32(ccm + CCU_AHB_RESET0_CFG, 1 << AHB_RESET_OFFSET_MMC(sdc_no)); #endif #if defined(CONFIG_MACH_SUN9I) /* sun9i has a mmc-common module, also set the gate and reset there */ @@ -586,9 +586,9 @@ struct mmc *sunxi_mmc_init(int sdc_no) SUNXI_MMC_COMMON_BASE + 4 * sdc_no); #endif #else /* CONFIG_SUN50I_GEN_H6 */ - setbits_le32(&ccm->sd_gate_reset, 1 << sdc_no); + setbits_le32(ccm + CCU_H6_MMC_GATE_RESET, 1 << sdc_no); /* unassert reset */ - setbits_le32(&ccm->sd_gate_reset, 1 << (RESET_SHIFT + sdc_no)); + setbits_le32(ccm + CCU_H6_MMC_GATE_RESET, 1 << (RESET_SHIFT + sdc_no)); #endif ret = mmc_set_mod_clk(priv, 24000000); if (ret) |