diff options
| -rw-r--r-- | drivers/mmc/mmc.c | 134 | ||||
| -rw-r--r-- | include/mmc.h | 26 | 
2 files changed, 160 insertions, 0 deletions
| diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 2590f1bcc..9c0652d9a 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1374,3 +1374,137 @@ int mmc_initialize(bd_t *bis)  	return 0;  } + +#ifdef CONFIG_SUPPORT_EMMC_BOOT +/* + * This function changes the size of boot partition and the size of rpmb + * partition present on EMMC devices. + * + * Input Parameters: + * struct *mmc: pointer for the mmc device strcuture + * bootsize: size of boot partition + * rpmbsize: size of rpmb partition + * + * Returns 0 on success. + */ + +int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, +				unsigned long rpmbsize) +{ +	int err; +	struct mmc_cmd cmd; + +	/* Only use this command for raw EMMC moviNAND. Enter backdoor mode */ +	cmd.cmdidx = MMC_CMD_RES_MAN; +	cmd.resp_type = MMC_RSP_R1b; +	cmd.cmdarg = MMC_CMD62_ARG1; + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		debug("mmc_boot_partition_size_change: Error1 = %d\n", err); +		return err; +	} + +	/* Boot partition changing mode */ +	cmd.cmdidx = MMC_CMD_RES_MAN; +	cmd.resp_type = MMC_RSP_R1b; +	cmd.cmdarg = MMC_CMD62_ARG2; + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		debug("mmc_boot_partition_size_change: Error2 = %d\n", err); +		return err; +	} +	/* boot partition size is multiple of 128KB */ +	bootsize = (bootsize * 1024) / 128; + +	/* Arg: boot partition size */ +	cmd.cmdidx = MMC_CMD_RES_MAN; +	cmd.resp_type = MMC_RSP_R1b; +	cmd.cmdarg = bootsize; + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		debug("mmc_boot_partition_size_change: Error3 = %d\n", err); +		return err; +	} +	/* RPMB partition size is multiple of 128KB */ +	rpmbsize = (rpmbsize * 1024) / 128; +	/* Arg: RPMB partition size */ +	cmd.cmdidx = MMC_CMD_RES_MAN; +	cmd.resp_type = MMC_RSP_R1b; +	cmd.cmdarg = rpmbsize; + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		debug("mmc_boot_partition_size_change: Error4 = %d\n", err); +		return err; +	} +	return 0; +} + +/* + * This function shall form and send the commands to open / close the + * boot partition specified by user. + * + * Input Parameters: + * ack: 0x0 - No boot acknowledge sent (default) + *	0x1 - Boot acknowledge sent during boot operation + * part_num: User selects boot data that will be sent to master + *	0x0 - Device not boot enabled (default) + *	0x1 - Boot partition 1 enabled for boot + *	0x2 - Boot partition 2 enabled for boot + * access: User selects partitions to access + *	0x0 : No access to boot partition (default) + *	0x1 : R/W boot partition 1 + *	0x2 : R/W boot partition 2 + *	0x3 : R/W Replay Protected Memory Block (RPMB) + * + * Returns 0 on success. + */ +int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access) +{ +	int err; +	struct mmc_cmd cmd; + +	/* Boot ack enable, boot partition enable , boot partition access */ +	cmd.cmdidx = MMC_CMD_SWITCH; +	cmd.resp_type = MMC_RSP_R1b; + +	cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | +			(EXT_CSD_PART_CONF << 16) | +			((EXT_CSD_BOOT_ACK(ack) | +			EXT_CSD_BOOT_PART_NUM(part_num) | +			EXT_CSD_PARTITION_ACCESS(access)) << 8); + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		if (access) { +			debug("mmc boot partition#%d open fail:Error1 = %d\n", +			      part_num, err); +		} else { +			debug("mmc boot partition#%d close fail:Error = %d\n", +			      part_num, err); +		} +		return err; +	} + +	if (access) { +		/* 4bit transfer mode at booting time. */ +		cmd.cmdidx = MMC_CMD_SWITCH; +		cmd.resp_type = MMC_RSP_R1b; + +		cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | +				(EXT_CSD_BOOT_BUS_WIDTH << 16) | +				((1 << 0) << 8); + +		err = mmc_send_cmd(mmc, &cmd, NULL); +		if (err) { +			debug("mmc boot partition#%d open fail:Error2 = %d\n", +			      part_num, err); +			return err; +		} +	} +	return 0; +} +#endif diff --git a/include/mmc.h b/include/mmc.h index 8bbc6b6eb..21d0937d5 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -92,6 +92,11 @@  #define MMC_CMD_APP_CMD			55  #define MMC_CMD_SPI_READ_OCR		58  #define MMC_CMD_SPI_CRC_ON_OFF		59 +#define MMC_CMD_RES_MAN			62 + +#define MMC_CMD62_ARG1			0xefac62ec +#define MMC_CMD62_ARG2			0xcbaea7 +  #define SD_CMD_SEND_RELATIVE_ADDR	3  #define SD_CMD_SWITCH_FUNC		6 @@ -159,6 +164,7 @@   */  #define EXT_CSD_PARTITIONING_SUPPORT	160	/* RO */  #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */ +#define EXT_CSD_BOOT_BUS_WIDTH		177  #define EXT_CSD_PART_CONF		179	/* R/W */  #define EXT_CSD_BUS_WIDTH		183	/* R/W */  #define EXT_CSD_HS_TIMING		185	/* R/W */ @@ -183,6 +189,16 @@  #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */  #define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */ +#define EXT_CSD_BOOT_ACK_ENABLE			(1 << 6) +#define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3) +#define EXT_CSD_PARTITION_ACCESS_ENABLE		(1 << 0) +#define EXT_CSD_PARTITION_ACCESS_DISABLE	(0 << 0) + +#define EXT_CSD_BOOT_ACK(x)		(x << 6) +#define EXT_CSD_BOOT_PART_NUM(x)	(x << 3) +#define EXT_CSD_PARTITION_ACCESS(x)	(x << 0) + +  #define R1_ILLEGAL_COMMAND		(1 << 22)  #define R1_APP_CMD			(1 << 5) @@ -210,6 +226,11 @@  /* Maximum block size for MMC */  #define MMC_MAX_BLOCK_LEN	512 +/* The number of MMC physical partitions.  These consist of: + * boot partitions (2), general purpose partitions (4) in MMC v4.4. + */ +#define MMC_NUM_BOOT_PARTITION	2 +  struct mmc_cid {  	unsigned long psn;  	unsigned short oid; @@ -286,6 +307,11 @@ int mmc_switch_part(int dev_num, unsigned int part_num);  int mmc_getcd(struct mmc *mmc);  int mmc_getwp(struct mmc *mmc);  void spl_mmc_load(void) __noreturn; +/* Function to change the size of boot partition and rpmb partitions */ +int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, +					unsigned long rpmbsize); +/* Function to send commands to open/close the specified boot partition */ +int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access);  #ifdef CONFIG_GENERIC_MMC  #define mmc_host_is_spi(mmc)	((mmc)->host_caps & MMC_MODE_SPI) |