platform/msm_shared/mmc.c
unsigned int
mmc_boot_write_to_card(struct mmc_boot_host *host,
		       struct mmc_boot_card *card,
		       unsigned long long data_addr,
		       unsigned int data_len, unsigned int *in)
{
	unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
	unsigned int mmc_status = 0;
	unsigned int mmc_reg = 0;
	unsigned int addr;
	unsigned int xfer_type;
	unsigned int status;

	if ((host == NULL) || (card == NULL)) {
		return MMC_BOOT_E_INVAL;
	}

	/* Set block length. High Capacity MMC/SD card uses fixed 512 bytes block
	   length. So no need to send CMD16. */
	if ((card->type != MMC_BOOT_TYPE_MMCHC)
	    && (card->type != MMC_BOOT_TYPE_SDHC)) {
		mmc_ret = mmc_boot_set_block_len(card, card->wr_block_len);
		if (mmc_ret != MMC_BOOT_E_SUCCESS) {
			dprintf(CRITICAL, "Error No.%d: Failure setting block length for Card\
                    (RCA:%s)\n", mmc_ret,
				(char *)(card->rca));
			return mmc_ret;
		}
	}

	/* use multi-block mode to transfer for data larger than a block */
	xfer_type =
	    (data_len >
	     card->
	     rd_block_len) ? MMC_BOOT_XFER_MULTI_BLOCK :
	    MMC_BOOT_XFER_SINGLE_BLOCK;

	/* For MMCHC/SDHC data address is specified in unit of 512B */
	addr = ((card->type != MMC_BOOT_TYPE_MMCHC)
		&& (card->type !=
		    MMC_BOOT_TYPE_SDHC)) ? (unsigned int)data_addr : (unsigned
								      int)
	    (data_addr / 512);

	/* Set the FLOW_ENA bit of MCI_CLK register to 1 */
	mmc_reg = readl(MMC_BOOT_MCI_CLK);
	mmc_reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
	writel(mmc_reg, MMC_BOOT_MCI_CLK);

	/* Write data timeout period to MCI_DATA_TIMER register */
	/* Data timeout period should be in card bus clock periods */
	/*TODO: Fix timeout value */
	mmc_reg = 0xFFFFFFFF;
	writel(mmc_reg, MMC_BOOT_MCI_DATA_TIMER);

	/* Write the total size of the transfer data to MCI_DATA_LENGTH register */
	writel(data_len, MMC_BOOT_MCI_DATA_LENGTH);

	/* Send command to the card/device in order to start the write data xfer.
	   The possible commands are CMD24/25/53/60/61 */
	mmc_ret = mmc_boot_send_write_command(card, xfer_type, addr);
	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
		dprintf(CRITICAL, "Error No.%d: Failure sending write command to the\
                Card(RCA:%x)\n", mmc_ret,
			card->rca);
		return mmc_ret;
	}

	/* Set appropriate fields and write the MCI_DATA_CTL register */
	/* Set ENABLE bit to 1 to enable the data transfer. */
	mmc_reg = 0;
	mmc_reg |= MMC_BOOT_MCI_DATA_ENABLE;
	/* Clear DIRECTION bit to 0 to enable transfer from host to card */
	/* Clear MODE bit to 0 to enable block oriented data transfer. For
	   MMC cards only, if stream data transfer mode is desired, set
	   MODE bit to 1. */

	/* Set DM_ENABLE bit to 1 in order to enable DMA, otherwise set 0 */

#if MMC_BOOT_ADM
	mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
