Browse Source

Merge branch 'CR_6570_SDBOOT_u-boot_william.qiu' into 'jh7110-master'

CR_6570: mmc: starfive: add HS200 support

See merge request sdk/u-boot!62
andy.hu 10 months ago
parent
commit
f1ad44f525
4 changed files with 113 additions and 2 deletions
  1. 23 1
      arch/riscv/include/asm/arch-jh7110/gpio.h
  2. 2 0
      configs/starfive_evb_defconfig
  3. 78 1
      drivers/mmc/dw_mmc.c
  4. 10 0
      include/dwmmc.h

+ 23 - 1
arch/riscv/include/asm/arch-jh7110/gpio.h

@@ -20,6 +20,14 @@ extern "C" {
 #define GPIO_DOEN_MASK	0x3f
 #define GPIO_DOUT_MASK	0x7f
 #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
+#define GPIO_PULL_DOWN	2
 
 #define NR_GPIOS		64
 
@@ -38,8 +46,10 @@ enum gpio_state {
 #define GPIO_DOUT	0x40
 #define GPIO_DIN	0x80
 #define GPIO_EN		0xdc
-#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 {
@@ -61,6 +71,18 @@ struct starfive_gpio_platdata {
 		GPIO_DIN_MASK << GPIO_SHIFT(gpi),\
 		((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)
+
+#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)
+
 #define SYS_IOMUX_COMPLEX(gpio, gpi, gpo, oen) do {\
 		SYS_IOMUX_DOEN(gpio, oen);\
 		SYS_IOMUX_DOUT(gpio, gpo);\

+ 2 - 0
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

+ 78 - 1
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;
 }

+ 10 - 0
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 {