diff options
| -rw-r--r-- | common/cmd_mmc.c | 38 | ||||
| -rw-r--r-- | drivers/mmc/mmc.c | 30 | ||||
| -rw-r--r-- | include/mmc.h | 8 | 
3 files changed, 71 insertions, 5 deletions
| diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index e266d4fa4..176646d46 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -164,6 +164,7 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  			return 1;  		} +		mmc->has_init = 0;  		mmc_init(mmc);  		return 0; @@ -189,14 +190,22 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		print_mmc_devices('\n');  		return 0;  	} else if (strcmp(argv[1], "dev") == 0) { -		int dev; +		int dev, part = -1;  		struct mmc *mmc;  		if (argc == 2)  			dev = curr_device;  		else if (argc == 3)  			dev = simple_strtoul(argv[2], NULL, 10); -		else +		else if (argc == 4) { +			dev = (int)simple_strtoul(argv[2], NULL, 10); +			part = (int)simple_strtoul(argv[3], NULL, 10); +			if (part > PART_ACCESS_MASK) { +				printf("#part_num shouldn't be larger" +					" than %d\n", PART_ACCESS_MASK); +				return 1; +			} +		} else  			return cmd_usage(cmdtp);  		mmc = find_mmc_device(dev); @@ -205,8 +214,29 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  			return 1;  		} +		mmc_init(mmc); +		if (part != -1) { +			int ret; +			if (mmc->part_config == MMCPART_NOAVAILABLE) { +				printf("Card doesn't support part_switch\n"); +				return 1; +			} + +			if (part != mmc->part_num) { +				ret = mmc_switch_part(dev, part); +				if (!ret) +					mmc->part_num = part; + +				printf("switch to partions #%d, %s\n", +						part, (!ret) ? "OK" : "ERROR"); +			} +		}  		curr_device = dev; -		printf("mmc%d is current device\n", curr_device); +		if (mmc->part_config == MMCPART_NOAVAILABLE) +			printf("mmc%d is current device\n", curr_device); +		else +			printf("mmc%d(part %d) is current device\n", +				curr_device, mmc->part_num);  		return 0;  	} else if (strcmp(argv[1], "read") == 0) { @@ -269,6 +299,6 @@ U_BOOT_CMD(  	"mmc write addr blk# cnt\n"  	"mmc rescan\n"  	"mmc part - lists available partition on current mmc device\n" -	"mmc dev [dev] - show or set current mmc device\n" +	"mmc dev [dev] [part] - show or set current mmc device [partition]\n"  	"mmc list - lists available devices");  #endif diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index cdf2713ba..1d089a7d1 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -577,6 +577,18 @@ int mmc_change_freq(struct mmc *mmc)  	return 0;  } +int mmc_switch_part(int dev_num, unsigned int part_num) +{ +	struct mmc *mmc = find_mmc_device(dev_num); + +	if (!mmc) +		return -1; + +	return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, +			  (mmc->part_config & ~PART_ACCESS_MASK) +			  | (part_num & PART_ACCESS_MASK)); +} +  int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)  {  	struct mmc_cmd cmd; @@ -899,6 +911,7 @@ int mmc_startup(struct mmc *mmc)  			return err;  	} +	mmc->part_config = MMCPART_NOAVAILABLE;  	if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {  		/* check  ext_csd version and capacity */  		err = mmc_send_ext_csd(mmc, ext_csd); @@ -907,6 +920,10 @@ int mmc_startup(struct mmc *mmc)  					ext_csd[214] << 16 | ext_csd[215] << 24;  			mmc->capacity *= 512;  		} + +		/* store the partition info of emmc */ +		if (ext_csd[160] & PART_SUPPORT) +			mmc->part_config = ext_csd[179];  	}  	if (IS_SD(mmc)) @@ -1048,6 +1065,9 @@ int mmc_init(struct mmc *mmc)  {  	int err; +	if (mmc->has_init) +		return 0; +  	err = mmc->init(mmc);  	if (err) @@ -1062,6 +1082,9 @@ int mmc_init(struct mmc *mmc)  	if (err)  		return err; +	/* The internal partition reset to user partition(0) at every CMD0*/ +	mmc->part_num = 0; +  	/* Test for SD version 2 */  	err = mmc_send_if_cond(mmc); @@ -1078,7 +1101,12 @@ int mmc_init(struct mmc *mmc)  		}  	} -	return mmc_startup(mmc); +	err = mmc_startup(mmc); +	if (err) +		mmc->has_init = 0; +	else +		mmc->has_init = 1; +	return err;  }  /* diff --git a/include/mmc.h b/include/mmc.h index 5501f5547..aeacdee30 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -138,6 +138,7 @@   * EXT_CSD fields   */ +#define EXT_CSD_PART_CONF	179	/* R/W */  #define EXT_CSD_BUS_WIDTH	183	/* R/W */  #define EXT_CSD_HS_TIMING	185	/* R/W */  #define EXT_CSD_CARD_TYPE	196	/* RO */ @@ -179,6 +180,9 @@  #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) +#define MMCPART_NOAVAILABLE	(0xff) +#define PART_ACCESS_MASK	(0x7) +#define PART_SUPPORT		(0x1)  struct mmc_cid {  	unsigned long psn; @@ -263,6 +267,7 @@ struct mmc {  	void *priv;  	uint voltages;  	uint version; +	uint has_init;  	uint f_min;  	uint f_max;  	int high_capacity; @@ -275,6 +280,8 @@ struct mmc {  	uint csd[4];  	uint cid[4];  	ushort rca; +	char part_config; +	char part_num;  	uint tran_speed;  	uint read_bl_len;  	uint write_bl_len; @@ -297,6 +304,7 @@ int mmc_set_dev(int dev_num);  void print_mmc_devices(char separator);  int get_mmc_num(void);  int board_mmc_getcd(u8 *cd, struct mmc *mmc); +int mmc_switch_part(int dev_num, unsigned int part_num);  #ifdef CONFIG_GENERIC_MMC  int atmel_mci_init(void *regs); |