mmc: fsl_esdhc: Add peripheral clock support
authorYangbo Lu <yangbo.lu@freescale.com>
Wed, 22 Apr 2015 05:57:40 +0000 (13:57 +0800)
committerYork Sun <yorksun@freescale.com>
Mon, 4 May 2015 16:25:39 +0000 (09:25 -0700)
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@freescale.com>
Cc: York Sun <yorksun@freescale.com>
Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
Reviewed-by: York Sun <yorksun@freescale.com>
arch/powerpc/cpu/mpc85xx/speed.c
arch/powerpc/include/asm/config_mpc85xx.h
drivers/mmc/fsl_esdhc.c
include/e500.h
include/fsl_esdhc.h

index 321ade24fe7d639f1723f2bcb8672167202167c4..d954fe2fd20cb6637d5b40f5c6ecfde90701451f 100644 (file)
@@ -73,7 +73,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];
@@ -453,6 +454,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()) {
@@ -660,12 +703,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)
index fecfe1b03cd34145ae142220c4b9a287523fb97a..9d56bc17732dd547506536f2e9a6a784e03268a7 100644 (file)
@@ -775,7 +775,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
@@ -791,6 +790,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
@@ -823,7 +825,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
@@ -836,6 +837,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
@@ -883,6 +886,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
index 270ec1c1fad6a34c87538c85f50ad3d3440e5190..c690a9722d34425857c36c6d2b0289d62d0c6662 100644 (file)
@@ -506,11 +506,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);
 
@@ -740,8 +776,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);
index 255f46bf1e54c0ac98c46e35e20997819eb184a9..1acf7784dfc9ea04be7a5f803dbd39778a2c9ea5 100644 (file)
@@ -18,6 +18,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
index bec8a0e4ccbb47f7c40156619ed8b835752ad2f7..0d00b7dfdbc5969bfd047cbacca57451a7756060 100644 (file)
@@ -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)