Example #1
0
/*
 * Function: mmc device sleep
 * Arg     : None
 * Return  : Clean up function for storage
 * Flow    : Put the mmc card to sleep
 */
void mmc_device_sleep()
{
	void *dev;
	dev = target_mmc_device();

	if (target_mmc_device())
	{
		mmc_put_card_to_sleep((struct mmc_device *)dev);
	}
}
Example #2
0
int ufs_get_boot_lun()
{
	int ret = 0;
	void *dev;
	dev = target_mmc_device();

	if (!(target_mmc_device()))
		ret = dme_get_bbootlunen((struct ufs_dev *)dev);
	return ret;
}
Example #3
0
int ufs_set_boot_lun(uint32_t boot_lun_id)
{
	int ret = 0;
	void *dev;
	dev = target_mmc_device();

	if (!(target_mmc_device()))
		ret = dme_set_bbootlunen((struct ufs_dev *)dev, boot_lun_id);
	return ret;
}
Example #4
0
/*
 * Function     : mmc get LUN from ufs
 * Arg          : LUN number
 * Return type  : lun number for UFS and 0 for emmc
 */
uint8_t mmc_get_lun(void)
{
	void *dev;
	uint8_t lun=0;

	dev = target_mmc_device();

	if (!target_mmc_device())
	{
		lun = ((struct ufs_dev*)dev)->current_lun;
	}

	return lun;
}
Example #5
0
/*
 * Function: storage page size
 * Arg     : None
 * Return  : Returns the page size for the card
 * Flow    : Get the page size for storage
 */
uint32_t mmc_page_size()
{
	if (target_mmc_device())
	{
		return BOARD_KERNEL_PAGESIZE;
	}
	else
	{
		void *dev;

		dev = target_mmc_device();

		return ufs_get_page_size((struct ufs_dev *)dev);
	}
}
Example #6
0
int rpmb_init()
{
	int ret = 0;

	dev = target_mmc_device();

	/* 1. Initialize storage specific data */
	if (platform_boot_dev_isemmc())
	{
		struct mmc_device *mmc_dev = (struct mmc_device *) dev;
		info.size = mmc_dev->card.rpmb_size / RPMB_MIN_BLK_SZ;
		info.rel_wr_count = mmc_dev->card.rel_wr_count;
		info.dev_type  = EMMC_RPMB;
	}
	else
	{
		struct ufs_dev *ufs_dev = (struct ufs_dev *) dev;
		ufs_rpmb_init(ufs_dev);
		info.size = ufs_dev->rpmb_num_blocks;
		info.rel_wr_count = ufs_dev->rpmb_rw_size;
		info.dev_type  = UFS_RPMB;
	}

	/* Register & start the listener */
	ret = rpmb_listener_start();
	if (ret < 0)
	{
		dprintf(CRITICAL, "Error registering the handler\n");
		goto err;
	}

err:
	return ret;
}
Example #7
0
void platform_boot_dev_cmdline(char *buf)
{
	uint32_t val = 0;
	void *dev;

	dev = target_mmc_device();

	val = platform_get_boot_dev();
	switch(val)
	{
		case BOOT_DEFAULT:
		case BOOT_EMMC:
			sprintf(buf, "%x.sdhci", ((struct mmc_device *)dev)->host.base);
			break;
		case BOOT_UFS:
			sprintf(buf, "%x.ufshc", ((struct ufs_dev *)dev)->base);
			break;
		case BOOT_NAND:
			sprintf(buf, "%x.nandc", nand_device_base());
			break;
		default:
			dprintf(CRITICAL,"ERROR: Unexpected boot_device val=%x",val);
			ASSERT(0);
	};
}
Example #8
0
/*
 * Function: get mmc card
 * Arg     : None
 * Return  : Pointer to mmc card structure
 * Flow    : Get the card pointer from the device structure
 */
static struct mmc_card *get_mmc_card()
{
	struct mmc_device *dev;
	struct mmc_card *card;

	dev = target_mmc_device();
	card = &dev->card;

	return card;
}
Example #9
0
/*
 * Function: mmc get psn
 * Arg     : None
 * Return  : Returns the product serial number
 * Flow    : Get the PSN from card
 */
uint32_t mmc_get_psn(void)
{
	if (target_mmc_device())
	{
		struct mmc_card *card;

		card = get_mmc_card();

		return card->cid.psn;
	}
	else
	{
		void *dev;

		dev = target_mmc_device();

		return ufs_get_serial_num((struct ufs_dev *)dev);
	}
}
Example #10
0
/*
 * Function: mmc get capacity
 * Arg     : None
 * Return  : Returns the density of the emmc card
 * Flow    : Get the density from card
 */
