platform/msm_shared/mmc.c
static unsigned int mmc_boot_send_command(struct mmc_boot_command *cmd)
{
	unsigned int mmc_cmd = 0;
	unsigned int mmc_status = 0;
	unsigned int mmc_resp = 0;
	unsigned int mmc_return = MMC_BOOT_E_SUCCESS;
	unsigned int cmd_index = 0;
	int i = 0;

	/* basic check */
	if (cmd == NULL) {
		return MMC_BOOT_E_INVAL;
	}

	/* 1. Write command argument to MMC_BOOT_MCI_ARGUMENT register */
	writel(cmd->argument, MMC_BOOT_MCI_ARGUMENT);

	/* Writes to MCI port are not effective for 3 ticks of PCLK.
	 * The min pclk is 144KHz which gives 6.94 us/tick.
	 * Thus 21us == 3 ticks.
	 */
	udelay(21);

	/* 2. Set appropriate fields and write MMC_BOOT_MCI_CMD */
	/* 2a. Write command index in CMD_INDEX field */
	cmd_index = cmd->cmd_index;
	mmc_cmd |= cmd->cmd_index;
	/* 2b. Set RESPONSE bit to 1 for all cmds except CMD0 */
	if (cmd_index != CMD0_GO_IDLE_STATE) {
		mmc_cmd |= MMC_BOOT_MCI_CMD_RESPONSE;
	}

	/* 2c. Set LONGRESP bit to 1 for CMD2, CMD9 and CMD10 */
	if (IS_RESP_136_BITS(cmd->resp_type)) {
		mmc_cmd |= MMC_BOOT_MCI_CMD_LONGRSP;
	}

	/* 2d. Set INTERRUPT bit to 1 to disable command timeout */

	/* 2e. Set PENDING bit to 1 for CMD12 in the beginning of stream
	   mode data transfer */
	if (cmd->xfer_mode == MMC_BOOT_XFER_MODE_STREAM) {
		mmc_cmd |= MMC_BOOT_MCI_CMD_PENDING;
	}

	/* 2f. Set ENABLE bit to 1 */
	mmc_cmd |= MMC_BOOT_MCI_CMD_ENABLE;

	/* 2g. Set PROG_ENA bit to 1 for CMD12, CMD13 issued at the end of
	   write data transfer */
	if ((cmd_index == CMD12_STOP_TRANSMISSION ||
	     cmd_index == CMD13_SEND_STATUS) && cmd->prg_enabled) {
		mmc_cmd |= MMC_BOOT_MCI_CMD_PROG_ENA;
	}

	/* 2h. Set MCIABORT bit to 1 for CMD12 when working with SDIO card */
	/* 2i. Set CCS_ENABLE bit to 1 for CMD61 when Command Completion Signal
	   of CE-ATA device is enabled */

	/* 2j. clear all static status bits */
	writel(MMC_BOOT_MCI_STATIC_STATUS, MMC_BOOT_MCI_CLEAR);

	/* 2k. Write to MMC_BOOT_MCI_CMD register */
	writel(mmc_cmd, MMC_BOOT_MCI_CMD);

	dprintf(SPEW, "Command sent: CMD%d MCI_CMD_REG:%x MCI_ARG:%x\n",
		cmd_index, mmc_cmd, cmd->argument);

	/* 3. Wait for interrupt or poll on the following bits of MCI_STATUS
	   register */
	do {
		/* 3a. Read MCI_STATUS register */
		while (readl(MMC_BOOT_MCI_STATUS) &
		       MMC_BOOT_MCI_STAT_CMD_ACTIVE) ;

		mmc_status = readl(MMC_BOOT_MCI_STATUS);

		/* 3b. CMD_SENT bit supposed to be set to 1 only after CMD0 is sent -
		   no response required. */
		if ((cmd->resp_type == MMC_BOOT_RESP_NONE) &&
		    (mmc_status & MMC_BOOT_MCI_STAT_CMD_SENT)) {
			break;
		}

		/* 3c. If CMD_TIMEOUT bit is set then no response was received */
		else if (mmc_status & MMC_BOOT_MCI_STAT_CMD_TIMEOUT) {
			mmc_return = MMC_BOOT_E_TIMEOUT;
			break;
		}
		/* 3d. If CMD_RESPONSE_END bit is set to 1 then command's response was
		   received and CRC check passed
		   Spcial case for ACMD41: it seems to always fail CRC even if
		   the response is valid
		 */
		else if ((mmc_status & MMC_BOOT_MCI_STAT_CMD_RESP_END)
			 || (cmd_index == CMD1_SEND_OP_COND)
			 || (cmd_index == CMD8_SEND_IF_COND)) {
			/* 3i. Read MCI_RESP_CMD register to verify that response index is
			   equal to command index */
			mmc_resp = readl(MMC_BOOT_MCI_RESP_CMD) & 0x3F;

			/* However, long response does not contain the command index field.
			 * In that case, response index field must be set to 111111b (0x3F) */
			if ((mmc_resp == cmd_index) ||
			    (cmd->resp_type == MMC_BOOT_RESP_R2 ||
			     cmd->resp_type == MMC_BOOT_RESP_R3 ||
			     cmd->resp_type == MMC_BOOT_RESP_R6 ||
			     cmd->resp_type == MMC_BOOT_RESP_R7)) {
				/* 3j. If resp index is equal to cmd index, read command resp
				   from MCI_RESPn registers
				   - MCI_RESP0/1/2/3 for CMD2/9/10
				   - MCI_RESP0 for all other registers */
				if (IS_RESP_136_BITS(cmd->resp_type)) {
					for (i = 0; i < 4; i++) {
						cmd->resp[3 - i] =
						    readl(MMC_BOOT_MCI_RESP_0 +
							  (i * 4));

					}
				} else {
					cmd->resp[0] =
					    readl(MMC_BOOT_MCI_RESP_0);
				}
			} else {
				/* command index mis-match */
				mmc_return = MMC_BOOT_E_CMD_INDX_MISMATCH;
			}

			dprintf(SPEW, "Command response received: %X\n",
				cmd->resp[0]);
			break;
		}

		/* 3e. If CMD_CRC_FAIL bit is set to 1 then cmd's response was recvd,
		   but CRC check failed. */
		else if ((mmc_status & MMC_BOOT_MCI_STAT_CMD_CRC_FAIL)) {
			if (cmd_index == ACMD41_SEND_OP_COND) {
				cmd->resp[0] = readl(MMC_BOOT_MCI_RESP_0);
			} else
				mmc_return = MMC_BOOT_E_CRC_FAIL;
			break;
		}

	}
	while (1);

	return mmc_return;
}
/*
 * Sends specified command to a card and waits for a response.
 */
