platform/msm_shared/mmc.c
unsigned int
mmc_boot_read_from_card(struct mmc_boot_host *host,
			struct mmc_boot_card *card,
			unsigned long long data_addr,
			unsigned int data_len, unsigned int *out)
{
	unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
	unsigned int mmc_reg = 0;
	unsigned int xfer_type;
	unsigned int addr = 0;
	unsigned char open_ended_read = 1;

	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->rd_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;

	if (xfer_type == MMC_BOOT_XFER_MULTI_BLOCK) {
		if ((card->type == MMC_BOOT_TYPE_MMCHC)
		    || (card->type == MMC_BOOT_TYPE_STD_MMC)) {
			/* Virtio model does not support open-ended multi-block reads.
			 * So, block count must be set before sending read command.
			 * All SD cards do not support this command. Restrict this to MMC.
			 */
			mmc_ret =
			    mmc_boot_set_block_count(card,
						     data_len /
						     (card->rd_block_len));
			if (mmc_ret != MMC_BOOT_E_SUCCESS) {
				dprintf(CRITICAL,
					"Error No.%d: Failure setting read block count for Card (RCA:%s)\n",
					mmc_ret, (char *)(card->rca));
				return mmc_ret;
			}

			open_ended_read = 0;
		}
	}

	/* Set the FLOW_ENA bit of MCI_CLK register to 1 */
	/* Note: It's already enabled */

	/* If Data Mover is used for data transfer then prepare Command
	   List Entry and enable the Data mover to work with SDCC2 */

	/* Write data timeout period to MCI_DATA_TIMER register. */
	/* Data timeout period should be in card bus clock periods */
	mmc_reg = (unsigned long)(card->rd_timeout_ns / 1000000) *
	    (host->mclk_rate / 1000);
	mmc_reg += 1000;	// add some extra clock cycles to be safe
	mmc_reg = mmc_reg / 2;
	writel(mmc_reg, MMC_BOOT_MCI_DATA_TIMER);

	/* Write the total size of the transfer data to MCI_DATA_LENGTH
	   register. For block xfer it must be multiple of the block
	   size. */
	writel(data_len, MMC_BOOT_MCI_DATA_LENGTH);

	/* 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 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 1 to enable transfer from card to host */
	mmc_reg |= MMC_BOOT_MCI_DATA_DIR;
	/* 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. */

	/* If DMA is to be used, Set DM_ENABLE bit to 1 */

#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->rd_block_len << MMC_BOOT_MCI_BLKSIZE_POS);
	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);

	/* Send command to the card/device in order to start the read data
	   transfer. Possible commands: CMD17/18/53/60/61. */
	mmc_ret = mmc_boot_send_read_command(card, xfer_type, addr);
	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
		dprintf(CRITICAL,
			"Error No.%d: Failure sending read command to the Card(RCA:%x)\n",
			mmc_ret, card->rca);
		return mmc_ret;
	}

	/* Read the transfer data from SDCC FIFO. */
	mmc_ret =
	    mmc_boot_fifo_data_transfer(out, data_len, MMC_BOOT_DATA_READ);

	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);
		return mmc_ret;
	}

	/* In case a multiple block transfer was performed, send CMD12 to the
	   card/device in order to indicate the end of read data transfer */
	if ((xfer_type == MMC_BOOT_XFER_MULTI_BLOCK) && open_ended_read) {
		mmc_ret = mmc_boot_send_stop_transmission(card, 0);
		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;
		}
	}

	return MMC_BOOT_E_SUCCESS;
}
/*
 * Reads a data of data_len from the address specified. data_len
 * should be multiple of block size for block data transfer.
 */
