Esempio n. 1
0
static int init_mmc_for_env(struct mmc *mmc)
{
	if (!mmc) {
		puts("No MMC card found\n");
		return -1;
	}

	if (mmc_init(mmc)) {
		puts("MMC init failed\n");
		return -1;
	}

#ifdef CONFIG_SYS_MMC_ENV_PART
	if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num) {
		int mmc_env_devno = mmc_get_env_devno();

		if (mmc_switch_part(mmc_env_devno,
				    CONFIG_SYS_MMC_ENV_PART)) {
			puts("MMC partition switch failed\n");
			return -1;
		}
	}
#endif

	return 0;
}
Esempio n. 2
0
static void fini_mmc_for_env(struct mmc *mmc)
{
#ifdef CONFIG_SYS_MMC_ENV_PART
	if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num)
		mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV,
				mmc->part_num);
#endif
}
Esempio n. 3
0
static void fini_mmc_for_env(struct mmc *mmc)
{
#ifdef CONFIG_SYS_MMC_ENV_PART
	int mmc_env_devno = mmc_get_env_devno();

	if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num)
		mmc_switch_part(mmc_env_devno,
				mmc->part_num);
#endif
}
static void fini_mmc_for_env(struct mmc *mmc)
{
#ifdef CONFIG_SYS_MMC_ENV_PART
	int dev = CONFIG_SYS_MMC_ENV_DEV;

#ifdef CONFIG_SPL_BUILD
	dev = 0;
#endif
	if (mmc_get_env_part(mmc) != mmc->part_num)
		mmc_switch_part(dev, mmc->part_num);
#endif
}
Esempio n. 5
0
static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
{
	struct udevice *mmc_dev = dev_get_parent(bdev);
	struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
	struct blk_desc *desc = dev_get_uclass_platdata(bdev);

	if (desc->hwpart == hwpart)
		return 0;

	if (mmc->part_config == MMCPART_NOAVAILABLE)
		return -EMEDIUMTYPE;

	return mmc_switch_part(mmc, hwpart);
}
Esempio n. 6
0
static int mmc_access_part(struct dfu_entity *dfu, struct mmc *mmc, int part)
{
	int ret;

	if (part == mmc->part_num)
		return 0;

	ret = mmc_switch_part(dfu->dev_num, part);
	if (ret) {
		error("Cannot switch to partition %d\n", part);
		return ret;
	}
	mmc->part_num = part;

	return 0;
}
Esempio n. 7
0
static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
{
	int ret;
	u8 dev_num;
	int part_num = 0;
	struct mmc_part *part;
	struct blk_desc *mmc_blk;

	part = malloc(sizeof(struct mmc_part));
	if (!part)
		return NULL;

	dev_num = get_boot_device(ops);
	part->mmc = find_mmc_device(dev_num);
	if (!part->mmc) {
		printf("No MMC device at slot %x\n", dev_num);
		return NULL;
	}

	if (mmc_init(part->mmc)) {
		printf("MMC initialization failed\n");
		return NULL;
	}

	ret = mmc_switch_part(part->mmc, part_num);
	if (ret)
		return NULL;

	mmc_blk = mmc_get_blk_desc(part->mmc);
	if (!mmc_blk) {
		printf("Error - failed to obtain block descriptor\n");
		return NULL;
	}

	ret = part_get_info_by_name(mmc_blk, partition, &part->info);
	if (!ret) {
		printf("Can't find partition '%s'\n", partition);
		return NULL;
	}

	part->dev_num = dev_num;
	part->mmc_blk = mmc_blk;

	return part;
}
static int mmc_set_env_part(struct mmc *mmc)
{
	uint part = mmc_get_env_part(mmc);
	int dev = CONFIG_SYS_MMC_ENV_DEV;
	int ret = 0;

#ifdef CONFIG_SPL_BUILD
	dev = 0;
#endif

	if (part != mmc->part_num) {
		ret = mmc_switch_part(dev, part);
		if (ret)
			puts("MMC partition switch failed\n");
	}

	return ret;
}
/*
 * This needs to be called with host claimed
 * @part: GPP partition part ID, should be 1/2/3/4.
 * @addr: GPP write group unit
 */
