1 From 1bc5e5f2cee211a74ee79e0eb5f7f37a3db387f4 Mon Sep 17 00:00:00 2001
2 From: Anish Trivedi <anish@freescale.com>
3 Date: Fri, 16 Jul 2010 12:35:32 -0500
4 Subject: [PATCH] ENGR00125036 Uboot Add eMMC 4.4 support
6 Enable DDR mode on ESDHC controller and mmc library
7 Enable 8-bit support in mmc library
9 Signed-off-by: Anish Trivedi <anish@freescale.com>
11 common/cmd_mmc.c | 6 ++
12 drivers/mmc/imx_esdhc.c | 55 ++++++++++++++++--
13 drivers/mmc/mmc.c | 109 ++++++++++++++++++++++++++++++++++-
14 include/configs/mx50_arm2.h | 6 ++-
15 include/configs/mx50_arm2_lpddr2.h | 7 ++-
16 include/fsl_esdhc.h | 10 +++
17 include/mmc.h | 12 ++++-
18 7 files changed, 193 insertions(+), 12 deletions(-)
20 diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
21 index 1061dab..139b1e8 100644
22 --- a/common/cmd_mmc.c
23 +++ b/common/cmd_mmc.c
24 @@ -138,6 +138,12 @@ static void print_mmcinfo(struct mmc *mmc)
25 printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
26 printf("Capacity: %lld\n", mmc->capacity);
28 +#ifdef CONFIG_EMMC_DDR_MODE
29 + if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
30 + mmc->bus_width == EMMC_MODE_8BIT_DDR)
31 + printf("Bus Width: %d-bit DDR\n", (mmc->bus_width >> 8));
34 printf("Bus Width: %d-bit\n", mmc->bus_width);
35 #ifdef CONFIG_BOOT_PARTITION_ACCESS
36 if (mmc->boot_size_mult == 0) {
37 diff --git a/drivers/mmc/imx_esdhc.c b/drivers/mmc/imx_esdhc.c
38 index e3a1fb7..a57aa74 100644
39 --- a/drivers/mmc/imx_esdhc.c
40 +++ b/drivers/mmc/imx_esdhc.c
41 @@ -69,10 +69,11 @@ struct fsl_esdhc {
45 - char reserved2[168];
49 + char reserved3[148];
51 - char reserved3[780];
55 /* Return the XFERTYP flags for a given command and data packet */
56 @@ -197,6 +198,10 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
57 /* Figure out the transfer arguments */
58 xfertyp = esdhc_xfertyp(cmd, data);
60 + if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
61 + mmc->bus_width == EMMC_MODE_8BIT_DDR)
62 + xfertyp |= XFERTYP_DDR_EN;
64 /* Send the command */
65 writel(cmd->cmdarg, ®s->cmdarg);
66 writel(xfertyp, ®s->xfertyp);
67 @@ -274,6 +279,9 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
68 while (!(readl(®s->irqstat) & IRQSTAT_TC)) ;
71 + if (readl(®s->irqstat) & 0xFFFF0000)
74 writel(-1, ®s->irqstat);
77 @@ -325,6 +333,22 @@ void set_sysctl(struct mmc *mmc, uint clock)
81 +static void esdhc_dll_setup(struct mmc *mmc)
83 + struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
84 + struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
86 + uint dll_control = readl(®s->dllctrl);
87 + dll_control &= ~(ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK |
88 + ESDHC_DLLCTRL_SLV_OVERRIDE);
89 + dll_control |= ((ESDHC_DLLCTRL_SLV_OVERRIDE_VAL <<
90 + ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_SHIFT) |
91 + ESDHC_DLLCTRL_SLV_OVERRIDE);
93 + writel(dll_control, ®s->dllctrl);
97 static void esdhc_set_ios(struct mmc *mmc)
99 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
100 @@ -344,6 +368,14 @@ static void esdhc_set_ios(struct mmc *mmc)
101 } else if (mmc->bus_width == 8) {
102 tmp = readl(®s->proctl) | PROCTL_DTW_8;
103 writel(tmp, ®s->proctl);
104 + } else if (mmc->bus_width == EMMC_MODE_4BIT_DDR) {
105 + tmp = readl(®s->proctl) | PROCTL_DTW_4;
106 + writel(tmp, ®s->proctl);
107 + esdhc_dll_setup(mmc);
108 + } else if (mmc->bus_width == EMMC_MODE_8BIT_DDR) {
109 + tmp = readl(®s->proctl) | PROCTL_DTW_8;
110 + writel(tmp, ®s->proctl);
111 + esdhc_dll_setup(mmc);
115 @@ -411,22 +443,35 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
116 mmc->set_ios = esdhc_set_ios;
117 mmc->init = esdhc_init;
119 - caps = regs->hostcapblt;
120 + caps = readl(®s->hostcapblt);
121 if (caps & ESDHC_HOSTCAPBLT_VS30)
122 mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
123 if (caps & ESDHC_HOSTCAPBLT_VS33)
124 mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
126 - mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
127 + mmc->host_caps = MMC_MODE_4BIT;
129 if (caps & ESDHC_HOSTCAPBLT_HSS)
130 mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
132 + if (((readl(®s->hostver) & ESDHC_HOSTVER_VVN_MASK)
133 + >> ESDHC_HOSTVER_VVN_SHIFT) >= ESDHC_HOSTVER_DDR_SUPPORT)
134 + mmc->host_caps |= EMMC_MODE_4BIT_DDR;
137 mmc->f_max = MIN(mxc_get_clock(MXC_ESDHC_CLK), 50000000);
141 +#ifdef CONFIG_MMC_8BIT_PORTS
142 + if ((1 << mmc->block_dev.dev) & CONFIG_MMC_8BIT_PORTS) {
143 + mmc->host_caps |= MMC_MODE_8BIT;
145 + if (mmc->host_caps & EMMC_MODE_4BIT_DDR)
146 + mmc->host_caps |= EMMC_MODE_8BIT_DDR;
153 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
154 index 072ef46..9f915cd 100644
155 --- a/drivers/mmc/mmc.c
156 +++ b/drivers/mmc/mmc.c
157 @@ -91,6 +91,13 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
159 blklen = mmc->write_bl_len;
161 +#ifdef CONFIG_EMMC_DDR_MODE
162 + if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
163 + mmc->bus_width == EMMC_MODE_8BIT_DDR) {
168 err = mmc_set_blocklen(mmc, mmc->write_bl_len);
171 @@ -173,6 +180,12 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)
172 int endblock = lldiv(src + size - 1, mmc->read_bl_len);
175 +#ifdef CONFIG_EMMC_DDR_MODE
176 + if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
177 + mmc->bus_width == EMMC_MODE_8BIT_DDR)
181 /* Make a buffer big enough to hold all the blocks we might read */
182 buffer = malloc(blklen);
184 @@ -181,6 +194,12 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)
188 +#ifdef CONFIG_EMMC_DDR_MODE
189 + if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
190 + mmc->bus_width == EMMC_MODE_8BIT_DDR)
194 /* We always do full block reads from the card */
195 err = mmc_set_blocklen(mmc, mmc->read_bl_len);
197 @@ -229,9 +248,14 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
201 - blklen = mmc->read_bl_len;
203 - err = mmc_set_blocklen(mmc, blklen);
204 + if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
205 + mmc->bus_width == EMMC_MODE_8BIT_DDR) {
209 + blklen = mmc->read_bl_len;
210 + err = mmc_set_blocklen(mmc, blklen);
214 puts("set read bl len failed\n\r");
215 @@ -444,7 +468,8 @@ static int mmc_change_freq(struct mmc *mmc)
216 if (mmc->version < MMC_VERSION_4)
219 - mmc->card_caps |= MMC_MODE_4BIT;
220 + mmc->card_caps |= ((mmc->host_caps & MMC_MODE_8BIT)
221 + ? MMC_MODE_8BIT : MMC_MODE_4BIT);
223 ext_csd = (char *)malloc(512);
225 @@ -488,6 +513,15 @@ static int mmc_change_freq(struct mmc *mmc)
226 mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
228 mmc->card_caps |= MMC_MODE_HS;
229 +#ifdef CONFIG_EMMC_DDR_MODE
230 + if (cardtype & EMMC_MODE_DDR_3V) {
231 + if (mmc->card_caps & MMC_MODE_8BIT)
232 + mmc->card_caps |= EMMC_MODE_8BIT_DDR;
234 + mmc->card_caps |= EMMC_MODE_4BIT_DDR;
241 @@ -681,6 +715,9 @@ int mmc_switch_partition(struct mmc *mmc, uint part, uint enable_boot)
243 uint old_part, new_part;
245 +#ifdef CONFIG_EMMC_DDR_MODE
246 + char boot_bus_width, card_boot_bus_width;
249 /* partition must be -
251 @@ -765,6 +802,44 @@ int mmc_switch_partition(struct mmc *mmc, uint part, uint enable_boot)
255 +#ifdef CONFIG_EMMC_DDR_MODE
256 + /* Program boot_bus_width field for eMMC 4.4 boot mode */
257 + if ((ext_csd[EXT_CSD_CARD_TYPE] & 0xC) && enable_boot != 0) {
259 + /* Configure according to this host's capabilities */
260 + if (mmc->host_caps & EMMC_MODE_8BIT_DDR)
261 + boot_bus_width = EXT_CSD_BOOT_BUS_WIDTH_DDR |
262 + EXT_CSD_BOOT_BUS_WIDTH_8BIT;
263 + else if (mmc->host_caps & EMMC_MODE_4BIT_DDR)
264 + boot_bus_width = EXT_CSD_BOOT_BUS_WIDTH_DDR |
265 + EXT_CSD_BOOT_BUS_WIDTH_4BIT;
266 + else if (mmc->host_caps & MMC_MODE_8BIT)
267 + boot_bus_width = EXT_CSD_BOOT_BUS_WIDTH_8BIT;
268 + else if (mmc->host_caps & MMC_MODE_4BIT)
269 + boot_bus_width = EXT_CSD_BOOT_BUS_WIDTH_4BIT;
271 + boot_bus_width = 0;
273 + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
274 + EXT_CSD_BOOT_BUS_WIDTH, boot_bus_width);
276 + /* Ensure that it programmed properly */
277 + err = mmc_send_ext_csd(mmc, ext_csd);
279 + puts("\nWarning: fail to get ext csd for MMC!\n");
283 + card_boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
284 + if (card_boot_bus_width != boot_bus_width) {
285 + printf("\nWarning: current boot_bus_width, 0x%x, is "
286 + "not same as requested boot_bus_width 0x%x!\n",
287 + card_boot_bus_width, boot_bus_width);
293 /* Seems everything is ok, return the partition id before switch */
296 @@ -1023,6 +1098,32 @@ static int mmc_startup(struct mmc *mmc)
297 mmc_set_bus_width(mmc, 8);
300 +#ifdef CONFIG_EMMC_DDR_MODE
302 + if (mmc->card_caps & EMMC_MODE_8BIT_DDR) {
303 + /* Set the card to use 8 bit DDR mode */
304 + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
306 + EXT_CSD_BUS_WIDTH_8_DDR);
311 + /* Setup the host controller for DDR mode */
312 + mmc_set_bus_width(mmc, EMMC_MODE_8BIT_DDR);
313 + } else if (mmc->card_caps & EMMC_MODE_4BIT_DDR) {
314 + /* Set the card to use 4 bit DDR mode */
315 + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
317 + EXT_CSD_BUS_WIDTH_4_DDR);
321 + /* Setup the host controller for DDR mode */
322 + mmc_set_bus_width(mmc, EMMC_MODE_4BIT_DDR);
326 if (mmc->card_caps & MMC_MODE_HS) {
327 if (mmc->card_caps & MMC_MODE_HS_52MHz)
328 mmc_set_clock(mmc, 52000000);
329 diff --git a/include/configs/mx50_arm2.h b/include/configs/mx50_arm2.h
330 index fbede97..4c23b95 100644
331 --- a/include/configs/mx50_arm2.h
332 +++ b/include/configs/mx50_arm2.h
333 @@ -201,10 +201,14 @@
334 #define CONFIG_CMD_FAT 1
335 #define CONFIG_CMD_EXT2 1
337 - /* detect whether ESDHC1 or ESDHC3 is boot device */
338 + /* detect whether ESDHC1, ESDHC2, or ESDHC3 is boot device */
339 #define CONFIG_DYNAMIC_MMC_DEVNO
341 #define CONFIG_BOOT_PARTITION_ACCESS
342 + #define CONFIG_EMMC_DDR_MODE
344 + /* Indicate to esdhc driver which ports support 8-bit data */
345 + #define CONFIG_MMC_8BIT_PORTS 0x6 /* ports 1 and 2 */
348 /*-----------------------------------------------------------------------
349 diff --git a/include/configs/mx50_arm2_lpddr2.h b/include/configs/mx50_arm2_lpddr2.h
350 index 505b859..a5683ad 100644
351 --- a/include/configs/mx50_arm2_lpddr2.h
352 +++ b/include/configs/mx50_arm2_lpddr2.h
353 @@ -202,10 +202,15 @@
354 #define CONFIG_CMD_FAT 1
355 #define CONFIG_CMD_EXT2 1
357 - /* detect whether ESDHC1 or ESDHC3 is boot device */
358 + /* detect whether ESDHC1, ESDHC2, or ESDHC3 is boot device */
359 #define CONFIG_DYNAMIC_MMC_DEVNO
361 #define CONFIG_BOOT_PARTITION_ACCESS
362 + #define CONFIG_EMMC_DDR_MODE
364 + /* Indicate to esdhc driver which ports support 8-bit data */
365 + #define CONFIG_MMC_8BIT_PORTS 0x6 /* ports 1 and 2 */
369 /*-----------------------------------------------------------------------
370 diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h
371 index 9f48afe..a0b1f5c 100644
372 --- a/include/fsl_esdhc.h
373 +++ b/include/fsl_esdhc.h
375 #define XFERTYP_RSPTYP_48_BUSY 0x00030000
376 #define XFERTYP_MSBSEL 0x00000020
377 #define XFERTYP_DTDSEL 0x00000010
378 +#define XFERTYP_DDR_EN 0x00000008
379 #define XFERTYP_AC12EN 0x00000004
380 #define XFERTYP_BCEN 0x00000002
381 #define XFERTYP_DMAEN 0x00000001
383 #define ESDHC_HOSTCAPBLT_DMAS 0x00400000
384 #define ESDHC_HOSTCAPBLT_HSS 0x00200000
386 +#define ESDHC_HOSTVER_VVN_MASK 0x0000ff00
387 +#define ESDHC_HOSTVER_VVN_SHIFT 8
388 +#define ESDHC_HOSTVER_DDR_SUPPORT 0x13
390 +#define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL 12
391 +#define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK 0x0000FC00
392 +#define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_SHIFT 10
393 +#define ESDHC_DLLCTRL_SLV_OVERRIDE 0x200
395 struct fsl_esdhc_cfg {
398 diff --git a/include/mmc.h b/include/mmc.h
399 index b8d6871..b450f4f 100644
403 #define MMC_MODE_HS_52MHz 0x010
404 #define MMC_MODE_4BIT 0x100
405 #define MMC_MODE_8BIT 0x200
406 +#define EMMC_MODE_4BIT_DDR 0x400
407 +#define EMMC_MODE_8BIT_DDR 0x800
409 #define SD_DATA_4BIT 0x00040000
413 #define MMC_HS_TIMING 0x00000100
414 #define MMC_HS_52MHZ 0x2
416 +#define EMMC_MODE_DDR_3V 0x4
417 #define OCR_BUSY 0x80000000
418 #define OCR_HCS 0x40000000
424 +#define EXT_CSD_BOOT_BUS_WIDTH 177 /* RW */
425 #define EXT_CSD_BOOT_CONFIG 179 /* RW */
426 #define EXT_CSD_BUS_WIDTH 183 /* R/W */
427 #define EXT_CSD_HS_TIMING 185 /* R/W */
429 #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
430 #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
431 #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
432 +#define EXT_CSD_BUS_WIDTH_4_DDR 5 /* eMMC 4.4 in 4-bit DDR mode */
433 +#define EXT_CSD_BUS_WIDTH_8_DDR 6 /* eMMC 4.4 in 8-bit DDR mode */
435 +#define EXT_CSD_BOOT_BUS_WIDTH_1BIT 0
436 +#define EXT_CSD_BOOT_BUS_WIDTH_4BIT 1
437 +#define EXT_CSD_BOOT_BUS_WIDTH_8BIT 2
438 +#define EXT_CSD_BOOT_BUS_WIDTH_DDR (1 << 4)
440 #define EXT_CSD_BOOT_PARTITION_ENABLE_MASK (0x7 << 3)
441 #define EXT_CSD_BOOT_PARTITION_DISABLE (0x0)