#endif

	/* Write size of block to be used during the data transfer to
	   BLOCKSIZE field */
	mmc_reg |= card->wr_block_len << MMC_BOOT_MCI_BLKSIZE_POS;
	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);

	/* write data to FIFO */
	mmc_ret =
	    mmc_boot_fifo_data_transfer(in, data_len, MMC_BOOT_DATA_WRITE);

	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
		dprintf(CRITICAL, "Error No.%d: Failure on data transfer from the \
                Card(RCA:%x)\n", mmc_ret,
			card->rca);
		/* In case of any failure happening for multi block transfer */
		if (xfer_type == MMC_BOOT_XFER_MULTI_BLOCK)
			mmc_boot_send_stop_transmission(card, 1);
		return mmc_ret;
	}

	/* Send command to the card/device in order to poll the de-assertion of
	   card/device BUSY condition. It is important to set PROG_ENA bit in
	   MCI_CLK register before sending the command. Possible commands are
	   CMD12/13. */
	if (xfer_type == MMC_BOOT_XFER_MULTI_BLOCK) {
		mmc_ret = mmc_boot_send_stop_transmission(card, 1);
		if (mmc_ret != MMC_BOOT_E_SUCCESS) {
			dprintf(CRITICAL, "Error No.%d: Failure sending Stop Transmission \
                    command to the Card(RCA:%x)\n", mmc_ret,
				card->rca);
			return mmc_ret;
		}
	} else {
		mmc_ret = mmc_boot_get_card_status(card, 1, &status);
		if (mmc_ret != MMC_BOOT_E_SUCCESS) {
			dprintf(CRITICAL,
				"Error No.%d: Failure getting card status of Card(RCA:%x)\n",
				mmc_ret, card->rca);
			return mmc_ret;
		}
	}

	/* Wait for interrupt or poll on PROG_DONE bit of MCI_STATUS register. If
	   PROG_DONE bit is set to 1 it means that the card finished it programming
	   and stopped driving DAT0 line to 0 */
	do {
		mmc_status = readl(MMC_BOOT_MCI_STATUS);
		if (mmc_status & MMC_BOOT_MCI_STAT_PROG_DONE) {
			break;
		}
	}
	while (1);

	return MMC_BOOT_E_SUCCESS;
}
/*
 * Write data_len data to address specified by data_addr. data_len is
 * multiple of blocks for block data transfer.
 */
Write data_len data to address specified by data_addr. data_len is
multiple of blocks for block data transfer.
Write data_len data to address specified by data_addr . data_len is multiple of blocks for block data transfer .
unsigned int
mmc_boot_write_to_card(struct mmc_boot_host *host,
		       struct mmc_boot_card *card,
		       unsigned long long data_addr,
		       unsigned int data_len, unsigned int *in)
{
	unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
	unsigned int mmc_status = 0;
	unsigned int mmc_reg = 0;
	unsigned int addr;
	unsigned int xfer_type;
	unsigned int status;
	if ((host == NULL) || (card == NULL)) {
		return MMC_BOOT_E_INVAL;
	}
	if ((card->type != MMC_BOOT_TYPE_MMCHC)
	    && (card->type != MMC_BOOT_TYPE_SDHC)) {
		mmc_ret = mmc_boot_set_block_len(card, card->wr_block_len);
		if (mmc_ret != MMC_BOOT_E_SUCCESS) {
			dprintf(CRITICAL, "Error No.%d: Failure setting block length for Card\
                    (RCA:%s)\n", mmc_ret,
				(char *)(card->rca));
			return mmc_ret;
		}
	}
	xfer_type =
	    (data_len >
	     card->
	     rd_block_len) ? MMC_BOOT_XFER_MULTI_BLOCK :
	    MMC_BOOT_XFER_SINGLE_BLOCK;
	addr = ((card->type != MMC_BOOT_TYPE_MMCHC)
		&& (card->type !=
		    MMC_BOOT_TYPE_SDHC)) ? (unsigned int)data_addr : (unsigned
								      int)
	    (data_addr / 512);
	mmc_reg = readl(MMC_BOOT_MCI_CLK);
	mmc_reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
	writel(mmc_reg, MMC_BOOT_MCI_CLK);
	mmc_reg = 0xFFFFFFFF;
	writel(mmc_reg, MMC_BOOT_MCI_DATA_TIMER);
	writel(data_len, MMC_BOOT_MCI_DATA_LENGTH);
	mmc_ret = mmc_boot_send_write_command(card, xfer_type, addr);
	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
		dprintf(CRITICAL, "Error No.%d: Failure sending write command to the\
                Card(RCA:%x)\n", mmc_ret,
			card->rca);
		return mmc_ret;
	}
	mmc_reg = 0;
	mmc_reg |= MMC_BOOT_MCI_DATA_ENABLE;