int mmc_set_user_wp(struct mmc_card *card, unsigned int part,
		unsigned int wpg)
{
	struct mmc_command cmd = {0};
	int err = 0;
	u32 status = 0;

	if (!card)
		return -ENODEV;

	mmc_claim_host(card->host);

	/*
	 * enable WP to partitions
	 * set bit2 of ext_csd[171], permanent write protect
	 */
	err = mmc_switch_bits(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_USER_WP,
			EXT_CSD_PERMANENT_WP, card->ext_csd.generic_cmd6_time,
			true, true);
	if (err) {
		pr_err("%s: enable permanent write protect err %d!\n",
				__func__, err);
		mmc_release_host(card->host);
		return err;
	}

	err = mmc_switch_part(card, part);
	if (err)
		goto switchback;

	cmd.opcode = MMC_SET_WRITE_PROT;
	cmd.arg = wpg * card->ext_csd.wpg_sz;
	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
	if (err) {
		pr_err("%s: failed to set addr 0x%x write protected, err %d\n",
				__func__, cmd.arg, err);
		goto out;
	}

	/* Must check status to be sure of no errors */
	do {
		err = mmc_send_status(card, &status);
		if (err) {
			pr_err("%s: card status get err %d, status 0x%x\n",
					__func__, err, status);
			goto out;
		}
		if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
			break;
		if (mmc_host_is_spi(card->host))
			break;
	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);

	if (mmc_host_is_spi(card->host)) {
		if (status & R1_SPI_ILLEGAL_COMMAND) {
			pr_err("%s: error card status 0x%x\n",
					__func__, status);
			err = -EILSEQ;
			goto out;
		}
	} else {
		if (status & 0xFDFFA000)
			pr_warn("%s: unexpected status %#x after switch",
					__func__, status);
		if (status & R1_SWITCH_ERROR) {
			pr_err("%s: card switch error, status 0x%x\n",
					__func__, status);
			err = -EIO;
			goto out;
		}
		if (status & R1_OUT_OF_RANGE) {
			pr_err("%s: addr out of range, status 0x%x\n",
					__func__, status);
			err = -EINVAL;
		}
	}

out:
	err = mmc_switch_part(card, EXT_CSD_PART_CONFIG_ACC_USER);
	if (err) {
		pr_warn("%s: switch to USER partition failed!\n", __func__);
		WARN_ON(err);
	}

switchback:
	/*
	 * clear bit2 of ext_csd[171], permanent write protect
	 */
	err = mmc_switch_bits(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_USER_WP,
			EXT_CSD_PERMANENT_WP, card->ext_csd.generic_cmd6_time,
			true, false);
	if (err) {
		pr_err("%s: clear write protect err %d!\n",
				__func__, err);
	}

	mmc_release_host(card->host);

	return err;
}
/*
 * @part: GPP partition part number
 * @addr: GPP write group
 */
int mmc_wp_status(struct mmc_card *card, unsigned int part,
		unsigned int addr, u8 *wp_status)
{
	struct mmc_command cmd = {0};
	struct mmc_data data = {0};
	struct mmc_request mrq = {0};
	struct scatterlist sg;
	u32 status = 0;
	int err = 0;
	u8 *rbuf = NULL;

	if (!card)
		return -ENODEV;

	if (!card->ext_csd.gpp_sz[part - EXT_CSD_PART_CONFIG_ACC_GP0]) {
		pr_err("%s: doesn't have GPP%d\n", __func__,
				part - 3);
		return -ENODEV;
	}

	rbuf = kzalloc(8, GFP_KERNEL);
	if (rbuf == NULL) {
		pr_err("%s: no memory\n", __func__);
		return -ENOMEM;
	}

	cmd.opcode = MMC_SEND_WRITE_PROT_TYPE;
	cmd.arg = addr * card->ext_csd.wpg_sz;
	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;

	data.sg = &sg;
	data.sg_len = 1;
	data.blksz = 8;
	data.blocks = 1;
	data.flags = MMC_DATA_READ;
	sg_init_one(data.sg, rbuf, 8);
	mrq.data = &data;
	mrq.cmd = &cmd;

	mmc_claim_host(card->host);

	mmc_set_data_timeout(&data, card);

	err = mmc_switch_part(card, part);
	if (err) {
		mmc_release_host(card->host);
		dev_err(mmc_dev(card->host), "%s: swith error %d\n",
				__func__, err);
		goto out;
	}

	mmc_wait_for_req(card->host, &mrq);
	if (cmd.error) {
		dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
				__func__, cmd.error);
	}
	if (data.error) {
		dev_err(mmc_dev(card->host), "%s: data error %d\n",
				__func__, data.error);
	}

	/* Must check status to be sure of no errors */
	do {
		err = mmc_send_status(card, &status);
		if (err) {
			pr_err("%s: get card status err %d, status 0x%x\n",
					__func__, err, status);
			goto out;
		}
		if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
			break;
		if (mmc_host_is_spi(card->host))
			break;
	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);

	if (mmc_host_is_spi(card->host)) {
		if (status & R1_SPI_ILLEGAL_COMMAND) {
			pr_err("%s: error card status 0x%x\n",
					__func__, status);
			goto out;
		}
	} else {
		if (status & 0xFDFFA000)
			pr_warn("%s: unexpected status %#x after switch",
					__func__, status);
		if (status & R1_SWITCH_ERROR) {
			pr_err("%s: card switch error, status 0x%x\n",
					__func__, status);
		}
		if (status & R1_OUT_OF_RANGE) {
			pr_err("%s: addr out of range, status 0x%x\n",
					__func__, status);
			goto out;
		}
	}

	mmc_switch_part(card, EXT_CSD_PART_CONFIG_ACC_USER);

	mmc_release_host(card->host);

	sg_copy_from_buffer(data.sg, 1, rbuf, 8);

	/*
	 * the first write protect group type is in the last two
	 * bits in the last byte read from the device.
	 */
	*wp_status = rbuf[7] & 0x3;

	kfree(rbuf);

	return 0;
