From 46b29af149c186ed5097ba2b4cc13c2f0d5d0c35 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 25 Mar 2010 15:36:28 +0800 Subject: ENGR00121976 UBOOT: some fix for SD/MMC card -Update eSDHC clock setting, -Fix the GPT timer setting, -Fix the boot option pars, -Remove mdelay() function call to improve the performance Signed-off-by:Jason Liu --- board/freescale/mx53_evk/mx53_evk.c | 49 ++++++++++++++-- cpu/arm_cortexa8/mx53/generic.c | 111 ++++++++++++++++++++++++++++++++++-- cpu/arm_cortexa8/mx53/timer.c | 4 +- drivers/mmc/imx_esdhc.c | 16 +++--- include/asm-arm/arch-mx53/mx53.h | 13 ++++- 5 files changed, 170 insertions(+), 23 deletions(-) diff --git a/board/freescale/mx53_evk/mx53_evk.c b/board/freescale/mx53_evk/mx53_evk.c index ceef3c3..4804b02 100644 --- a/board/freescale/mx53_evk/mx53_evk.c +++ b/board/freescale/mx53_evk/mx53_evk.c @@ -57,15 +57,34 @@ static inline void setup_boot_device(void) uint bt_mem_type = (soc_sbmr & 0x00000008) >> 3; switch (bt_mem_ctl) { - case 0x4: - boot_dev = MMC_BOOT; + case 0x0: + if (bt_mem_type) + boot_dev = ONE_NAND_BOOT; + else + boot_dev = WEIM_NOR_BOOT; break; - case 0x8: - boot_dev = NAND_BOOT; + case 0x2: + if (bt_mem_type) + boot_dev = SATA_BOOT; + else + boot_dev = PATA_BOOT; break; case 0x3: if (bt_mem_type) boot_dev = SPI_NOR_BOOT; + else + boot_dev = I2C_BOOT; + break; + case 0x4: + case 0x5: + boot_dev = SD_BOOT; + break; + case 0x6: + case 0x7: + boot_dev = MMC_BOOT; + break; + case 0x8 ... 0xf: + boot_dev = NAND_BOOT; break; default: boot_dev = UNKNOWN_BOOT; @@ -505,15 +524,33 @@ int checkboard(void) printf("Boot Device: "); switch (get_boot_device()) { - case NAND_BOOT: - printf("NAND\n"); + case WEIM_NOR_BOOT: + printf("NOR\n"); + break; + case ONE_NAND_BOOT: + printf("ONE NAND\n"); + break; + case PATA_BOOT: + printf("PATA\n"); + break; + case SATA_BOOT: + printf("SATA\n"); + break; + case I2C_BOOT: + printf("I2C\n"); break; case SPI_NOR_BOOT: printf("SPI NOR\n"); break; + case SD_BOOT: + printf("SD\n"); + break; case MMC_BOOT: printf("MMC\n"); break; + case NAND_BOOT: + printf("NAND\n"); + break; case UNKNOWN_BOOT: default: printf("UNKNOWN\n"); diff --git a/cpu/arm_cortexa8/mx53/generic.c b/cpu/arm_cortexa8/mx53/generic.c index f75d15a..cdd9d7c 100644 --- a/cpu/arm_cortexa8/mx53/generic.c +++ b/cpu/arm_cortexa8/mx53/generic.c @@ -116,7 +116,7 @@ static u32 __get_ipg_per_clk(void) /*! * This function returns the low power audio clock. */ -static u32 get_lp_apm(void) +static u32 __get_lp_apm(void) { u32 ret_val = 0; u32 ccsr = __REG(MXC_CCM_CCSR); @@ -145,7 +145,7 @@ static u32 __get_uart_clk(void) freq = __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ); break; case 0x4: - freq = get_lp_apm(); + freq = __get_lp_apm(); break; default: break; @@ -190,7 +190,7 @@ static u32 __get_cspi_clk(void) ret_val = __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ) / div; break; default: - ret_val = get_lp_apm() / div; + ret_val = __get_lp_apm() / div; break; } @@ -265,7 +265,100 @@ static u32 __get_ddr_clk(void) return ret_val; } +static u32 __get_esdhc1_clk(void) +{ + u32 ret_val = 0, div, pre_pdf, pdf; + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 cscdr1 = __REG(MXC_CCM_CSCDR1); + u32 esdh1_clk_sel; + + esdh1_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK) \ + >> MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET; + pre_pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK) \ + >> MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET; + pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK) \ + >> MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET ; + + div = (pre_pdf + 1) * (pdf + 1); + + switch (esdh1_clk_sel) { + case 0: + ret_val = __decode_pll(PLL1_CLK, CONFIG_MX53_HCLK_FREQ); + break; + case 1: + ret_val = __decode_pll(PLL2_CLK, CONFIG_MX53_HCLK_FREQ); + break; + case 2: + ret_val = __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ); + break; + case 3: + ret_val = __get_lp_apm(); + break; + default: + break; + } + + ret_val /= div; + + return ret_val; +} + +static u32 __get_esdhc3_clk(void) +{ + u32 ret_val = 0, div, pre_pdf, pdf; + u32 esdh3_clk_sel; + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 cscdr1 = __REG(MXC_CCM_CSCDR1); + esdh3_clk_sel = (cscmr1 & MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_MASK) \ + >> MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_OFFSET; + pre_pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_MASK) \ + >> MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_OFFSET; + pdf = (cscdr1 & MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_MASK) \ + >> MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_OFFSET ; + + div = (pre_pdf + 1) * (pdf + 1); + switch (esdh3_clk_sel) { + case 0: + ret_val = __decode_pll(PLL1_CLK, CONFIG_MX53_HCLK_FREQ); + break; + case 1: + ret_val = __decode_pll(PLL2_CLK, CONFIG_MX53_HCLK_FREQ); + break; + case 2: + ret_val = __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ); + break; + case 3: + ret_val = __get_lp_apm(); + break; + default: + break; + } + + ret_val /= div; + + return ret_val; +} + +static u32 __get_esdhc2_clk(void) +{ + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 esdh2_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ESDHC2_CLK_SEL; + if (esdh2_clk_sel) + return __get_esdhc3_clk(); + + return __get_esdhc1_clk(); +} + +static u32 __get_esdhc4_clk(void) +{ + u32 cscmr1 = __REG(MXC_CCM_CSCMR1); + u32 esdh4_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + if (esdh4_clk_sel) + return __get_esdhc3_clk(); + + return __get_esdhc1_clk(); +} unsigned int mxc_get_clock(enum mxc_clock clk) { switch (clk) { @@ -290,7 +383,13 @@ unsigned int mxc_get_clock(enum mxc_clock clk) case MXC_DDR_CLK: return __get_ddr_clk(); case MXC_ESDHC_CLK: - return __decode_pll(PLL3_CLK, CONFIG_MX53_HCLK_FREQ); + return __get_esdhc1_clk(); + case MXC_ESDHC2_CLK: + return __get_esdhc2_clk(); + case MXC_ESDHC3_CLK: + return __get_esdhc3_clk(); + case MXC_ESDHC4_CLK: + return __get_esdhc4_clk(); default: break; } @@ -315,6 +414,10 @@ void mxc_dump_clocks(void) printf("axi_b clock : %dHz\n", mxc_get_clock(MXC_AXI_B_CLK)); printf("emi_slow clock: %dHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK)); printf("ddr clock : %dHz\n", mxc_get_clock(MXC_DDR_CLK)); + printf("esdhc1 clock : %dHz\n", mxc_get_clock(MXC_ESDHC_CLK)); + printf("esdhc2 clock : %dHz\n", mxc_get_clock(MXC_ESDHC2_CLK)); + printf("esdhc3 clock : %dHz\n", mxc_get_clock(MXC_ESDHC3_CLK)); + printf("esdhc4 clock : %dHz\n", mxc_get_clock(MXC_ESDHC4_CLK)); } #if defined(CONFIG_DISPLAY_CPUINFO) diff --git a/cpu/arm_cortexa8/mx53/timer.c b/cpu/arm_cortexa8/mx53/timer.c index 65ddab9..e6b7846 100644 --- a/cpu/arm_cortexa8/mx53/timer.c +++ b/cpu/arm_cortexa8/mx53/timer.c @@ -38,7 +38,7 @@ #define GPTCR_CLKSOURCE_32 (0x100<<6) /* Clock source */ #define GPTCR_CLKSOURCE_IPG (0x001<<6) /* Clock source */ #define GPTCR_TEN (1) /* Timer enable */ -#define GPTPR_VAL (66) +#define GPTPR_VAL (50) static inline void setup_gpt(void) { @@ -54,7 +54,7 @@ static inline void setup_gpt(void) GPTCR = GPTCR_SWR; for (i = 0; i < 100; i++) GPTCR = 0; /* We have no udelay by now */ - GPTPR = GPTPR_VAL; /* 66Mhz / 66 */ + GPTPR = GPTPR_VAL; /* 50Mhz / 50 */ /* Freerun Mode, PERCLK1 input */ GPTCR |= GPTCR_CLKSOURCE_IPG | GPTCR_TEN; } diff --git a/drivers/mmc/imx_esdhc.c b/drivers/mmc/imx_esdhc.c index 39a0b49..95eee80 100644 --- a/drivers/mmc/imx_esdhc.c +++ b/drivers/mmc/imx_esdhc.c @@ -1,6 +1,6 @@ /* - * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. - * Terry Lv + * (C) Copyright 2008-2010 Freescale Semiconductor, Inc. + * Terry Lv, Jason Liu * * Copyright 2007, Freescale Semiconductor, Inc * Andy Fleming @@ -184,7 +184,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Wait for the bus to be idle */ while ((readl(®s->prsstat) & PRSSTAT_CICHB) || (readl(®s->prsstat) & PRSSTAT_CIDHB)) - mdelay(1); + ; while (readl(®s->prsstat) & PRSSTAT_DLA); @@ -193,7 +193,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) * Note: This is way more than 8 cycles, but 1ms seems to * resolve timing issues with some cards */ - mdelay(10); + udelay(1000); /* Set up for a data transfer if we have one */ if (data) { @@ -211,8 +211,6 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) writel(cmd->cmdarg, ®s->cmdarg); writel(xfertyp, ®s->xfertyp); - mdelay(10); - /* Mask all irqs */ writel(0, ®s->irqsigen); @@ -258,7 +256,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) for (i = 0; i < (block_cnt); ++i) { while (!(readl(®s->irqstat) & IRQSTAT_BRR)) - mdelay(1); + ; for (j = 0; j < (block_size >> 2); ++j, ++tmp_ptr) { *tmp_ptr = readl(®s->datport); @@ -271,8 +269,8 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) tmp_ptr = (u32 *)data->src; for (i = 0; i < (block_cnt); ++i) { - while (!(readl(®s->irqstat) & IRQSTAT_BWR)) - mdelay(1); + while (!(readl(®s->irqstat) & IRQSTAT_BWR)) + ; for (j = 0; j < (block_size >> 2); ++j, ++tmp_ptr) { writel(*tmp_ptr, ®s->datport); diff --git a/include/asm-arm/arch-mx53/mx53.h b/include/asm-arm/arch-mx53/mx53.h index e985357..b1f3d27 100644 --- a/include/asm-arm/arch-mx53/mx53.h +++ b/include/asm-arm/arch-mx53/mx53.h @@ -379,10 +379,16 @@ #ifndef __ASSEMBLER__ enum boot_device { - UNKNOWN_BOOT, - NAND_BOOT, + WEIM_NOR_BOOT, + ONE_NAND_BOOT, + PATA_BOOT, + SATA_BOOT, + I2C_BOOT, SPI_NOR_BOOT, + SD_BOOT, MMC_BOOT, + NAND_BOOT, + UNKNOWN_BOOT }; enum mxc_clock { @@ -397,6 +403,9 @@ enum mxc_clock { MXC_EMI_SLOW_CLK, MXC_DDR_CLK, MXC_ESDHC_CLK, + MXC_ESDHC2_CLK, + MXC_ESDHC3_CLK, + MXC_ESDHC4_CLK, }; enum mxc_peri_clocks { -- cgit v1.1