[U-Boot] [PATCH v3 3/4] mmc: fsl_esdhc: Add peripheral clock support

Yangbo Lu yangbo.lu at freescale.com
Wed Apr 22 07:57:40 CEST 2015


The SD clock could be generated by platform clock or peripheral
clock for some platforms. This patch adds peripheral clock
support for T1024/T1040/T2080. To enable it, define
CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK.

Signed-off-by: Yangbo Lu <yangbo.lu at freescale.com>
Cc: York Sun <yorksun at freescale.com>
Cc: Pantelis Antoniou <panto at antoniou-consulting.com>
---
Changes for v3:
	- Add Pantelis Antoniou to Cc list
	- Modify some code and commit message
---
---
 arch/powerpc/cpu/mpc85xx/speed.c          | 49 ++++++++++++++++++++++++++++++-
 arch/powerpc/include/asm/config_mpc85xx.h | 10 +++++--
 drivers/mmc/fsl_esdhc.c                   | 41 ++++++++++++++++++++++++++
 include/e500.h                            |  1 +
 include/fsl_esdhc.h                       |  4 +++
 5 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/cpu/mpc85xx/speed.c b/arch/powerpc/cpu/mpc85xx/speed.c
index 7e69873..79202bb 100644
--- a/arch/powerpc/cpu/mpc85xx/speed.c
+++ b/arch/powerpc/cpu/mpc85xx/speed.c
@@ -69,7 +69,8 @@ void get_sys_info(sys_info_t *sys_info)
 		[14] = 4,	/* CC4 PPL / 4 */
 	};
 	uint i, freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
-#if !defined(CONFIG_FM_PLAT_CLK_DIV) || !defined(CONFIG_PME_PLAT_CLK_DIV)
+#if !defined(CONFIG_FM_PLAT_CLK_DIV) || !defined(CONFIG_PME_PLAT_CLK_DIV) || \
+	defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)
 	uint rcw_tmp;
 #endif
 	uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
@@ -313,6 +314,48 @@ void get_sys_info(sys_info_t *sys_info)
 #endif
 #endif
 
+#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
+#if defined(CONFIG_PPC_T2080)
+#define ESDHC_CLK_SEL	0x00000007
+#define ESDHC_CLK_SHIFT	0
+#define ESDHC_CLK_RCWSR	15
+#else	/* Support T1040 T1024 by now */
+#define ESDHC_CLK_SEL	0xe0000000
+#define ESDHC_CLK_SHIFT	29
+#define ESDHC_CLK_RCWSR	7
+#endif
+	rcw_tmp = in_be32(&gur->rcwsr[ESDHC_CLK_RCWSR]);
+	switch ((rcw_tmp & ESDHC_CLK_SEL) >> ESDHC_CLK_SHIFT) {
+	case 1:
+		sys_info->freq_sdhc = freq_c_pll[CONFIG_SYS_SDHC_CLK];
+		break;
+	case 2:
+		sys_info->freq_sdhc = freq_c_pll[CONFIG_SYS_SDHC_CLK] / 2;
+		break;
+	case 3:
+		sys_info->freq_sdhc = freq_c_pll[CONFIG_SYS_SDHC_CLK] / 3;
+		break;
+#if defined(CONFIG_SYS_SDHC_CLK_2_PLL)
+	case 4:
+		sys_info->freq_sdhc = freq_c_pll[CONFIG_SYS_SDHC_CLK] / 4;
+		break;
+#if defined(CONFIG_PPC_T2080)
+	case 5:
+		sys_info->freq_sdhc = freq_c_pll[1 - CONFIG_SYS_SDHC_CLK];
+		break;
+#endif
+	case 6:
+		sys_info->freq_sdhc = freq_c_pll[1 - CONFIG_SYS_SDHC_CLK] / 2;
+		break;
+	case 7:
+		sys_info->freq_sdhc = freq_c_pll[1 - CONFIG_SYS_SDHC_CLK] / 3;
+		break;
+#endif
+	default:
+		sys_info->freq_sdhc = 0;
+		printf("Error: Unknown SDHC peripheral clock select!\n");
+	}
+#endif
 #else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
 
 	for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
