diff options
| -rw-r--r-- | drivers/mmc/mmc.c | 62 | ||||
| -rw-r--r-- | include/mmc.h | 4 | 
2 files changed, 63 insertions, 3 deletions
| diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 41c28d48e..3d445c0e2 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -52,6 +52,42 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)  	return mmc->send_cmd(mmc, cmd, data);  } +int mmc_send_status(struct mmc *mmc, int timeout) +{ +	struct mmc_cmd cmd; +	int err; +#ifdef CONFIG_MMC_TRACE +	int status; +#endif + +	cmd.cmdidx = MMC_CMD_SEND_STATUS; +	cmd.resp_type = MMC_RSP_R1; +	cmd.cmdarg = 0; +	cmd.flags = 0; + +	do { +		err = mmc_send_cmd(mmc, &cmd, NULL); +		if (err) +			return err; +		else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) +			break; + +		udelay(1000); + +		if (cmd.response[0] & MMC_STATUS_MASK) { +			printf("Status Error: 0x%08X\n", cmd.response[0]); +			return COMM_ERR; +		} +	} while (timeout--); + +	if (!timeout) { +		printf("Timeout waiting card ready\n"); +		return TIMEOUT; +	} + +	return 0; +} +  int mmc_set_blocklen(struct mmc *mmc, int len)  {  	struct mmc_cmd cmd; @@ -86,6 +122,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)  {  	struct mmc_cmd cmd;  	struct mmc_data data; +	int timeout = 1000;  	if ((start + blkcnt) > mmc->block_dev.lba) {  		printf("MMC: block number 0x%lx exceeds max(0x%lx)\n", @@ -128,6 +165,9 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)  			printf("mmc fail to send stop cmd\n");  			return 0;  		} + +		/* Waiting for the ready status */ +		mmc_send_status(mmc, timeout);  	}  	return blkcnt; @@ -162,6 +202,7 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)  {  	struct mmc_cmd cmd;  	struct mmc_data data; +	int timeout = 1000;  	if (blkcnt > 1)  		cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; @@ -193,6 +234,9 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)  			printf("mmc fail to send stop cmd\n");  			return 0;  		} + +		/* Waiting for the ready status */ +		mmc_send_status(mmc, timeout);  	}  	return blkcnt; @@ -396,15 +440,23 @@ int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)  int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)  {  	struct mmc_cmd cmd; +	int timeout = 1000; +	int ret;  	cmd.cmdidx = MMC_CMD_SWITCH;  	cmd.resp_type = MMC_RSP_R1b;  	cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | -		(index << 16) | -		(value << 8); +				 (index << 16) | +				 (value << 8);  	cmd.flags = 0; -	return mmc_send_cmd(mmc, &cmd, NULL); +	ret = mmc_send_cmd(mmc, &cmd, NULL); + +	/* Waiting for the ready status */ +	mmc_send_status(mmc, timeout); + +	return ret; +  }  int mmc_change_freq(struct mmc *mmc) @@ -643,6 +695,7 @@ int mmc_startup(struct mmc *mmc)  	u64 cmult, csize;  	struct mmc_cmd cmd;  	char ext_csd[512]; +	int timeout = 1000;  #ifdef CONFIG_MMC_SPI_CRC_ON  	if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */ @@ -699,6 +752,9 @@ int mmc_startup(struct mmc *mmc)  	err = mmc_send_cmd(mmc, &cmd, NULL); +	/* Waiting for the ready status */ +	mmc_send_status(mmc, timeout); +  	if (err)  		return err; diff --git a/include/mmc.h b/include/mmc.h index 2cf489f4b..ed084c814 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -97,6 +97,10 @@  #define OCR_BUSY	0x80000000  #define OCR_HCS		0x40000000 +#define MMC_STATUS_MASK		(~0x0206BF7F) +#define MMC_STATUS_RDY_FOR_DATA (1<<8) +#define MMC_STATUS_CURR_STATE	(0xf<<9) +  #define MMC_VDD_165_195		0x00000080	/* VDD voltage 1.65 - 1.95 */  #define MMC_VDD_20_21		0x00000100	/* VDD voltage 2.0 ~ 2.1 */  #define MMC_VDD_21_22		0x00000200	/* VDD voltage 2.1 ~ 2.2 */ |