out:
	kfree(rbuf);

	return -EPERM;
}
Esempio n. 11
0
static int mmc_burn_image(size_t image_size)
{
	struct mmc	*mmc;
	lbaint_t	start_lba;
	lbaint_t	blk_count;
	ulong		blk_written;
	int		err;
	const u8	mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
#ifdef CONFIG_BLK
	struct blk_desc *blk_desc;
#endif
	mmc = find_mmc_device(mmc_dev_num);
	if (!mmc) {
		printf("No SD/MMC/eMMC card found\n");
		return -ENOMEDIUM;
	}

	err = mmc_init(mmc);
	if (err) {
		printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
		       mmc_dev_num);
		return err;
	}

#ifdef CONFIG_SYS_MMC_ENV_PART
	if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART) {
		err = mmc_switch_part(mmc_dev_num, CONFIG_SYS_MMC_ENV_PART);
		if (err) {
			printf("MMC partition switch failed\n");
			return err;
		}
	}
#endif

	/* SD reserves LBA-0 for MBR and boots from LBA-1,
	 * MMC/eMMC boots from LBA-0
	 */
	start_lba = IS_SD(mmc) ? 1 : 0;
#ifdef CONFIG_BLK
	blk_count = image_size / mmc->write_bl_len;
	if (image_size % mmc->write_bl_len)
		blk_count += 1;

	blk_desc = mmc_get_blk_desc(mmc);
	if (!blk_desc) {
		printf("Error - failed to obtain block descriptor\n");
		return -ENODEV;
	}
	blk_written = blk_dwrite(blk_desc, start_lba, blk_count,
				 (void *)get_load_addr());
#else
	blk_count = image_size / mmc->block_dev.blksz;
	if (image_size % mmc->block_dev.blksz)
		blk_count += 1;

	blk_written = mmc->block_dev.block_write(mmc_dev_num,
						 start_lba, blk_count,
						 (void *)get_load_addr());
#endif /* CONFIG_BLK */
	if (blk_written != blk_count) {
		printf("Error - written %#lx blocks\n", blk_written);
		return -ENOSPC;
	}
	printf("Done!\n");

#ifdef CONFIG_SYS_MMC_ENV_PART
	if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART)
		mmc_switch_part(mmc_dev_num, mmc->part_num);
#endif

	return 0;
}
/*******************************************************************************
Reset environment variables.
********************************************************************************/
int resetenv_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
#if defined(CONFIG_ENV_IS_IN_FLASH )
	ulong	stop_addr;
	ulong	start_addr;
#elif defined(CONFIG_ENV_IS_IN_MMC)
	lbaint_t	start_lba;
	lbaint_t	blk_count;
	ulong		blk_erased;
	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
	struct mmc	*mmc;
	int			err;
#endif

#if defined(CONFIG_ENV_IS_IN_NAND)
	size_t env_offset = CONFIG_ENV_OFFSET;
	nand_info_t *nand = &nand_info[0];

	printf("Erasing 0x%x - 0x%x:",env_offset, env_offset + CONFIG_ENV_RANGE);
	nand_erase(nand, env_offset, CONFIG_ENV_RANGE);
	puts ("[Done]\n");

#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH)
	u32 sector = 1;

	if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
		sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
		if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
			sector++;
	}

#ifdef CONFIG_SPI_FLASH_PROTECTION
	printf("Unprotecting flash:");
	spi_flash_protect(flash, 0);
	printf("\t\t[Done]\n");
#endif

	printf("Erasing 0x%x - 0x%x:",CONFIG_ENV_OFFSET, CONFIG_ENV_OFFSET + sector * CONFIG_ENV_SECT_SIZE);
	if(!flash) {
		flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
								CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
		if (!flash) {
			printf("Failed to probe SPI Flash\n");
			set_default_env("!spi_flash_probe() failed");
			return 0;
		}
	}
	if (spi_flash_erase(flash, CONFIG_ENV_OFFSET, sector * CONFIG_ENV_SECT_SIZE))
		return 1;
	puts("\t[Done]\n");

#ifdef CONFIG_SPI_FLASH_PROTECTION
	printf("Protecting flash:");
	spi_flash_protect(flash, 1);
	printf("\t\t[Done]\n");