@@ -520,12 +563,16 @@ int get_clocks (void)
 	gd->arch.i2c2_clk = gd->arch.i2c1_clk;
 
 #if defined(CONFIG_FSL_ESDHC)
+#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
+	gd->arch.sdhc_clk = sys_info.freq_sdhc / 2;
+#else
 #if defined(CONFIG_MPC8569) || defined(CONFIG_P1010) ||\
        defined(CONFIG_P1014)
 	gd->arch.sdhc_clk = gd->bus_clk;
 #else
 	gd->arch.sdhc_clk = gd->bus_clk / 2;
 #endif
+#endif
 #endif /* defined(CONFIG_FSL_ESDHC) */
 
 #if defined(CONFIG_CPM2)
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index 01b0905..24c593b 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -757,7 +757,6 @@ defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022)
 #endif
 #define CONFIG_SYS_FSL_NUM_CC_PLLS	2
 #define CONFIG_SYS_FSL_CLUSTER_CLOCKS   { 1, 1, 1, 1 }
-#define CONFIG_SYS_SDHC_CLOCK		0
 #define CONFIG_SYS_FSL_NUM_LAWS		16
 #define CONFIG_SYS_FSL_SRDS_1
 #define CONFIG_SYS_FSL_SEC_COMPAT	5
@@ -773,6 +772,9 @@ defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022)
 #define CONFIG_SYS_FMAN_V3
 #define CONFIG_FM_PLAT_CLK_DIV	1
 #define CONFIG_SYS_FM1_CLK		CONFIG_FM_PLAT_CLK_DIV
+#define CONFIG_SYS_SDHC_CLK		0/* Select SDHC CLK begining from PLL1
+					    per rcw field value */
+#define CONFIG_SYS_SDHC_CLK_2_PLL	/* Select SDHC CLK from 2 PLLs */
 #define CONFIG_SYS_FM_MURAM_SIZE	0x30000
 #define CONFIG_SYS_FSL_SINGLE_SOURCE_CLK
 #define CONFIG_SYS_FSL_TBCLK_DIV	16
@@ -805,7 +807,6 @@ defined(CONFIG_PPC_T1014) || defined(CONFIG_PPC_T1013)
 #endif
 #define CONFIG_SYS_FSL_NUM_CC_PLL	2
 #define CONFIG_SYS_FSL_CLUSTER_CLOCKS  { 1, 1, 1, 1 }
-#define CONFIG_SYS_SDHC_CLOCK		0
 #define CONFIG_SYS_FSL_NUM_LAWS		16
 #define CONFIG_SYS_FSL_SRDS_1
 #define CONFIG_SYS_FSL_SEC_COMPAT	5
@@ -818,6 +819,8 @@ defined(CONFIG_PPC_T1014) || defined(CONFIG_PPC_T1013)
 #define CONFIG_SYS_FSL_DDR_VER	 FSL_DDR_VER_5_0
 #define CONFIG_SYS_FSL_IFC_BANK_COUNT	8
 #define CONFIG_SYS_FM1_CLK		0
+#define CONFIG_SYS_SDHC_CLK		0/* Select SDHC CLK begining from PLL1
+					    per rcw field value */
 #define CONFIG_QBMAN_CLK_DIV		1
 #define CONFIG_SYS_FM_MURAM_SIZE	0x30000
 #define CONFIG_SYS_FSL_SINGLE_SOURCE_CLK
@@ -865,6 +868,9 @@ defined(CONFIG_PPC_T1014) || defined(CONFIG_PPC_T1013)
 #define CONFIG_PME_PLAT_CLK_DIV		1
 #define CONFIG_SYS_PME_CLK		CONFIG_PME_PLAT_CLK_DIV
 #define CONFIG_SYS_FM1_CLK		0