#if MMC_BOOT_ADM
	mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
#endif
	mmc_reg |= card->wr_block_len << MMC_BOOT_MCI_BLKSIZE_POS;
	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);
	mmc_ret =
	    mmc_boot_fifo_data_transfer(in, data_len, MMC_BOOT_DATA_WRITE);
	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
		dprintf(CRITICAL, "Error No.%d: Failure on data transfer from the \
                Card(RCA:%x)\n", mmc_ret,
			card->rca);
		if (xfer_type == MMC_BOOT_XFER_MULTI_BLOCK)
			mmc_boot_send_stop_transmission(card, 1);
		return mmc_ret;
	}
	if (xfer_type == MMC_BOOT_XFER_MULTI_BLOCK) {
		mmc_ret = mmc_boot_send_stop_transmission(card, 1);
		if (mmc_ret != MMC_BOOT_E_SUCCESS) {
			dprintf(CRITICAL, "Error No.%d: Failure sending Stop Transmission \
                    command to the Card(RCA:%x)\n", mmc_ret,
				card->rca);
			return mmc_ret;
		}
	} else {
		mmc_ret = mmc_boot_get_card_status(card, 1, &status);
		if (mmc_ret != MMC_BOOT_E_SUCCESS) {
			dprintf(CRITICAL,
				"Error No.%d: Failure getting card status of Card(RCA:%x)\n",
				mmc_ret, card->rca);
			return mmc_ret;
		}
	}
	do {
		mmc_status = readl(MMC_BOOT_MCI_STATUS);
		if (mmc_status & MMC_BOOT_MCI_STAT_PROG_DONE) {
			break;
		}
	}
	while (1);
	return MMC_BOOT_E_SUCCESS;
}
unsigned int mmc_boot_write_to_card ( struct mmc_boot_host * host , struct mmc_boot_card * card , unsigned long long data_addr , unsigned int data_len , unsigned int * in ) { unsigned int mmc_ret = MMC_BOOT_E_SUCCESS ; unsigned int mmc_status = 0 ; unsigned int mmc_reg = 0 ; unsigned int addr ; unsigned int xfer_type ; unsigned int status ; if ( ( host == NULL ) || ( card == NULL ) ) { return MMC_BOOT_E_INVAL ; } if ( ( card -> type != MMC_BOOT_TYPE_MMCHC ) && ( card -> type != MMC_BOOT_TYPE_SDHC ) ) { mmc_ret = mmc_boot_set_block_len ( card , card -> wr_block_len ) ; if ( mmc_ret != MMC_BOOT_E_SUCCESS ) { dprintf ( CRITICAL , " \
 \n " , mmc_ret , ( char * ) ( card -> rca ) ) ; return mmc_ret ; } } xfer_type = ( data_len > card -> rd_block_len ) ? MMC_BOOT_XFER_MULTI_BLOCK : MMC_BOOT_XFER_SINGLE_BLOCK ; addr = ( ( card -> type != MMC_BOOT_TYPE_MMCHC ) && ( card -> type != MMC_BOOT_TYPE_SDHC ) ) ? ( unsigned int ) data_addr : ( unsigned int ) ( data_addr / 512 ) ; mmc_reg = readl ( MMC_BOOT_MCI_CLK ) ; mmc_reg |= MMC_BOOT_MCI_CLK_ENA_FLOW ; writel ( mmc_reg , MMC_BOOT_MCI_CLK ) ; mmc_reg = 0xFFFFFFFF ; writel ( mmc_reg , MMC_BOOT_MCI_DATA_TIMER ) ; writel ( data_len , MMC_BOOT_MCI_DATA_LENGTH ) ; mmc_ret = mmc_boot_send_write_command ( card , xfer_type , addr ) ; if ( mmc_ret != MMC_BOOT_E_SUCCESS ) { dprintf ( CRITICAL , " \
 \n " , mmc_ret , card -> rca ) ; return mmc_ret ; } mmc_reg = 0 ; mmc_reg |= MMC_BOOT_MCI_DATA_ENABLE ; #if MMC_BOOT_ADM mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE ; #endif mmc_reg |= card -> wr_block_len << MMC_BOOT_MCI_BLKSIZE_POS ; writel ( mmc_reg , MMC_BOOT_MCI_DATA_CTL ) ; mmc_ret = mmc_boot_fifo_data_transfer ( in , data_len , MMC_BOOT_DATA_WRITE ) ; if ( mmc_ret != MMC_BOOT_E_SUCCESS ) { dprintf ( CRITICAL , " \
 \n " , mmc_ret , card -> rca ) ; if ( xfer_type == MMC_BOOT_XFER_MULTI_BLOCK ) mmc_boot_send_stop_transmission ( card , 1 ) ; return mmc_ret ; } if ( xfer_type == MMC_BOOT_XFER_MULTI_BLOCK ) { mmc_ret = mmc_boot_send_stop_transmission ( card , 1 ) ; if ( mmc_ret != MMC_BOOT_E_SUCCESS ) { dprintf ( CRITICAL , " \
 \n " , mmc_ret , card -> rca ) ; return mmc_ret ; } } else { mmc_ret = mmc_boot_get_card_status ( card , 1 , & status ) ; if ( mmc_ret != MMC_BOOT_E_SUCCESS ) { dprintf ( CRITICAL , " \n " , mmc_ret , card -> rca ) ; return mmc_ret ; } } do { mmc_status = readl ( MMC_BOOT_MCI_STATUS ) ; if ( mmc_status & MMC_BOOT_MCI_STAT_PROG_DONE ) { break ; } } while ( 1 ) ; return MMC_BOOT_E_SUCCESS ; }
Write data_len data to address specified by data_addr.
Write data_len data to address specified by data_addr .
/* Set block length. High Capacity MMC/SD card uses fixed 512 bytes block
	   length. So no need to send CMD16. */ /* use multi-block mode to transfer for data larger than a block */ /* For MMCHC/SDHC data address is specified in unit of 512B */ /* Set the FLOW_ENA bit of MCI_CLK register to 1 */ /* Write data timeout period to MCI_DATA_TIMER register */ /* Data timeout period should be in card bus clock periods */ /*TODO: Fix timeout value */ /* Write the total size of the transfer data to MCI_DATA_LENGTH register */ /* Send command to the card/device in order to start the write data xfer.
	   The possible commands are CMD24/25/53/60/61 */ /* Set appropriate fields and write the MCI_DATA_CTL register */ /* Set ENABLE bit to 1 to enable the data transfer. */ /* Clear DIRECTION bit to 0 to enable transfer from host to card */ /* Clear MODE bit to 0 to enable block oriented data transfer. For
	   MMC cards only, if stream data transfer mode is desired, set
	   MODE bit to 1. */ /* Set DM_ENABLE bit to 1 in order to enable DMA, otherwise set 0 */ /* Write size of block to be used during the data transfer to
	   BLOCKSIZE field */ /* write data to FIFO */ /* In case of any failure happening for multi block transfer */ /* Send command to the card/device in order to poll the de-assertion of
	   card/device BUSY condition. It is important to set PROG_ENA bit in
	   MCI_CLK register before sending the command. Possible commands are
	   CMD12/13. */ /* Wait for interrupt or poll on PROG_DONE bit of MCI_STATUS register. If
	   PROG_DONE bit is set to 1 it means that the card finished it programming
	   and stopped driving DAT0 line to 0 */