uint64_t mmc_get_device_capacity()
{
	if (target_mmc_device())
	{
		struct mmc_card *card;

		card = get_mmc_card();

		return card->capacity;
	}
	else
	{
		void *dev;

		dev = target_mmc_device();

		return ufs_get_dev_capacity((struct ufs_dev *)dev);
	}
}
Example #11
0
/*
 * Function: mmc get blocksize
 * Arg     : None
 * Return  : Returns the block size of the storage
 * Flow    : Get the block size form the card
 */
uint32_t mmc_get_device_blocksize()
{
	if (target_mmc_device())
	{
		struct mmc_card *card;

		card = get_mmc_card();

		return card->block_size;
	}
	else
	{
		void *dev;

		dev = target_mmc_device();

		return ufs_get_page_size((struct ufs_dev *)dev);
	}
}
Example #12
0
/*
 * Function: get mmc card
 * Arg     : None
 * Return  : Pointer to mmc card structure
 * Flow    : Get the card pointer from the device structure
 */
static struct mmc_card *get_mmc_card()
{
	void *dev;
	struct mmc_card *card;

	dev = target_mmc_device();
	card = &((struct mmc_device*)dev)->card;

	return card;
}
Example #13
0
/*
 * Function: mmc erase card
 * Arg     : Block address & length
 * Return  : Returns 0
 * Flow    : Erase the card from specified addr
 */
uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
{
	struct mmc_device *dev;

	dev = target_mmc_device();

	ASSERT(!(addr % MMC_BLK_SZ));
	ASSERT(!(len % MMC_BLK_SZ));

	if (mmc_sdhci_erase(dev, (addr / MMC_BLK_SZ), len))
	{
		dprintf(CRITICAL, "MMC erase failed\n");
		return 1;
	}
	return 0;
}
Example #14
0
/*
 * Function: mmc_write
 * Arg     : Data address on card, data length, i/p buffer
 * Return  : 0 on Success, non zero on failure
 * Flow    : Write the data from in to the card
 */
uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in)
{
	uint32_t val = 0;
	uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ;
	uint8_t *sptr = (uint8_t *)in;
	struct mmc_device *dev;

	dev = target_mmc_device();

	ASSERT(!(data_addr % MMC_BLK_SZ));

	if (data_len % MMC_BLK_SZ)
		data_len = ROUNDUP(data_len, MMC_BLK_SZ);

	/* TODO: This function is aware of max data that can be
	 * tranferred using sdhci adma mode, need to have a cleaner
	 * implementation to keep this function independent of sdhci
	 * limitations
	 */
	while (data_len > write_size) {
		val = mmc_sdhci_write(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (write_size / MMC_BLK_SZ));
		if (val)
		{
			dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / MMC_BLK_SZ));
			return val;
		}
		sptr += write_size;
		data_addr += write_size;
		data_len -= write_size;
	}

	if (data_len)
		val = mmc_sdhci_write(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));

	if (val)
		dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / MMC_BLK_SZ));

	return val;
}
Example #15
0
/*
 * Function: mmc_read
 * Arg     : Data address on card, o/p buffer & data length
 * Return  : 0 on Success, non zero on failure
 * Flow    : Read data from the card to out
 */
uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len)
{
	uint32_t ret = 0;
	uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ;
	struct mmc_device *dev;
	uint8_t *sptr = (uint8_t *)out;

	ASSERT(!(data_addr % MMC_BLK_SZ));
	ASSERT(!(data_len % MMC_BLK_SZ));

	dev = target_mmc_device();

	/* TODO: This function is aware of max data that can be
	 * tranferred using sdhci adma mode, need to have a cleaner
	 * implementation to keep this function independent of sdhci
	 * limitations
	 */
	while (data_len > read_size) {
		ret = mmc_sdhci_read(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (read_size / MMC_BLK_SZ));
		if (ret)
		{
			dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / MMC_BLK_SZ));
			return ret;
		}
		sptr += read_size;
		data_addr += read_size;
		data_len -= read_size;
	}

	if (data_len)
		ret = mmc_sdhci_read(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));

	if (ret)
		dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / MMC_BLK_SZ));

	return ret;
}
Example #16
0
void platform_boot_dev_cmdline(char *buf)
{
	uint32_t val = 0;
	void *dev = target_mmc_device();

	val = platform_get_boot_dev();
	switch(val)
	{
#if !USE_MDM_BOOT_CFG
		case BOOT_DEFAULT:
			snprintf(buf, ((sizeof((struct mmc_device *)dev)->host.base)*2) + 7,"%x.sdhci", ((struct mmc_device *)dev)->host.base);
			break;
		case BOOT_UFS:
			snprintf(buf, ((sizeof((struct ufs_dev *)dev)->base)*2) + 7, "%x.ufshc", ((struct ufs_dev *)dev)->base);
			break;
#endif
		case BOOT_EMMC:
			snprintf(buf, ((sizeof((struct mmc_device *)dev)->host.base)*2) + 7,"%x.sdhci", ((struct mmc_device *)dev)->host.base);
			break;
		default:
			dprintf(CRITICAL,"ERROR: Unexpected boot_device val=%x",val);
			ASSERT(0);
	};
}
Example #17
0
uint32_t mmc_write_protect(const char *ptn_name, int set_clr)
{
	void *dev = NULL;
	struct mmc_card *card = NULL;
	uint32_t block_size;
	unsigned long long  ptn = 0;
	uint64_t size;
	int index = -1;
#ifdef UFS_SUPPORT
	int ret = 0;
#endif

	dev = target_mmc_device();
	block_size = mmc_get_device_blocksize();

	if (target_mmc_device())
	{
		card = &((struct mmc_device *)dev)->card;

		index = partition_get_index(ptn_name);

		ptn = partition_get_offset(index);
		if(!ptn)
		{
			return 1;
		}

		/* Convert the size to blocks */
		size = partition_get_size(index) / block_size;

		/*
		 * For read only partitions the minimum size allocated on the disk is
		 * 1 WP GRP size. If the size of partition is less than 1 WP GRP size
		 * protect atleast one WP group.
		 */
		if (partition_read_only(index) && size < card->wp_grp_size)
		{
			/* Write protect api takes the size in bytes, convert size to bytes */
			size = card->wp_grp_size * block_size;
		}
		else
		{
			size *= block_size;
		}

		/* Set the power on WP bit */
		return mmc_set_clr_power_on_wp_user((struct mmc_device *)dev, (ptn / block_size), size, set_clr);
	}
	else
	{
#ifdef UFS_SUPPORT
		/* Enable the power on WP fo all LUNs which have WP bit is enabled */
		ret = dme_set_fpoweronwpen((struct ufs_dev*) dev);
		if (ret < 0)
		{
			dprintf(CRITICAL, "Failure to WP UFS partition\n");
			return 1;
		}
#endif
	}

	return 0;
}
Example #18
0
int rpmb_init()
{
	int ret = 0;

	dev = target_mmc_device();

	/* 1. Initialize storage specific data */
	if (platform_boot_dev_isemmc())
	{
		struct mmc_device *mmc_dev = (struct mmc_device *) dev;
		info.size = mmc_dev->card.rpmb_size / RPMB_MIN_BLK_SZ;
		if (mmc_dev->card.ext_csd[MMC_EXT_CSD_REV] < 8)
		{
			//as per emmc spec rel_wr_count should be 1 for emmc version < 5.1
			dprintf(SPEW, "EMMC Version < 5.1\n");
			info.rel_wr_count = 1;
		}
		else
		{
			if (mmc_dev->card.ext_csd[MMC_EXT_CSD_EN_RPMB_REL_WR] == 0)
			{
				dprintf(SPEW, "EMMC Version >= 5.1 EN_RPMB_REL_WR = 0\n");
				// according to emmc version 5.1 and above if EN_RPMB_REL_WR in extended
				// csd is not set the maximum number of frames that can be reliably written
				// to emmc would be 2
				info.rel_wr_count = 2;
			}
			else
			{
				dprintf(SPEW, "EMMC Version >= 5.1 EN_RPMB_REL_WR = 1\n");
				// according to emmc version 5.1 and above if EN_RPMB_REL_WR in extended
				// csd is set the maximum number of frames that can be reliably written
				// to emmc would be 32
				info.rel_wr_count = 32;
			}
		}

		/*
		 *  tz changes required for supporting
		 *  multiple frames are not present
		 *  force the number of frames to be minimum
		 *  i.e. one for tz 3.0 and earlier.
		 */
		if( qseecom_get_version() < QSEE_VERSION_40 )
			info.rel_wr_count = 1;

		info.dev_type  = EMMC_RPMB;
	}
#ifdef UFS_SUPPORT
	else
	{
		struct ufs_dev *ufs_dev = (struct ufs_dev *) dev;
		ufs_rpmb_init(ufs_dev);
		info.size = ufs_dev->rpmb_num_blocks;
		info.rel_wr_count = ufs_dev->rpmb_rw_size;
		info.dev_type  = UFS_RPMB;
	}
#endif

	/* Register & start the listener */
	ret = rpmb_listener_start();
	if (ret < 0)
	{
		dprintf(CRITICAL, "Error registering the handler\n");
		goto err;
	}

err:
	return ret;
}
Example #19
0
/*
 * Function: mmc_write
 * Arg     : Data address on card, data length, i/p buffer
 * Return  : 0 on Success, non zero on failure
 * Flow    : Write the data from in to the card
 */
uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in)
{
	uint32_t val = 0;
	int ret = 0;
	uint32_t block_size = 0;
	uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ;
	uint8_t *sptr = (uint8_t *)in;
	void *dev;

	dev = target_mmc_device();

	block_size = mmc_get_device_blocksize();

	ASSERT(!(data_addr % block_size));

	if (data_len % block_size)
		data_len = ROUNDUP(data_len, block_size);

	/*
	 * Flush the cache before handing over the data to
	 * storage driver
	 */
	arch_clean_invalidate_cache_range((addr_t)in, data_len);

	if (target_mmc_device())
	{
		/* TODO: This function is aware of max data that can be
		 * tranferred using sdhci adma mode, need to have a cleaner
		 * implementation to keep this function independent of sdhci
		 * limitations
		 */
		while (data_len > write_size) {
			val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (write_size / block_size));
			if (val)
			{
				dprintf(CRITICAL, "Failed Writing block @ %x\n",(unsigned int)(data_addr / block_size));
				return val;
			}
			sptr += write_size;
			data_addr += write_size;
			data_len -= write_size;
		}

		if (data_len)
			val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));

		if (val)
			dprintf(CRITICAL, "Failed Writing block @ %x\n",(unsigned int)(data_addr / block_size));
	}
	else
	{
		ret = ufs_write((struct ufs_dev *)dev, data_addr, (addr_t)in, (data_len / block_size));

		if (ret)
		{
			dprintf(CRITICAL, "Error: UFS write failed writing to block: %llu\n", data_addr);
			val = 1;
		}
	}

	return val;
}
Example #20
0
/*
 * Function: mmc erase card
 * Arg     : Block address & length
 * Return  : Returns 0
 * Flow    : Erase the card from specified addr
 */
uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
{
	struct mmc_device *dev;
	uint32_t block_size;
	uint32_t unaligned_blks;
	uint32_t head_unit;
	uint32_t tail_unit;
	uint32_t erase_unit_sz;
	uint32_t blk_addr;
	uint32_t blk_count;
	uint64_t blks_to_erase;

	block_size = mmc_get_device_blocksize();

	dev = target_mmc_device();

	ASSERT(!(addr % block_size));
	ASSERT(!(len % block_size));

	if (target_mmc_device())
	{
		erase_unit_sz = mmc_get_eraseunit_size();
		dprintf(SPEW, "erase_unit_sz:0x%x\n", erase_unit_sz);

		blk_addr = addr / block_size;
		blk_count = len / block_size;

		dprintf(INFO, "Erasing card: 0x%x:0x%x\n", blk_addr, blk_count);

		head_unit = blk_addr / erase_unit_sz;
		tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;

		if (tail_unit - head_unit <= 1)
		{
			dprintf(INFO, "SDHCI unit erase not required\n");
			return mmc_zero_out(dev, blk_addr, blk_count);
		}

		unaligned_blks = erase_unit_sz - (blk_addr % erase_unit_sz);

		if (unaligned_blks < erase_unit_sz)
		{
			dprintf(SPEW, "Handling unaligned head blocks\n");
			if (mmc_zero_out(dev, blk_addr, unaligned_blks))
				return 1;

			blk_addr += unaligned_blks;
			blk_count -= unaligned_blks;

			head_unit = blk_addr / erase_unit_sz;
			tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;

			if (tail_unit - head_unit <= 1)
			{
				dprintf(INFO, "SDHCI unit erase not required\n");
				return mmc_zero_out(dev, blk_addr, blk_count);
			}
		}

		unaligned_blks = blk_count % erase_unit_sz;
		blks_to_erase = blk_count - unaligned_blks;

		dprintf(SPEW, "Performing SDHCI erase: 0x%x:0x%x\n", blk_addr,(unsigned int)blks_to_erase);
		if (mmc_sdhci_erase((struct mmc_device *)dev, blk_addr, blks_to_erase * block_size))
		{
			dprintf(CRITICAL, "MMC erase failed\n");
			return 1;
		}

		blk_addr += blks_to_erase;

		if (unaligned_blks)
		{
			dprintf(SPEW, "Handling unaligned tail blocks\n");
			if (mmc_zero_out(dev, blk_addr, unaligned_blks))
				return 1;
		}

	}
	else
	{
		if(ufs_erase((struct ufs_dev *)dev, addr, (len / block_size)))
		{
			dprintf(CRITICAL, "mmc_erase_card: UFS erase failed\n");
			return 1;
		}
	}

	return 0;
}