+#define CONFIG_SYS_SDHC_CLK		1/* Select SDHC CLK begining from PLL2
+					    per rcw field value */
+#define CONFIG_SYS_SDHC_CLK_2_PLL	/* Select SDHC CLK from 2 PLLs */
 #define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_7
 #define CONFIG_SYS_FSL_IFC_BANK_COUNT	8
 #define CONFIG_SYS_FMAN_V3
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 355cada..1d5bc2d 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -459,11 +459,47 @@ static void set_sysctl(struct mmc *mmc, uint clock)
 	esdhc_setbits32(&regs->sysctl, clk);
 }
 
+#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
+static void esdhc_clock_control(struct mmc *mmc, bool enable)
+{
+	struct fsl_esdhc_cfg *cfg = mmc->priv;
+	struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
+	u32 value;
+	u32 time_out;
+
+	value = esdhc_read32(&regs->sysctl);
+
+	if (enable)
+		value |= SYSCTL_CKEN;
+	else
+		value &= ~SYSCTL_CKEN;
+
+	esdhc_write32(&regs->sysctl, value);
+
+	time_out = 20;
+	value = PRSSTAT_SDSTB;
+	while (!(esdhc_read32(&regs->prsstat) & value)) {
+		if (time_out == 0) {
+			printf("fsl_esdhc: Internal clock never stabilised.\n");
+			break;
+		}
+		time_out--;
+		mdelay(1);
+	}
+}
+#endif
+
 static void esdhc_set_ios(struct mmc *mmc)
 {
 	struct fsl_esdhc_cfg *cfg = mmc->priv;
 	struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 
+#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
+	/* Select to use peripheral clock */
+	esdhc_clock_control(mmc, false);
+	esdhc_setbits32(&regs->scr, ESDHCCTL_PCS);
+	esdhc_clock_control(mmc, true);
+#endif
 	/* Set the clock speed */
 	set_sysctl(mmc, mmc->clock);
 
@@ -689,8 +725,13 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd)
 	}
 #endif
 
+#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
+	do_fixup_by_compat_u32(blob, compat, "peripheral-frequency",
+			       gd->arch.sdhc_clk, 1);
+#else
 	do_fixup_by_compat_u32(blob, compat, "clock-frequency",
 			       gd->arch.sdhc_clk, 1);
+#endif
 #ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
 	do_fixup_by_compat_u32(blob, compat, "adapter-type",
 			       (u32)(gd->arch.sdhc_adapter), 1);
diff --git a/include/e500.h b/include/e500.h
index 5884a22..07d0ee8 100644
--- a/include/e500.h
+++ b/include/e500.h
@@ -15,6 +15,7 @@ typedef struct
 	unsigned long freq_ddrbus;
 	unsigned long freq_localbus;
 	unsigned long freq_qe;
+	unsigned long freq_sdhc;
 #ifdef CONFIG_SYS_DPAA_FMAN
 	unsigned long freq_fman[CONFIG_SYS_NUM_FMAN];
 #endif
diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h
index 5462b4c..aba0f87 100644
--- a/include/fsl_esdhc.h
+++ b/include/fsl_esdhc.h
@@ -78,6 +78,9 @@
 #define IRQSTATEN_TC		(0x00000002)
 #define IRQSTATEN_CC		(0x00000001)
 
+#define ESDHCCTL		0x0002e40c
+#define ESDHCCTL_PCS		(0x00080000)
+
 #define PRSSTAT			0x0002e024
 #define PRSSTAT_DAT0		(0x01000000)
 #define PRSSTAT_CLSL		(0x00800000)
@@ -86,6 +89,7 @@
 #define PRSSTAT_CINS		(0x00010000)
 #define PRSSTAT_BREN		(0x00000800)
 #define PRSSTAT_BWEN		(0x00000400)
+#define PRSSTAT_SDSTB		(0X00000008)
 #define PRSSTAT_DLA		(0x00000004)
 #define PRSSTAT_CICHB		(0x00000002)
 #define PRSSTAT_CIDHB		(0x00000001)
-- 
2.1.0.27.g96db324



More information about the U-Boot mailing list