1 From 8bab684efeed6ae55e43df47298578c31b251af3 Mon Sep 17 00:00:00 2001
2 From: Terry Lv <r65388@freescale.com>
3 Date: Sat, 6 Feb 2010 18:19:39 +0800
4 Subject: [PATCH] ENGR00120830: Add eMMC and eSD fast boot support
6 Add eMMC and eSD fast boot support.
8 Signed-off-by: Terry Lv <r65388@freescale.com>
9 Signed-off-by: Brian Liu <b14843@freescale.com>
11 common/cmd_mmc.c | 131 +++++++++++++++++++++++++++++++++++++-
12 drivers/mmc/mmc.c | 151 +++++++++++++++++++++++++++++++++++++++++++-
13 include/configs/mx51_bbg.h | 33 +---------
14 include/mmc.h | 26 +++++++-
15 4 files changed, 307 insertions(+), 34 deletions(-)
17 diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
18 index 421482e..b8d494b 100644
19 --- a/common/cmd_mmc.c
20 +++ b/common/cmd_mmc.c
21 @@ -112,6 +112,48 @@ static void print_mmcinfo(struct mmc *mmc)
22 printf("Capacity: %lld\n", mmc->capacity);
24 printf("Bus Width: %d-bit\n", mmc->bus_width);
25 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
26 + if (mmc->boot_size_mult == 0) {
27 + printf("Boot Partition Size: %s\n", "No boot partition available");
29 + printf("Boot Partition Size: %5dKB\n", mmc->boot_size_mult * 128);
31 + printf("Current Partition for boot: ");
32 + switch (mmc->boot_config & EXT_CSD_BOOT_PARTITION_ENABLE_MASK) {
33 + case EXT_CSD_BOOT_PARTITION_DISABLE:
34 + printf("Not bootable\n");
36 + case EXT_CSD_BOOT_PARTITION_PART1:
37 + printf("Boot partition 1\n");
39 + case EXT_CSD_BOOT_PARTITION_PART2:
40 + printf("Boot partition 2\n");
42 + case EXT_CSD_BOOT_PARTITION_USER:
43 + printf("User area\n");
46 + printf("Unknown\n");
50 + printf("Current Partition for read/write: ");
51 + switch (mmc->boot_config & EXT_CSD_BOOT_PARTITION_ACCESS_MASK) {
52 + case EXT_CSD_BOOT_PARTITION_ACCESS_DISABLE:
53 + printf("User Area\n");
55 + case EXT_CSD_BOOT_PARTITION_ACCESS_PART1:
56 + printf("Boot partition 1\n");
58 + case EXT_CSD_BOOT_PARTITION_ACCESS_PART2:
59 + printf("Boot partition 2\n");
62 + printf("Unknown\n");
69 int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
70 @@ -144,6 +186,9 @@ U_BOOT_CMD(mmcinfo, 2, 0, do_mmcinfo,
71 int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
74 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
80 @@ -171,6 +216,10 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
84 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
85 + case 6: /* Fall through */
86 + part = simple_strtoul(argv[6], NULL, 10);
88 default: /* at least 5 args */
89 if (strcmp(argv[1], "read") == 0) {
90 int dev = simple_strtoul(argv[2], NULL, 10);
91 @@ -178,6 +227,7 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
92 u32 cnt = simple_strtoul(argv[5], NULL, 16);
94 u32 blk = simple_strtoul(argv[4], NULL, 16);
96 struct mmc *mmc = find_mmc_device(dev);
99 @@ -188,11 +238,44 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
103 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
104 + /* After mmc_init, we now know whether this is a eSD/eMMC which support boot partition */
107 + if (sd_switch_partition(mmc, 1) < 0) {
108 + printf("\nError: Fail to switch partition to %d before reading\n", 1);
112 + if (mmc_switch_partition(mmc, part) < 0) {
113 + printf("\nError: Fail to switch partition to %d before reading\n", part);
120 n = mmc->block_dev.block_read(dev, blk, cnt, addr);
122 /* flush cache after read */
123 flush_cache((ulong)addr, cnt * 512); /* FIXME */
125 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
129 + if (sd_switch_partition(mmc, 0) < 0) {
130 + printf("\nError: Fail to switch partition back!\n");
134 + if (mmc_switch_partition(mmc, 0) < 0) {
135 + printf("\nError: Fail to switch partition back!\n");
141 printf("%d blocks read: %s\n",
142 n, (n==cnt) ? "OK" : "ERROR");
143 return (n == cnt) ? 0 : 1;
144 @@ -201,6 +284,7 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
145 void *addr = (void *)simple_strtoul(argv[3], NULL, 16);
146 u32 cnt = simple_strtoul(argv[5], NULL, 16);
149 struct mmc *mmc = find_mmc_device(dev);
151 int blk = simple_strtoul(argv[4], NULL, 16);
152 @@ -213,8 +297,42 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
156 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
157 + /* After mmc_init, we now know whether this is a eSD/eMMC which support boot partition */
160 + if (sd_switch_partition(mmc, 1) < 0) {
161 + printf("\nError: Fail to switch partition to %d before writing\n", 1);
165 + if (mmc_switch_partition(mmc, part) < 0) {
166 + printf("\nError: Fail to switch partition to %d before writing\n", part);
173 n = mmc->block_dev.block_write(dev, blk, cnt, addr);
175 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
179 + if (sd_switch_partition(mmc, 0) < 0) {
180 + printf("\nError: Fail to switch partition back!\n");
184 + if (mmc_switch_partition(mmc, 0) < 0) {
185 + printf("\nError: Fail to switch partition back!\n");
192 printf("%d blocks written: %s\n",
193 n, (n == cnt) ? "OK" : "ERROR");
194 return (n == cnt) ? 0 : 1;
195 @@ -227,11 +345,22 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
199 +#ifndef CONFIG_BOOT_PARTITION_ACCESS
201 mmc, 6, 1, do_mmcops,
203 - "read <device num> addr blk# cnt\n"
204 + "mmc read <device num> addr blk# cnt\n"
205 "mmc write <device num> addr blk# cnt\n"
206 "mmc rescan <device num>\n"
207 "mmc list - lists available devices");
210 + mmc, 7, 1, do_mmcops,
212 + "mmc read <device num> addr blk# cnt [partition]\n"
213 + "mmc write <device num> addr blk# cnt [partition]\n"
214 + "mmc rescan <device num>\n"
215 + "mmc list - lists available devices");
219 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
220 index f78b8a8..422c6ed 100644
221 --- a/drivers/mmc/mmc.c
222 +++ b/drivers/mmc/mmc.c
225 - * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
226 + * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
229 * Copyright 2008, Freescale Semiconductor, Inc
230 @@ -646,6 +646,149 @@ void mmc_set_bus_width(struct mmc *mmc, uint width)
234 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
235 +/* Return 0/1/2 for partition id before switch; Return -1 if fail to switch */
236 +int mmc_switch_partition(struct mmc *mmc, uint part)
240 + uint old_part, new_part;
243 + /* partition must be -
245 + 1 - boot partition 1
246 + 2 - boot partition 2
249 + printf("\nWrong partition id - 0 (user area), 1 (boot1), 2 (boot2)\n");
253 + /* Before calling this func, "mmc" struct must have been initialized */
254 + if (mmc->version < MMC_VERSION_4) {
255 + puts("Error: invalid mmc version! mmc version is below version 4!");
259 + if (mmc->boot_size_mult <= 0) {
260 + /* it's a normal SD/MMC but user request to boot partition */
261 + printf("\nError: This is a normal SD/MMC card but you request to access boot partition\n");
265 + /* part must be 0 (user area), 1 (boot partition1) or 2 (boot partition2) */
267 + puts("Error: partition id must be 0(user area), 1(boot partition1) or 2(boot partition2)\n");
272 + /* eSD card hadn't been supported. Return directly without warning */
276 + ext_csd = (char *)malloc(512);
278 + puts("Error: Could not allocate buffer for MMC ext csd!\n");
282 + err = mmc_send_ext_csd(mmc, ext_csd);
284 + puts("Warning: fail to get ext csd for MMC!\n");
288 + old_part = ext_csd[EXT_CSD_BOOT_CONFIG] & EXT_CSD_BOOT_PARTITION_ACCESS_MASK;
290 + /* Send SWITCH command to change partition for access */
291 + boot_config = (ext_csd[EXT_CSD_BOOT_CONFIG] & ~EXT_CSD_BOOT_PARTITION_ACCESS_MASK) | (char)part;
293 + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_CONFIG, boot_config);
295 + puts("Error: fail to send SWITCH command to card to swich partition for access!\n");
299 + /* Now check whether it works */
300 + err = mmc_send_ext_csd(mmc, ext_csd);
302 + puts("Warning: fail to get ext csd for MMC!\n");
306 + new_part = ext_csd[EXT_CSD_BOOT_CONFIG] & EXT_CSD_BOOT_PARTITION_ACCESS_MASK;
307 + if ((char)part != new_part) {
308 + printf("Warning: after SWITCH, current part id %d is not same as requested partition %d!\n",
313 + /* Seems everything is ok, return the partition id before switch */
322 +int sd_switch_partition(struct mmc *mmc, uint part)
324 + struct mmc_cmd cmd;
328 + printf("\nWrong partition id - 0 (user area), 1 (boot1)\n");
332 + cmd.cmdidx = SD_CMD_SELECT_PARTITION;
333 + cmd.resp_type = MMC_RSP_R1;
334 + cmd.cmdarg = part << 24;
337 + err = mmc_send_cmd(mmc, &cmd, NULL);
340 + printf("Failed to switch to partition %d\nPartition not exists or command execute fail!\n");
347 +int mmc_get_cur_boot_partition(struct mmc *mmc)
352 + ext_csd = (char *)malloc(512);
355 + puts("Error! Could not allocate buffer for MMC ext csd!\n");
359 + err = mmc_send_ext_csd(mmc, ext_csd);
362 + mmc->boot_config = 0;
363 + mmc->boot_size_mult = 0;
364 + /* continue since it's not a fatal error */
366 + mmc->boot_config = ext_csd[EXT_CSD_BOOT_CONFIG];
367 + mmc->boot_size_mult = ext_csd[EXT_CSD_BOOT_INFO];
377 int mmc_startup(struct mmc *mmc)
380 @@ -819,6 +962,7 @@ int mmc_startup(struct mmc *mmc)
381 mmc_set_clock(mmc, 50000000);
383 mmc_set_clock(mmc, 25000000);
386 if (mmc->card_caps & MMC_MODE_4BIT) {
387 /* Set the card to use 4 bit*/
388 @@ -849,6 +993,10 @@ int mmc_startup(struct mmc *mmc)
389 mmc_set_clock(mmc, 26000000);
391 mmc_set_clock(mmc, 20000000);
393 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
394 + mmc_get_cur_boot_partition(mmc);
398 /* fill in device description */
399 @@ -1009,3 +1157,4 @@ int mmc_initialize(bd_t *bis)
404 diff --git a/include/configs/mx51_bbg.h b/include/configs/mx51_bbg.h
405 index f773563..b2961a2 100644
406 --- a/include/configs/mx51_bbg.h
407 +++ b/include/configs/mx51_bbg.h
409 #define CONFIG_MX51_UART 1
410 #define CONFIG_MX51_UART1 1
415 -#define CONFIG_FSL_SF 1
416 -#define CONFIG_SPI_FLASH_IMX_ATMEL 1
417 -#define CONFIG_SPI_FLASH_CS 1
418 -#define CONFIG_IMX_ECSPI
419 -#define CONFIG_IMX_SPI_PMIC
420 -#define CONFIG_IMX_SPI_PMIC_CS 0
421 -#define IMX_CSPI_VER_2_3 1
422 -#define MAX_SPI_BYTES (64 * 4)
431 -#define CONFIG_HAS_ETH1
432 -#define CONFIG_NET_MULTI 1
433 -#define CONFIG_MXC_FEC
435 -#define CONFIG_DISCOVER_PHY
437 -#define CONFIG_FEC0_IOBASE FEC_BASE_ADDR
438 -#define CONFIG_FEC0_PINMUX -1
439 -#define CONFIG_FEC0_PHY_ADDR 0x1F
440 -#define CONFIG_FEC0_MIIBASE -1
442 /* allow to overwrite serial and ethaddr */
443 #define CONFIG_ENV_OVERWRITE
444 #define CONFIG_CONS_INDEX 1
446 #define CONFIG_FSL_SF 1
447 #define CONFIG_SPI_FLASH_IMX_ATMEL 1
448 #define CONFIG_SPI_FLASH_CS 1
449 - #define CONFIG_IMX_SPI
450 + #define CONFIG_IMX_ECSPI
451 + #define IMX_CSPI_VER_2_3 1
452 #define CONFIG_IMX_SPI_PMIC
453 #define CONFIG_IMX_SPI_PMIC_CS 0
455 diff --git a/include/mmc.h b/include/mmc.h
456 index 2dc69ab..fe63ed7 100644
461 - * Copyright 2008, Freescale Semiconductor, Inc
462 + * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
464 + * Copyright 2008-2010, Freescale Semiconductor, Inc
467 * Based (loosely) on the Linux code
469 #define SD_CMD_SEND_RELATIVE_ADDR 3
470 #define SD_CMD_SWITCH_FUNC 6
471 #define SD_CMD_SEND_IF_COND 8
472 +#define SD_CMD_SELECT_PARTITION 43
474 #define SD_CMD_APP_SET_BUS_WIDTH 6
475 #define SD_CMD_APP_SEND_OP_COND 41
476 @@ -128,11 +131,13 @@
480 +#define EXT_CSD_BOOT_CONFIG 179 /* RW */
481 #define EXT_CSD_BUS_WIDTH 183 /* R/W */
482 #define EXT_CSD_HS_TIMING 185 /* R/W */
483 #define EXT_CSD_CARD_TYPE 196 /* RO */
484 #define EXT_CSD_REV 192 /* RO */
485 #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
486 +#define EXT_CSD_BOOT_INFO 228 /* RO */
489 * EXT_CSD field definitions
491 #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
492 #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
494 +#define EXT_CSD_BOOT_PARTITION_ENABLE_MASK (0x7 << 3)
495 +#define EXT_CSD_BOOT_PARTITION_DISABLE (0x0)
496 +#define EXT_CSD_BOOT_PARTITION_PART1 (0x1 << 3)
497 +#define EXT_CSD_BOOT_PARTITION_PART2 (0x2 << 3)
498 +#define EXT_CSD_BOOT_PARTITION_USER (0x7 << 3)
500 +#define EXT_CSD_BOOT_PARTITION_ACCESS_MASK (0x7)
501 +#define EXT_CSD_BOOT_PARTITION_ACCESS_DISABLE (0x0)
502 +#define EXT_CSD_BOOT_PARTITION_ACCESS_PART1 (0x1)
503 +#define EXT_CSD_BOOT_PARTITION_ACCESS_PART2 (0x2)
505 #define R1_ILLEGAL_COMMAND (1 << 22)
506 #define R1_APP_CMD (1 << 5)
508 @@ -259,6 +275,10 @@ struct mmc {
512 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
514 + uint boot_size_mult;
516 block_dev_desc_t block_dev;
517 int (*send_cmd)(struct mmc *mmc,
518 struct mmc_cmd *cmd, struct mmc_data *data);
519 @@ -272,6 +292,10 @@ int mmc_init(struct mmc *mmc);
520 int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
521 struct mmc *find_mmc_device(int dev_num);
522 void print_mmc_devices(char separator);
523 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
524 +int mmc_switch_partition(struct mmc *mmc, uint part);
525 +int sd_switch_partition(struct mmc *mmc, uint part);
528 #ifndef CONFIG_GENERIC_MMC
529 int mmc_legacy_init(int verbose);