From 3bd50a46e4453ca2492169e7add9cde0752442e2 Mon Sep 17 00:00:00 2001 From: Anish Trivedi Date: Tue, 15 Jun 2010 18:01:10 -0500 Subject: ENGR00123782 Fix boot partition problem for emmc Enable boot partition in BOOT_CONFIG byte of EXT_CSD Signed-off-by: Anish Trivedi --- common/cmd_mmc.c | 136 +++++++++++++++++++------------------------- drivers/mmc/mmc.c | 118 +++++++++++++++++++++----------------- include/configs/mx53_arm2.h | 2 + include/configs/mx53_evk.h | 2 + include/mmc.h | 5 +- 5 files changed, 129 insertions(+), 134 deletions(-) diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index cd7d16f..29cae1b 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -93,6 +93,29 @@ U_BOOT_CMD( ); #else /* !CONFIG_GENERIC_MMC */ +#ifdef CONFIG_BOOT_PARTITION_ACCESS +#define MMC_PARTITION_SWITCH(mmc, part, enable_boot) \ + do { \ + if (IS_SD(mmc)) { \ + if (part > 1) {\ + printf( \ + "\nError: SD partition can only be 0 or 1\n");\ + return 1; \ + } \ + if (sd_switch_partition(mmc, part) < 0) { \ + return 1; \ + } \ + } else { \ + if (mmc_switch_partition(mmc, part, enable_boot) \ + < 0) { \ + printf("Error: Fail to switch " \ + "partition to %d\n", part); \ + return 1; \ + } \ + } \ + } while (0) +#endif + static void print_mmcinfo(struct mmc *mmc) { printf("Device: %s\n", mmc->name); @@ -136,22 +159,6 @@ static void print_mmcinfo(struct mmc *mmc) printf("Unknown\n"); break; } - - printf("Current Partition for read/write: "); - switch (mmc->boot_config & EXT_CSD_BOOT_PARTITION_ACCESS_MASK) { - case EXT_CSD_BOOT_PARTITION_ACCESS_DISABLE: - printf("User Area\n"); - break; - case EXT_CSD_BOOT_PARTITION_ACCESS_PART1: - printf("Boot partition 1\n"); - break; - case EXT_CSD_BOOT_PARTITION_ACCESS_PART2: - printf("Boot partition 2\n"); - break; - default: - printf("Unknown\n"); - break; - } } #endif } @@ -217,7 +224,7 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } return 1; #ifdef CONFIG_BOOT_PARTITION_ACCESS - case 6: /* Fall through */ + case 7: /* Fall through */ part = simple_strtoul(argv[6], NULL, 10); #endif default: /* at least 5 args */ @@ -233,25 +240,27 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (!mmc) return 1; - printf("\nMMC read: dev # %d, block # %d, count %d ... ", - dev, blk, cnt); +#ifdef CONFIG_BOOT_PARTITION_ACCESS + printf("\nMMC read: dev # %d, block # %d, " + "count %d partition # %d ... \n", + dev, blk, cnt, part); +#else + printf("\nMMC read: dev # %d, block # %d," + "count %d ... \n", dev, blk, cnt); +#endif mmc_init(mmc); #ifdef CONFIG_BOOT_PARTITION_ACCESS - /* After mmc_init, we now know whether this is a eSD/eMMC which support boot partition */ - if (part > 0) { - if (IS_SD(mmc)) { - if (sd_switch_partition(mmc, 1) < 0) { - printf("\nError: Fail to switch partition to %d before reading\n", 1); - return 1; - } - } else { - if (mmc_switch_partition(mmc, part) < 0) { - printf("\nError: Fail to switch partition to %d before reading\n", part); - return 1; - } - } + if (((mmc->boot_config & + EXT_CSD_BOOT_PARTITION_ACCESS_MASK) != part) + || IS_SD(mmc)) { + /* + * After mmc_init, we now know whether + * this is a eSD/eMMC which support boot + * partition + */ + MMC_PARTITION_SWITCH(mmc, part, 0); } #endif @@ -260,22 +269,6 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) /* flush cache after read */ flush_cache((ulong)addr, cnt * 512); /* FIXME */ -#ifdef CONFIG_BOOT_PARTITION_ACCESS - /* Switch back */ - if (part > 0) { - if (IS_SD(mmc)) { - if (sd_switch_partition(mmc, 0) < 0) { - printf("\nError: Fail to switch partition back!\n"); - return 1; - } - } else { - if (mmc_switch_partition(mmc, 0) < 0) { - printf("\nError: Fail to switch partition back!\n"); - return 1; - } - } - } -#endif printf("%d blocks read: %s\n", n, (n==cnt) ? "OK" : "ERROR"); return (n == cnt) ? 0 : 1; @@ -292,47 +285,32 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (!mmc) return 1; - printf("\nMMC write: dev # %d, block # %d, count %d ... ", +#ifdef CONFIG_BOOT_PARTITION_ACCESS + printf("\nMMC write: dev # %d, block # %d, " + "count %d, partition # %d ... \n", + dev, blk, cnt, part); +#else + printf("\nMMC write: dev # %d, block # %d, " + "count %d ... \n", dev, blk, cnt); +#endif mmc_init(mmc); #ifdef CONFIG_BOOT_PARTITION_ACCESS - /* After mmc_init, we now know whether this is a eSD/eMMC which support boot partition */ - if (part > 0) { - if (IS_SD(mmc)) { - if (sd_switch_partition(mmc, 1) < 0) { - printf("\nError: Fail to switch partition to %d before writing\n", 1); - return 1; - } - } else { - if (mmc_switch_partition(mmc, part) < 0) { - printf("\nError: Fail to switch partition to %d before writing\n", part); - return 1; - } - } + if (((mmc->boot_config & + EXT_CSD_BOOT_PARTITION_ACCESS_MASK) != part) + || IS_SD(mmc)) { + /* + * After mmc_init, we now know whether this is a + * eSD/eMMC which support boot partition + */ + MMC_PARTITION_SWITCH(mmc, part, 1); } #endif n = mmc->block_dev.block_write(dev, blk, cnt, addr); -#ifdef CONFIG_BOOT_PARTITION_ACCESS - /* Switch back */ - if (part > 0) { - if (IS_SD(mmc)) { - if (sd_switch_partition(mmc, 0) < 0) { - printf("\nError: Fail to switch partition back!\n"); - return 1; - } - } else { - if (mmc_switch_partition(mmc, 0) < 0) { - printf("\nError: Fail to switch partition back!\n"); - return 1; - } - } - } -#endif - printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); return (n == cnt) ? 0 : 1; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 2f774ee..072ef46 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -40,12 +40,13 @@ static struct list_head mmc_devices; static int cur_dev_num = -1; -int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) +static int mmc_send_cmd(struct mmc *mmc, + struct mmc_cmd *cmd, struct mmc_data *data) { return mmc->send_cmd(mmc, cmd, data); } -int mmc_set_blocklen(struct mmc *mmc, int len) +static int mmc_set_blocklen(struct mmc *mmc, int len) { struct mmc_cmd cmd; @@ -140,7 +141,7 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src) return blkcnt; } -int mmc_read_block(struct mmc *mmc, void *dst, uint blocknum) +static int mmc_read_block(struct mmc *mmc, void *dst, uint blocknum) { struct mmc_cmd cmd; struct mmc_data data; @@ -279,7 +280,9 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst) return blkcnt; } -int mmc_go_idle(struct mmc* mmc) +#define CARD_STATE(r) ((u32)((r) & 0x1e00) >> 9) + +static int mmc_go_idle(struct mmc *mmc) { struct mmc_cmd cmd; int err; @@ -301,7 +304,7 @@ int mmc_go_idle(struct mmc* mmc) return 0; } -int +static int sd_send_op_cond(struct mmc *mmc) { int timeout = 1000; @@ -356,7 +359,7 @@ sd_send_op_cond(struct mmc *mmc) return 0; } -int mmc_send_op_cond(struct mmc *mmc) +static int mmc_send_op_cond(struct mmc *mmc) { int timeout = 1000; struct mmc_cmd cmd; @@ -392,7 +395,7 @@ int mmc_send_op_cond(struct mmc *mmc) } -int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd) +static int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd) { struct mmc_cmd cmd; struct mmc_data data; @@ -415,7 +418,7 @@ int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd) } -int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) +static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) { struct mmc_cmd cmd; @@ -429,7 +432,7 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) return mmc_send_cmd(mmc, &cmd, NULL); } -int mmc_change_freq(struct mmc *mmc) +static int mmc_change_freq(struct mmc *mmc) { char *ext_csd; char cardtype; @@ -455,13 +458,13 @@ int mmc_change_freq(struct mmc *mmc) if (err) goto err_rtn; -/* - if (ext_csd[EXT_CSD_SEC_CNT] || - ext_csd[EXT_CSD_SEC_CNT + 1] || - ext_csd[EXT_CSD_SEC_CNT + 2] || - ext_csd[EXT_CSD_SEC_CNT + 3]) - mmc->high_capacity = 1; -*/ + if (mmc->high_capacity) { + mmc->capacity = ext_csd[EXT_CSD_SEC_CNT + 3] << 24 | + ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | + ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | + ext_csd[EXT_CSD_SEC_CNT]; + mmc->capacity *= 512; + } cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf; @@ -495,7 +498,7 @@ err_rtn: return err; } -int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) +static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) { struct mmc_cmd cmd; struct mmc_data data; @@ -517,7 +520,7 @@ int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) } -int sd_change_freq(struct mmc *mmc) +static int sd_change_freq(struct mmc *mmc) { int err; struct mmc_cmd cmd; @@ -616,7 +619,7 @@ retry_scr: /* frequency bases */ /* divided by 10 to be nice to platforms without floating point */ -int fbase[] = { +static int fbase[] = { 10000, 100000, 1000000, @@ -626,7 +629,7 @@ int fbase[] = { /* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice * to platforms without floating point. */ -int multipliers[] = { +static int multipliers[] = { 0, /* reserved */ 10, 12, @@ -645,12 +648,12 @@ int multipliers[] = { 80, }; -void mmc_set_ios(struct mmc *mmc) +static void mmc_set_ios(struct mmc *mmc) { mmc->set_ios(mmc); } -void mmc_set_clock(struct mmc *mmc, uint clock) +static void mmc_set_clock(struct mmc *mmc, uint clock) { if (clock > mmc->f_max) clock = mmc->f_max; @@ -663,7 +666,7 @@ void mmc_set_clock(struct mmc *mmc, uint clock) mmc_set_ios(mmc); } -void mmc_set_bus_width(struct mmc *mmc, uint width) +static void mmc_set_bus_width(struct mmc *mmc, uint width) { mmc->bus_width = width; @@ -672,7 +675,7 @@ void mmc_set_bus_width(struct mmc *mmc, uint width) #ifdef CONFIG_BOOT_PARTITION_ACCESS /* Return 0/1/2 for partition id before switch; Return -1 if fail to switch */ -int mmc_switch_partition(struct mmc *mmc, uint part) +int mmc_switch_partition(struct mmc *mmc, uint part, uint enable_boot) { char *ext_csd; int err; @@ -685,66 +688,79 @@ int mmc_switch_partition(struct mmc *mmc, uint part) 2 - boot partition 2 */ if (part > 2) { - printf("\nWrong partition id - 0 (user area), 1 (boot1), 2 (boot2)\n"); + printf("\nWrong partition id - " + "0 (user area), 1 (boot1), 2 (boot2)\n"); return 1; } /* Before calling this func, "mmc" struct must have been initialized */ if (mmc->version < MMC_VERSION_4) { - puts("Error: invalid mmc version! mmc version is below version 4!"); + puts("\nError: invalid mmc version! " + "mmc version is below version 4!"); return -1; } if (mmc->boot_size_mult <= 0) { /* it's a normal SD/MMC but user request to boot partition */ - printf("\nError: This is a normal SD/MMC card but you request to access boot partition\n"); + printf("\nError: This is a normal SD/MMC card but you" + "request to access boot partition\n"); return -1; } - /* part must be 0 (user area), 1 (boot partition1) or 2 (boot partition2) */ + /* + * Part must be 0 (user area), 1 (boot partition1) + * or 2 (boot partition2) + */ if (part > 2) { - puts("Error: partition id must be 0(user area), 1(boot partition1) or 2(boot partition2)\n"); - return -1; - } - - if (IS_SD(mmc)) { - /* eSD card hadn't been supported. Return directly without warning */ + puts("\nError: partition id must be 0(user area), " + "1(boot partition1) or 2(boot partition2)\n"); return -1; } ext_csd = (char *)malloc(512); if (!ext_csd) { - puts("Error: Could not allocate buffer for MMC ext csd!\n"); + puts("\nError: Could not allocate buffer for MMC ext csd!\n"); return -1; } err = mmc_send_ext_csd(mmc, ext_csd); if (err) { - puts("Warning: fail to get ext csd for MMC!\n"); + puts("\nWarning: fail to get ext csd for MMC!\n"); goto err_rtn; - } + } - old_part = ext_csd[EXT_CSD_BOOT_CONFIG] & EXT_CSD_BOOT_PARTITION_ACCESS_MASK; + old_part = ext_csd[EXT_CSD_BOOT_CONFIG] & + EXT_CSD_BOOT_PARTITION_ACCESS_MASK; /* Send SWITCH command to change partition for access */ - boot_config = (ext_csd[EXT_CSD_BOOT_CONFIG] & ~EXT_CSD_BOOT_PARTITION_ACCESS_MASK) | (char)part; + boot_config = (ext_csd[EXT_CSD_BOOT_CONFIG] & + ~EXT_CSD_BOOT_PARTITION_ACCESS_MASK) | + (char)part; + + /* enable access plus boot from that partition and boot_ack bit */ + if (enable_boot != 0) + boot_config = (char)(part) | (char)(part << 3) | (char)(1 << 6); - err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_CONFIG, boot_config); + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BOOT_CONFIG, boot_config); if (err) { - puts("Error: fail to send SWITCH command to card to swich partition for access!\n"); + puts("\nError: fail to send SWITCH command to card " + "to swich partition for access!\n"); goto err_rtn; } /* Now check whether it works */ err = mmc_send_ext_csd(mmc, ext_csd); if (err) { - puts("Warning: fail to get ext csd for MMC!\n"); + puts("\nWarning: fail to get ext csd for MMC!\n"); goto err_rtn; } - new_part = ext_csd[EXT_CSD_BOOT_CONFIG] & EXT_CSD_BOOT_PARTITION_ACCESS_MASK; + new_part = ext_csd[EXT_CSD_BOOT_CONFIG] & + EXT_CSD_BOOT_PARTITION_ACCESS_MASK; if ((char)part != new_part) { - printf("Warning: after SWITCH, current part id %d is not same as requested partition %d!\n", + printf("\nWarning: after SWITCH, current part id %d is " + "not same as requested partition %d!\n", new_part, part); goto err_rtn; } @@ -775,15 +791,13 @@ int sd_switch_partition(struct mmc *mmc, uint part) err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - printf("Failed to switch to partition %d\nPartition not exists or command execute fail!\n"); + if (err) return -1; - } return 0; } -int mmc_get_cur_boot_partition(struct mmc *mmc) +static int mmc_get_cur_boot_partition(struct mmc *mmc) { char *ext_csd; int err; @@ -791,7 +805,7 @@ int mmc_get_cur_boot_partition(struct mmc *mmc) ext_csd = (char *)malloc(512); if (!ext_csd) { - puts("Error! Could not allocate buffer for MMC ext csd!\n"); + puts("\nError! Could not allocate buffer for MMC ext csd!\n"); return -1; } @@ -803,7 +817,7 @@ int mmc_get_cur_boot_partition(struct mmc *mmc) /* continue since it's not a fatal error */ } else { mmc->boot_config = ext_csd[EXT_CSD_BOOT_CONFIG]; - mmc->boot_size_mult = ext_csd[EXT_CSD_BOOT_INFO]; + mmc->boot_size_mult = ext_csd[EXT_CSD_BOOT_SIZE_MULT]; } free(ext_csd); @@ -813,7 +827,7 @@ int mmc_get_cur_boot_partition(struct mmc *mmc) #endif -int mmc_startup(struct mmc *mmc) +static int mmc_startup(struct mmc *mmc) { int err; uint mult, freq; @@ -1039,7 +1053,7 @@ int mmc_startup(struct mmc *mmc) return 0; } -int mmc_send_if_cond(struct mmc *mmc) +static int mmc_send_if_cond(struct mmc *mmc) { struct mmc_cmd cmd; int err; diff --git a/include/configs/mx53_arm2.h b/include/configs/mx53_arm2.h index c28f6d3..0af93c9 100644 --- a/include/configs/mx53_arm2.h +++ b/include/configs/mx53_arm2.h @@ -199,6 +199,8 @@ #define CONFIG_DOS_PARTITION 1 #define CONFIG_CMD_FAT 1 #define CONFIG_CMD_EXT2 1 + + #define CONFIG_BOOT_PARTITION_ACCESS #endif /* diff --git a/include/configs/mx53_evk.h b/include/configs/mx53_evk.h index 4fa66f2..e139840 100644 --- a/include/configs/mx53_evk.h +++ b/include/configs/mx53_evk.h @@ -198,6 +198,8 @@ #define CONFIG_DOS_PARTITION 1 #define CONFIG_CMD_FAT 1 #define CONFIG_CMD_EXT2 1 + + #define CONFIG_BOOT_PARTITION_ACCESS #endif /* diff --git a/include/mmc.h b/include/mmc.h index fe63ed7..b8d6871 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -137,7 +137,7 @@ #define EXT_CSD_CARD_TYPE 196 /* RO */ #define EXT_CSD_REV 192 /* RO */ #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ -#define EXT_CSD_BOOT_INFO 228 /* RO */ +#define EXT_CSD_BOOT_SIZE_MULT 226 /* RO */ /* * EXT_CSD field definitions @@ -185,7 +185,6 @@ #define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) #define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) - struct mmc_cid { unsigned long psn; unsigned short oid; @@ -293,7 +292,7 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size); struct mmc *find_mmc_device(int dev_num); void print_mmc_devices(char separator); #ifdef CONFIG_BOOT_PARTITION_ACCESS -int mmc_switch_partition(struct mmc *mmc, uint part); +int mmc_switch_partition(struct mmc *mmc, uint part, uint enable_boot); int sd_switch_partition(struct mmc *mmc, uint part); #endif -- cgit v1.1