diff options
author | Andy Hu <andy.hu@starfivetech.com> | 2023-07-27 05:02:40 +0300 |
---|---|---|
committer | Andy Hu <andy.hu@starfivetech.com> | 2023-07-27 05:02:40 +0300 |
commit | ef1922cbce5fbb7be9d638a3df6cf989f4414cc2 (patch) | |
tree | 6aea92a3f925cf1e171a81791fc195f2b122b1cf | |
parent | ab0801f58135b80495dee1bfe1483d1007c85e31 (diff) | |
parent | f1ad44f525915b4f5a3ba04eee3be6e15c08aa77 (diff) | |
download | u-boot-ef1922cbce5fbb7be9d638a3df6cf989f4414cc2.tar.xz |
Merge tag 'JH7110_515_SDK_v5.4.2' into vf2-devel
-rw-r--r-- | arch/riscv/include/asm/arch-jh7110/gpio.h | 19 | ||||
-rw-r--r-- | configs/starfive_evb_defconfig | 2 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 79 | ||||
-rw-r--r-- | include/dwmmc.h | 10 |
4 files changed, 103 insertions, 7 deletions
diff --git a/arch/riscv/include/asm/arch-jh7110/gpio.h b/arch/riscv/include/asm/arch-jh7110/gpio.h index 94a27a75b9..68a9bdc9ed 100644 --- a/arch/riscv/include/asm/arch-jh7110/gpio.h +++ b/arch/riscv/include/asm/arch-jh7110/gpio.h @@ -22,6 +22,8 @@ extern "C" { #define GPIO_DIN_MASK 0x7f #define GPIO_DS_MASK 0x06 #define GPIO_DS_SHIFT 1 +#define GPIO_SLEW_MASK BIT(5) +#define GPIO_SLEW_SHIFT 5 #define GPIO_PULL_MASK 0x18 #define GPIO_PULL_SHIFT 3 #define GPIO_PULL_UP 1 @@ -44,9 +46,10 @@ enum gpio_state { #define GPIO_DOUT 0x40 #define GPIO_DIN 0x80 #define GPIO_EN 0xdc -#define GPIO_CONFIG 0x120 -#define GPIO_LOW_IE 0x100 +#define GPIO_LOW_IE 0x100 #define GPIO_HIGH_IE 0x104 +#define GPIO_CONFIG 0x120 + /* Details about a GPIO bank */ struct starfive_gpio_platdata { @@ -69,12 +72,16 @@ struct starfive_gpio_platdata { ((gpio+2) & GPIO_DIN_MASK) << GPIO_SHIFT(gpi)) #define SYS_IOMUX_SET_DS(gpio, ds) \ - clrsetbits_le32(SYS_IOMUX_BASE + GPIO_CONFIG + gpio * 4, \ - GPIO_DS_MASK, (ds) << GPIO_DS_SHIFT) + clrsetbits_le32(SYS_IOMUX_BASE + GPIO_CONFIG + gpio * 4, \ + GPIO_DS_MASK, (ds) << GPIO_DS_SHIFT) + +#define SYS_IOMUX_SET_SLEW(gpio, slew) \ + clrsetbits_le32(SYS_IOMUX_BASE + GPIO_CONFIG + gpio * 4, \ + GPIO_SLEW_MASK, (slew) << GPIO_SLEW_SHIFT) #define SYS_IOMUX_SET_PULL(gpio, pull) \ - clrsetbits_le32(SYS_IOMUX_BASE + GPIO_CONFIG + gpio * 4, \ - GPIO_PULL_MASK, (pull) << GPIO_PULL_SHIFT) + clrsetbits_le32(SYS_IOMUX_BASE + GPIO_CONFIG + gpio * 4, \ + GPIO_PULL_MASK, (pull) << GPIO_PULL_SHIFT) #define SYS_IOMUX_COMPLEX(gpio, gpi, gpo, oen) do {\ SYS_IOMUX_DOEN(gpio, oen);\ diff --git a/configs/starfive_evb_defconfig b/configs/starfive_evb_defconfig index 91769d83c3..f64cb42b00 100644 --- a/configs/starfive_evb_defconfig +++ b/configs/starfive_evb_defconfig @@ -72,6 +72,8 @@ CONFIG_CLK_CCF=y CONFIG_CLK_COMPOSITE_CCF=y CONFIG_SPL_CLK_JH7110=y CONFIG_SYS_I2C_DW=y +CONFIG_MMC_HS200_SUPPORT=y +CONFIG_SPL_MMC_HS200_SUPPORT=y CONFIG_MMC_DW=y CONFIG_MMC_DW_SNPS=y CONFIG_SF_DEFAULT_MODE=0x0 diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index a949dad574..b3b69fabd4 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -21,6 +21,19 @@ #define PAGE_SIZE 4096 +static inline int __test_and_clear_bit_1(int nr, void *addr) +{ + int mask, retval; + unsigned int *a = (unsigned int *)addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a &= ~mask; + + return retval; +} + static int dwmci_wait_reset(struct dwmci_host *host, u32 value) { unsigned long timeout = 1000; @@ -317,6 +330,9 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, if (cmd->resp_type & MMC_RSP_CRC) flags |= DWMCI_CMD_CHECK_CRC; + if (__test_and_clear_bit_1(DW_MMC_CARD_NEED_INIT, &host->flags)) + flags |= DWMCI_CMD_SEND_INIT; + flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG); debug("Sending CMD%d\n",cmd->cmdidx); @@ -522,6 +538,64 @@ static int dwmci_set_ios(struct mmc *mmc) return 0; } +static void dw_mci_hs_set_bits(struct dwmci_host *host, u32 smpl_phase) +{ + /* change driver phase and sample phase */ + u32 mask = 0x1f; + u32 reg_value; + + reg_value = dwmci_readl(host, DWMCI_UHS_REG_EXT); + + /* In UHS_REG_EXT, only 5 bits valid in DRV_PHASE and SMPL_PHASE */ + reg_value &= ~(mask << 16); + reg_value |= (smpl_phase << 16); + dwmci_writel(host, DWMCI_UHS_REG_EXT, reg_value); + + /* We should delay 1ms wait for timing setting finished. */ + udelay(1000); +} + +static int dwmci_execute_tuning(struct udevice *dev, uint opcode) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + struct dwmci_host *host = mmc->priv; + int err = -1; + int smpl_phase, smpl_raise = -1, smpl_fall = -1; + int i; + + for (i = 0; i < 32; ++i) { + smpl_phase = i; + dw_mci_hs_set_bits(host, smpl_phase); + dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL); + + err = mmc_send_tuning(mmc, opcode, NULL); + + if (!err && smpl_raise < 0) { + smpl_raise = i; + } else if (err && smpl_raise >= 0) { + smpl_fall = i - 1; + break; + } + } + + if (i >= 32 && smpl_raise >= 0) + smpl_fall = 31; + + if (smpl_raise < 0) { + pr_err("No valid delay chain! use default\n"); + dw_mci_hs_set_bits(host, 0); + err = -EINVAL; + } else { + smpl_phase = (smpl_raise + smpl_fall) / 2; + dw_mci_hs_set_bits(host, smpl_phase); + pr_debug("Found valid delay chain! use it [delay=%d]\n", smpl_phase); + err = 0; + } + + dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL); + return err; +} + static int dwmci_init(struct mmc *mmc) { struct dwmci_host *host = mmc->priv; @@ -536,6 +610,8 @@ static int dwmci_init(struct mmc *mmc) return -EIO; } + host->flags = 1 << DW_MMC_CARD_NEED_INIT; + /* Enumerate at 400KHz */ dwmci_setup_bus(host, mmc->cfg->f_min); @@ -577,6 +653,7 @@ int dwmci_probe(struct udevice *dev) const struct dm_mmc_ops dm_dwmci_ops = { .send_cmd = dwmci_send_cmd, .set_ios = dwmci_set_ios, + .execute_tuning = dwmci_execute_tuning, }; #else @@ -608,7 +685,7 @@ void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host, cfg->host_caps |= MMC_MODE_4BIT; cfg->host_caps &= ~MMC_MODE_8BIT; } - cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz; + cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS200; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; } diff --git a/include/dwmmc.h b/include/dwmmc.h index 5fc8ed8395..fe1be76a7d 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -49,6 +49,7 @@ #define DWMCI_IDINTEN 0x090 #define DWMCI_DSCADDR 0x094 #define DWMCI_BUFADDR 0x098 +#define DWMCI_UHS_REG_EXT 0x108 #define DWMCI_DATA 0x200 /* Interrupt Mask register */ @@ -91,6 +92,7 @@ #define DWMCI_CMD_RW (1 << 10) #define DWMCI_CMD_SEND_STOP (1 << 12) #define DWMCI_CMD_ABORT_STOP (1 << 14) +#define DWMCI_CMD_SEND_INIT (1 << 15) #define DWMCI_CMD_PRV_DAT_WAIT (1 << 13) #define DWMCI_CMD_UPD_CLK (1 << 21) #define DWMCI_CMD_USE_HOLD_REG (1 << 29) @@ -197,6 +199,14 @@ struct dwmci_host { /* use fifo mode to read and write data */ bool fifo_mode; + + /* Starfive: porting from kernel 5.15, fix mmc device power-up sequence */ + unsigned int flags; +#define DW_MMC_CARD_PRESENT 0 +#define DW_MMC_CARD_NEED_INIT 1 +#define DW_MMC_CARD_NO_LOW_PWR 2 +#define DW_MMC_CARD_NO_USE_HOLD 3 +#define DW_MMC_CARD_NEEDS_POLL 4 }; struct dwmci_idmac { |