Reads a data of data_len from the address specified. data_len
should be multiple of block size for block data transfer.
Reads a data of data_len from the address specified . data_len should be multiple of block size for block data transfer .
unsigned int
mmc_boot_read_from_card(struct mmc_boot_host *host,
			struct mmc_boot_card *card,
			unsigned long long data_addr,
			unsigned int data_len, unsigned int *out)
{
	unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
	unsigned int mmc_reg = 0;
	unsigned int xfer_type;
	unsigned int addr = 0;
	unsigned char open_ended_read = 1;
	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->rd_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;
	if (xfer_type == MMC_BOOT_XFER_MULTI_BLOCK) {
		if ((card->type == MMC_BOOT_TYPE_MMCHC)
		    || (card->type == MMC_BOOT_TYPE_STD_MMC)) {
			mmc_ret =
			    mmc_boot_set_block_count(card,
						     data_len /
						     (card->rd_block_len));
			if (mmc_ret != MMC_BOOT_E_SUCCESS) {
				dprintf(CRITICAL,
					"Error No.%d: Failure setting read block count for Card (RCA:%s)\n",
					mmc_ret, (char *)(card->rca));
				return mmc_ret;
			}
			open_ended_read = 0;
		}
	}
	mmc_reg = (unsigned long)(card->rd_timeout_ns / 1000000) *
	    (host->mclk_rate / 1000);
	mmc_reg += 1000;	
	mmc_reg = mmc_reg / 2;
	writel(mmc_reg, MMC_BOOT_MCI_DATA_TIMER);
	writel(data_len, MMC_BOOT_MCI_DATA_LENGTH);
	addr = ((card->type != MMC_BOOT_TYPE_MMCHC)
		&& (card->type !=
		    MMC_BOOT_TYPE_SDHC)) ? (unsigned int)data_addr : (unsigned
								      int)
	    (data_addr / 512);
	mmc_reg = 0;
	mmc_reg |= MMC_BOOT_MCI_DATA_ENABLE;
	mmc_reg |= MMC_BOOT_MCI_DATA_DIR;
#if MMC_BOOT_ADM
	mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE;
#endif
	mmc_reg |= (card->rd_block_len << MMC_BOOT_MCI_BLKSIZE_POS);
	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);
	mmc_ret = mmc_boot_send_read_command(card, xfer_type, addr);
	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
		dprintf(CRITICAL,
			"Error No.%d: Failure sending read command to the Card(RCA:%x)\n",
			mmc_ret, card->rca);
		return mmc_ret;
	}
	mmc_ret =
	    mmc_boot_fifo_data_transfer(out, data_len, MMC_BOOT_DATA_READ);
	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);
		return mmc_ret;
	}
	if ((xfer_type == MMC_BOOT_XFER_MULTI_BLOCK) && open_ended_read) {
		mmc_ret = mmc_boot_send_stop_transmission(card, 0);
		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;
		}
	}
	return MMC_BOOT_E_SUCCESS;
}
unsigned int mmc_boot_read_from_card ( struct mmc_boot_host * host , struct mmc_boot_card * card , unsigned long long data_addr , unsigned int data_len , unsigned int * out ) { unsigned int mmc_ret = MMC_BOOT_E_SUCCESS ; unsigned int mmc_reg = 0 ; unsigned int xfer_type ; unsigned int addr = 0 ; unsigned char open_ended_read = 1 ; 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 -> rd_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 ; if ( xfer_type == MMC_BOOT_XFER_MULTI_BLOCK ) { if ( ( card -> type == MMC_BOOT_TYPE_MMCHC ) || ( card -> type == MMC_BOOT_TYPE_STD_MMC ) ) { mmc_ret = mmc_boot_set_block_count ( card , data_len / ( card -> rd_block_len ) ) ; if ( mmc_ret != MMC_BOOT_E_SUCCESS ) { dprintf ( CRITICAL , " \n " , mmc_ret , ( char * ) ( card -> rca ) ) ; return mmc_ret ; } open_ended_read = 0 ; } } mmc_reg = ( unsigned long ) ( card -> rd_timeout_ns / 1000000 ) * ( host -> mclk_rate / 1000 ) ; mmc_reg += 1000 ; mmc_reg = mmc_reg / 2 ; writel ( mmc_reg , MMC_BOOT_MCI_DATA_TIMER ) ; writel ( data_len , MMC_BOOT_MCI_DATA_LENGTH ) ; addr = ( ( card -> type != MMC_BOOT_TYPE_MMCHC ) && ( card -> type != MMC_BOOT_TYPE_SDHC ) ) ? ( unsigned int ) data_addr : ( unsigned int ) ( data_addr / 512 ) ; mmc_reg = 0 ; mmc_reg |= MMC_BOOT_MCI_DATA_ENABLE ; mmc_reg |= MMC_BOOT_MCI_DATA_DIR ; #if MMC_BOOT_ADM mmc_reg |= MMC_BOOT_MCI_DATA_DM_ENABLE ; #endif mmc_reg |= ( card -> rd_block_len << MMC_BOOT_MCI_BLKSIZE_POS ) ; writel ( mmc_reg , MMC_BOOT_MCI_DATA_CTL ) ; mmc_ret = mmc_boot_send_read_command ( card , xfer_type , addr ) ; if ( mmc_ret != MMC_BOOT_E_SUCCESS ) { dprintf ( CRITICAL , " \n " , mmc_ret , card -> rca ) ; return mmc_ret ; } mmc_ret = mmc_boot_fifo_data_transfer ( out , data_len , MMC_BOOT_DATA_READ ) ; if ( mmc_ret != MMC_BOOT_E_SUCCESS ) { dprintf ( CRITICAL , " \
 \n " , mmc_ret , card -> rca ) ; return mmc_ret ; } if ( ( xfer_type == MMC_BOOT_XFER_MULTI_BLOCK ) && open_ended_read ) { mmc_ret = mmc_boot_send_stop_transmission ( card , 0 ) ; if ( mmc_ret != MMC_BOOT_E_SUCCESS ) { dprintf ( CRITICAL , " \
 \n " , mmc_ret , card -> rca ) ; return mmc_ret ; } } return MMC_BOOT_E_SUCCESS ; }
Reads a data of data_len from the address specified.
Reads a data of data_len from the address specified .
/* 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 */ /* Virtio model does not support open-ended multi-block reads.
			 * So, block count must be set before sending read command.
			 * All SD cards do not support this command. Restrict this to MMC.
			 */ /* Set the FLOW_ENA bit of MCI_CLK register to 1 */ /* Note: It's already enabled */ /* If Data Mover is used for data transfer then prepare Command
	   List Entry and enable the Data mover to work with SDCC2 */ /* Write data timeout period to MCI_DATA_TIMER register. */ /* Data timeout period should be in card bus clock periods */ // add some extra clock cycles to be safe /* Write the total size of the transfer data to MCI_DATA_LENGTH
	   register. For block xfer it must be multiple of the block
	   size. */ /* For MMCHC/SDHC data address is specified in unit of 512B */ /* Set appropriate fields and write the MCI_DATA_CTL register. */ /* Set ENABLE bit to 1 to enable the data transfer. */ /* Clear DIRECTION bit to 1 to enable transfer from card to host */ /* 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. */ /* If DMA is to be used, Set DM_ENABLE bit to 1 */ /* Write size of block to be used during the data transfer to
	   BLOCKSIZE field */ /* Send command to the card/device in order to start the read data
	   transfer. Possible commands: CMD17/18/53/60/61. */ /* Read the transfer data from SDCC FIFO. */ /* In case a multiple block transfer was performed, send CMD12 to the
	   card/device in order to indicate the end of read data transfer */