Sends specified command to a card and waits for a response.
Sends specified command to a card and waits for a response .
static unsigned int mmc_boot_send_command(struct mmc_boot_command *cmd)
{
	unsigned int mmc_cmd = 0;
	unsigned int mmc_status = 0;
	unsigned int mmc_resp = 0;
	unsigned int mmc_return = MMC_BOOT_E_SUCCESS;
	unsigned int cmd_index = 0;
	int i = 0;
	if (cmd == NULL) {
		return MMC_BOOT_E_INVAL;
	}
	writel(cmd->argument, MMC_BOOT_MCI_ARGUMENT);
	udelay(21);
	cmd_index = cmd->cmd_index;
	mmc_cmd |= cmd->cmd_index;
	if (cmd_index != CMD0_GO_IDLE_STATE) {
		mmc_cmd |= MMC_BOOT_MCI_CMD_RESPONSE;
	}
	if (IS_RESP_136_BITS(cmd->resp_type)) {
		mmc_cmd |= MMC_BOOT_MCI_CMD_LONGRSP;
	}
	if (cmd->xfer_mode == MMC_BOOT_XFER_MODE_STREAM) {
		mmc_cmd |= MMC_BOOT_MCI_CMD_PENDING;
	}
	mmc_cmd |= MMC_BOOT_MCI_CMD_ENABLE;
	if ((cmd_index == CMD12_STOP_TRANSMISSION ||
	     cmd_index == CMD13_SEND_STATUS) && cmd->prg_enabled) {
		mmc_cmd |= MMC_BOOT_MCI_CMD_PROG_ENA;
	}
	writel(MMC_BOOT_MCI_STATIC_STATUS, MMC_BOOT_MCI_CLEAR);
	writel(mmc_cmd, MMC_BOOT_MCI_CMD);
	dprintf(SPEW, "Command sent: CMD%d MCI_CMD_REG:%x MCI_ARG:%x\n",
		cmd_index, mmc_cmd, cmd->argument);
	do {
		while (readl(MMC_BOOT_MCI_STATUS) &
		       MMC_BOOT_MCI_STAT_CMD_ACTIVE) ;
		mmc_status = readl(MMC_BOOT_MCI_STATUS);
		if ((cmd->resp_type == MMC_BOOT_RESP_NONE) &&
		    (mmc_status & MMC_BOOT_MCI_STAT_CMD_SENT)) {
			break;
		}
		else if (mmc_status & MMC_BOOT_MCI_STAT_CMD_TIMEOUT) {
			mmc_return = MMC_BOOT_E_TIMEOUT;
			break;
		}
		else if ((mmc_status & MMC_BOOT_MCI_STAT_CMD_RESP_END)
			 || (cmd_index == CMD1_SEND_OP_COND)
			 || (cmd_index == CMD8_SEND_IF_COND)) {
			mmc_resp = readl(MMC_BOOT_MCI_RESP_CMD) & 0x3F;
			if ((mmc_resp == cmd_index) ||
			    (cmd->resp_type == MMC_BOOT_RESP_R2 ||
			     cmd->resp_type == MMC_BOOT_RESP_R3 ||
			     cmd->resp_type == MMC_BOOT_RESP_R6 ||
			     cmd->resp_type == MMC_BOOT_RESP_R7)) {
				if (IS_RESP_136_BITS(cmd->resp_type)) {
					for (i = 0; i < 4; i++) {
						cmd->resp[3 - i] =
						    readl(MMC_BOOT_MCI_RESP_0 +
							  (i * 4));
					}
				} else {
					cmd->resp[0] =
					    readl(MMC_BOOT_MCI_RESP_0);
				}
			} else {
				mmc_return = MMC_BOOT_E_CMD_INDX_MISMATCH;
			}
			dprintf(SPEW, "Command response received: %X\n",
				cmd->resp[0]);
			break;
		}
		else if ((mmc_status & MMC_BOOT_MCI_STAT_CMD_CRC_FAIL)) {
			if (cmd_index == ACMD41_SEND_OP_COND) {
				cmd->resp[0] = readl(MMC_BOOT_MCI_RESP_0);
			} else
				mmc_return = MMC_BOOT_E_CRC_FAIL;
			break;
		}
	}
	while (1);
	return mmc_return;
}
static unsigned int mmc_boot_send_command ( struct mmc_boot_command * cmd ) { unsigned int mmc_cmd = 0 ; unsigned int mmc_status = 0 ; unsigned int mmc_resp = 0 ; unsigned int mmc_return = MMC_BOOT_E_SUCCESS ; unsigned int cmd_index = 0 ; int i = 0 ; if ( cmd == NULL ) { return MMC_BOOT_E_INVAL ; } writel ( cmd -> argument , MMC_BOOT_MCI_ARGUMENT ) ; udelay ( 21 ) ; cmd_index = cmd -> cmd_index ; mmc_cmd |= cmd -> cmd_index ; if ( cmd_index != CMD0_GO_IDLE_STATE ) { mmc_cmd |= MMC_BOOT_MCI_CMD_RESPONSE ; } if ( IS_RESP_136_BITS ( cmd -> resp_type ) ) { mmc_cmd |= MMC_BOOT_MCI_CMD_LONGRSP ; } if ( cmd -> xfer_mode == MMC_BOOT_XFER_MODE_STREAM ) { mmc_cmd |= MMC_BOOT_MCI_CMD_PENDING ; } mmc_cmd |= MMC_BOOT_MCI_CMD_ENABLE ; if ( ( cmd_index == CMD12_STOP_TRANSMISSION || cmd_index == CMD13_SEND_STATUS ) && cmd -> prg_enabled ) { mmc_cmd |= MMC_BOOT_MCI_CMD_PROG_ENA ; } writel ( MMC_BOOT_MCI_STATIC_STATUS , MMC_BOOT_MCI_CLEAR ) ; writel ( mmc_cmd , MMC_BOOT_MCI_CMD ) ; dprintf ( SPEW , " \n " , cmd_index , mmc_cmd , cmd -> argument ) ; do { while ( readl ( MMC_BOOT_MCI_STATUS ) & MMC_BOOT_MCI_STAT_CMD_ACTIVE ) ; mmc_status = readl ( MMC_BOOT_MCI_STATUS ) ; if ( ( cmd -> resp_type == MMC_BOOT_RESP_NONE ) && ( mmc_status & MMC_BOOT_MCI_STAT_CMD_SENT ) ) { break ; } else if ( mmc_status & MMC_BOOT_MCI_STAT_CMD_TIMEOUT ) { mmc_return = MMC_BOOT_E_TIMEOUT ; break ; } else if ( ( mmc_status & MMC_BOOT_MCI_STAT_CMD_RESP_END ) || ( cmd_index == CMD1_SEND_OP_COND ) || ( cmd_index == CMD8_SEND_IF_COND ) ) { mmc_resp = readl ( MMC_BOOT_MCI_RESP_CMD ) & 0x3F ; if ( ( mmc_resp == cmd_index ) || ( cmd -> resp_type == MMC_BOOT_RESP_R2 || cmd -> resp_type == MMC_BOOT_RESP_R3 || cmd -> resp_type == MMC_BOOT_RESP_R6 || cmd -> resp_type == MMC_BOOT_RESP_R7 ) ) { if ( IS_RESP_136_BITS ( cmd -> resp_type ) ) { for ( i = 0 ; i < 4 ; i ++ ) { cmd -> resp [ 3 - i ] = readl ( MMC_BOOT_MCI_RESP_0 + ( i * 4 ) ) ; } } else { cmd -> resp [ 0 ] = readl ( MMC_BOOT_MCI_RESP_0 ) ; } } else { mmc_return = MMC_BOOT_E_CMD_INDX_MISMATCH ; } dprintf ( SPEW , " \n " , cmd -> resp [ 0 ] ) ; break ; } else if ( ( mmc_status & MMC_BOOT_MCI_STAT_CMD_CRC_FAIL ) ) { if ( cmd_index == ACMD41_SEND_OP_COND ) { cmd -> resp [ 0 ] = readl ( MMC_BOOT_MCI_RESP_0 ) ; } else mmc_return = MMC_BOOT_E_CRC_FAIL ; break ; } } while ( 1 ) ; return mmc_return ; }
Sends specified command to a card and waits for a response.
Sends specified command to a card and waits for a response .
/* basic check */ /* 1. Write command argument to MMC_BOOT_MCI_ARGUMENT register */ /* Writes to MCI port are not effective for 3 ticks of PCLK.
	 * The min pclk is 144KHz which gives 6.94 us/tick.
	 * Thus 21us == 3 ticks.
	 */ /* 2. Set appropriate fields and write MMC_BOOT_MCI_CMD */ /* 2a. Write command index in CMD_INDEX field */ /* 2b. Set RESPONSE bit to 1 for all cmds except CMD0 */ /* 2c. Set LONGRESP bit to 1 for CMD2, CMD9 and CMD10 */ /* 2d. Set INTERRUPT bit to 1 to disable command timeout */ /* 2e. Set PENDING bit to 1 for CMD12 in the beginning of stream
	   mode data transfer */ /* 2f. Set ENABLE bit to 1 */ /* 2g. Set PROG_ENA bit to 1 for CMD12, CMD13 issued at the end of
	   write data transfer */ /* 2h. Set MCIABORT bit to 1 for CMD12 when working with SDIO card */ /* 2i. Set CCS_ENABLE bit to 1 for CMD61 when Command Completion Signal
	   of CE-ATA device is enabled */ /* 2j. clear all static status bits */ /* 2k. Write to MMC_BOOT_MCI_CMD register */ /* 3. Wait for interrupt or poll on the following bits of MCI_STATUS
	   register */ /* 3a. Read MCI_STATUS register */ /* 3b. CMD_SENT bit supposed to be set to 1 only after CMD0 is sent -
		   no response required. */ /* 3c. If CMD_TIMEOUT bit is set then no response was received */ /* 3d. If CMD_RESPONSE_END bit is set to 1 then command's response was
		   received and CRC check passed
		   Spcial case for ACMD41: it seems to always fail CRC even if
		   the response is valid
		 */ /* 3i. Read MCI_RESP_CMD register to verify that response index is
			   equal to command index */ /* However, long response does not contain the command index field.
			 * In that case, response index field must be set to 111111b (0x3F) */ /* 3j. If resp index is equal to cmd index, read command resp
				   from MCI_RESPn registers
				   - MCI_RESP0/1/2/3 for CMD2/9/10
				   - MCI_RESP0 for all other registers */ /* command index mis-match */ /* 3e. If CMD_CRC_FAIL bit is set to 1 then cmd's response was recvd,
		   but CRC check failed. */