#endif

#elif defined(CONFIG_ENV_IS_IN_FLASH )
	start_addr = CONFIG_ENV_ADDR;
	stop_addr = start_addr + CONFIG_ENV_SIZE - 1;

	printf("Erasing sector 0x%x:",CONFIG_ENV_OFFSET);
	flash_sect_protect (0, start_addr, stop_addr);

	flash_sect_erase (start_addr, stop_addr);

	flash_sect_protect (1, start_addr, stop_addr);
	printf("\t[Done]\n");

#elif defined(CONFIG_ENV_IS_IN_MMC)

	start_lba = CONFIG_ENV_ADDR / CONFIG_ENV_SECT_SIZE;
	blk_count = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;

	mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
	if (!mmc) {
		printf("No MMC card found\n");
		return 1;
	}

	if (mmc_init(mmc)) {
		printf("MMC(%d) init failed\n", CONFIG_SYS_MMC_ENV_DEV);
		return 1;
	}

#ifdef CONFIG_SYS_MMC_ENV_PART /* Valid for MMC/eMMC only - switch to ENV partition */
	if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num) {
		if (mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV, CONFIG_SYS_MMC_ENV_PART)) {
			printf("MMC partition switch failed\n");
			return 1;
		}
	}
#endif

	printf("Erasing 0x"LBAF" blocks starting at sector 0x"LBAF" :", blk_count, start_lba);
	/* For some unknown reason the mmc_berase() fails with timeout if called
	   before any futher write to MMC/SD (for instance, right after u-boot bring up).
	   However the mmc_bwrite() always succeds.
	   Writing zeroes into SD/MMC blocks is similar operation as doing so to IDE/SATA
	   disk and therefore can be used for erasing the imformation stored on the media.
	   blk_erased = mmc_berase(CONFIG_SYS_MMC_ENV_DEV, start_lba, blk_count);
	*/
	memset(buf, 0, CONFIG_ENV_SIZE);
	blk_erased = mmc_bwrite(CONFIG_SYS_MMC_ENV_DEV, start_lba, blk_count, buf);
	if (blk_erased != blk_count) {
		printf("\t[FAIL] - erased %#lx blocks\n", blk_erased);
		err = 1;
	} else {
		printf("\t[Done]\n");
		err = 0;
	}

#ifdef CONFIG_SYS_MMC_ENV_PART /* Valid for MMC/eMMC only - restore current partition */
	if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num)
		mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV, mmc->part_num);
#endif

	if (err)
		return err;

#endif
	printf("Warning: Default Environment Variables will take effect Only after RESET\n");
	return 0;
}
Esempio n. 13
0
int spl_mmc_load_image(void)
{
	struct mmc *mmc;
	int err;
	u32 boot_mode;

	mmc_initialize(gd->bd);
	/* We register only one device. So, the dev id is always 0 */
	mmc = find_mmc_device(0);
	if (!mmc) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
		puts("spl: mmc device not found!!\n");
#endif
		return -1;
	}

	err = mmc_init(mmc);
	if (err) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
		printf("spl: mmc init failed: err - %d\n", err);
#endif
		return -1;
	}

	boot_mode = spl_boot_mode();
	if (boot_mode == MMCSD_MODE_RAW) {
		debug("boot mode - RAW\n");
#ifdef CONFIG_SPL_OS_BOOT
		if (spl_start_uboot() || mmc_load_image_raw_os(mmc))
#endif
		err = mmc_load_image_raw(mmc,
			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
#ifdef CONFIG_SPL_FAT_SUPPORT
	} else if (boot_mode == MMCSD_MODE_FAT) {
		debug("boot mode - FAT\n");
#ifdef CONFIG_SPL_OS_BOOT
		if (spl_start_uboot() || spl_load_image_fat_os(&mmc->block_dev,
								CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION))
#endif
		err = spl_load_image_fat(&mmc->block_dev,
					CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION,
					CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME);
#endif
#ifdef CONFIG_SUPPORT_EMMC_BOOT
	} else if (boot_mode == MMCSD_MODE_EMMCBOOT) {
		/*
		 * We need to check what the partition is configured to.
		 * 1 and 2 match up to boot0 / boot1 and 7 is user data
		 * which is the first physical partition (0).
		 */
		int part = (mmc->part_config >> 3) & PART_ACCESS_MASK;

		if (part == 7)
			part = 0;

		if (mmc_switch_part(0, part)) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
			puts("MMC partition switch failed\n");
#endif
			return -1;
		}
#ifdef CONFIG_SPL_OS_BOOT
		if (spl_start_uboot() || mmc_load_image_raw_os(mmc))
#endif
		err = mmc_load_image_raw(mmc,
			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
#endif
	} else {